userlibandfileserver/fileserver/sfile/sf_disk.cpp
author Mike Kinghan <mikek@symbian.org>
Tue, 16 Nov 2010 14:39:21 +0000
branchGCC_SURGE
changeset 303 9b85206a602c
parent 0 a41df078684a
permissions -rw-r--r--
We need a way to pass flags to rombuilds in Raptor via extension flm interfaces, so that the CPP pass of the rom input files can be informed what toolchain we are building with and conditionally include or exclude files depending on whether the toolchain could build them.

// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32\sfile\sf_disk.cpp
// 
//

#include "sf_std.h"

#if defined(_LOCKABLE_MEDIA)

LOCAL_C TInt DelayedWriter(TAny *aPtr);
LOCAL_C void DelayedWriterL(const TDelayedWriter *aDW);


EXPORT_C void WriteToDisk(const TDesC& aFileName, const TDesC8& aBuf)
// 
// Launches as separate thread that writes the contents of the pbus pswd
// store to disk.  It is possible that this function will be called again
// before the thread has finished writing.  In that case, a new thread
// will be created and it will wait on the global DelayedWriteSem semaphore.
// 
	{
	static TInt32 ctr = 0x00000000;				// ctr to create unique thd names
	
	__PRINT(_L("WriteToDisk"));
	__PRINT1(_L("wtd:afn%S"), &aFileName);

	TDelayedWriterInit dwi;
	dwi.iFileName = &aFileName;
	dwi.iData = &aBuf;

	// Create local semaphore this thread can wait on until the child thread has
	// made copies of the file name and the store data.

	__PRINT(_L("wtd:cr sem"));
	TBuf<3 + 8> semName;
	semName.Format(_L("dws%08x"), ctr++);
	dwi.iSemName = &semName;
	RSemaphore svrSem;
	if (svrSem.CreateGlobal(semName, 0) != KErrNone)
		return;

	// Spin off a thread with a unique name.

	__PRINT(_L("wtd:cr thd"));
	TName nm;
	nm.Format(_L("dw%08x"), ctr);
	RThread t;
	TInt hminsz = Max(KHeapMinSize, aFileName.Length() + aBuf.Length() + 1024);
	if (t.Create(
		nm, DelayedWriter, KDefaultStackSize,
		hminsz /* aHeapMinSize */, hminsz /* aHeapMaxSize */, &dwi) == KErrNone)
		{
		__PRINT(_L("wtd:set pri"));
		t.SetPriority(EPriorityMuchLess);		// run as low priority task
		__PRINT(_L("wtd:res"));
		t.Resume();
		__PRINT(_L("wtd:wait"));
		svrSem.Wait();
		__PRINT(_L("wtd:cls thd"));
		t.Close();								// get rid of our handle
		}
	
	__PRINT(_L("wtd:cls sem"));
	svrSem.Close();
	}


LOCAL_D TInt DelayedWriter(TAny *aPtr)
//
// Main thread function for thread that is spun off from WriteToDisk().
// After local copies of the data have been allocated (or failed), tell
// the server to continue.
// 
	{
	__PRINT(_L("DelayedWriter"));

	User::SetCritical(User::ESystemCritical);

	TInt r;

	TDelayedWriterInit *dwi = (TDelayedWriterInit *) aPtr;
	RSemaphore svrSem;							// signal svr when data copied
	CTrapCleanup *th = NULL;					// thread trap handler
	TDelayedWriter *dw = NULL;					// thread copy of data
	RSemaphore queueSem;						// queued delayed write threads

	// Allocate a trap handler.
	__PRINT(_L("dlw:alc tp"));
	if ((th = CTrapCleanup::New()) == NULL)
		{
		r = KErrNoMemory;
		goto cleanup;
		}

	// Make copies of the filename and store data.
	__PRINT(_L("dlw:cp dat"));
	TRAP(r, dw = TDelayedWriter::NewL(dwi));
	if (r != KErrNone)
		goto cleanup;
	
	// Tell file server made local copies of data and so can continue.
	__PRINT(_L("dlw:sg cp dat"));
	if ((r = svrSem.OpenGlobal(*dwi->iSemName)) != KErrNone)
		goto cleanup;
	svrSem.Signal();

	// Wait for the other store threads to finish.
	__PRINT(_L("dlw:wait"));
	if ((r = queueSem.OpenGlobal(_L("dwsem"))) != KErrNone)
		goto cleanup;
	queueSem.Wait();

	// Write the data and signal the global semaphore so follow up threads can run.
	__PRINT(_L("dlw:wrt"));
	TRAP(r, DelayedWriterL(dw));
	__PRINT1(_L("dlw:wrt r = %d"), r);
	queueSem.Signal();

cleanup:										// free any opened resources
	__PRINT(_L("dlw:cln"));
	svrSem.Close();
	delete th;
	delete dw;
	queueSem.Close();

	return KErrNone;
	}


LOCAL_D void DelayedWriterL(const TDelayedWriter *aDW)
//
// Replace any existing store file; write data and set file as hidden and system.
//
	{
	__PRINT(_L("DelayedWriterL"));

	RFs fs;										// connect to the file server
	CleanupClosePushL(fs);
	User::LeaveIfError(fs.Connect());

	RFile f;									// replace any existing file
	CleanupClosePushL(f);

	__PRINT(_L("dlw: opn"));

	// Create the directory if it doesn't already exist
	TInt r;
	r = fs.MkDirAll(*aDW->iFileName);
	if (r != KErrNone && r != KErrAlreadyExists)
		{
		__PRINT(_L("dlw: MkDirAll err"));
		User::Leave(r);
		}

	User::LeaveIfError(f.Replace(fs, *aDW->iFileName, EFileShareExclusive | EFileStream | EFileWrite));
	__PRINT(_L("dlw: wrt"));
	User::LeaveIfError(f.Write(*aDW->iData));
	__PRINT(_L("dlw: sat"));
#ifndef __WINS__								// cannot replace hidden | system file in WINS.
	User::LeaveIfError(f.SetAtt(KEntryAttHidden | KEntryAttSystem, 0x00000000));
#endif
	__PRINT(_L("dlw: dst"));
	CleanupStack::PopAndDestroy(2);				// f, fs
	}

//
// TDelayedWriter
// 

TDelayedWriter *TDelayedWriter::NewL(const TDelayedWriterInit *dwi)
//
// static
// Allocates a TDelayedWriter structure on the thread's heap that is used to
// persist the data that the writer thread will need during its lifetime.
// 
	{
	__PRINT(_L("TDelayedWriter::NewL"));

	TDelayedWriter *self = new(ELeave) TDelayedWriter();
	CleanupStack::PushL(self);
	self->ConstructL(dwi);
	CleanupStack::Pop();						// self
	return self;
	}


TDelayedWriter::TDelayedWriter()
	{
	__PRINT(_L("TDelayedWriter::TDelayedWriter"));

	// empty.
	}


void TDelayedWriter::ConstructL(const TDelayedWriterInit *dwi)
//
// 2y initialisation.  Makes own copy of filename and data.
// Fields are not popped onto CleanupStack because will be deleted in dtor
// 
	{
	__PRINT(_L("TDelayedWriter::ConstructL"));

	iFileName = dwi->iFileName->AllocL();
	iData = dwi->iData->AllocL();
	}

TDelayedWriter::~TDelayedWriter()
//
// dtor - frees filename and store data that was allocated in ConstructL().
//
	{
	__PRINT(_L("TDelayedWriter::~TDelayedWriter"));

	delete iFileName;							// alloc in ConstructL()
	delete iData;								// alloc in server
	}

#else

EXPORT_C void WriteToDisk(const TDesC& /*aFileName*/, const TDesC8& /*aBuf*/)
//
//
//
	{}

#endif