1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_disk.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,238 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32\sfile\sf_disk.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "sf_std.h"
1.22 +
1.23 +#if defined(_LOCKABLE_MEDIA)
1.24 +
1.25 +LOCAL_C TInt DelayedWriter(TAny *aPtr);
1.26 +LOCAL_C void DelayedWriterL(const TDelayedWriter *aDW);
1.27 +
1.28 +
1.29 +EXPORT_C void WriteToDisk(const TDesC& aFileName, const TDesC8& aBuf)
1.30 +//
1.31 +// Launches as separate thread that writes the contents of the pbus pswd
1.32 +// store to disk. It is possible that this function will be called again
1.33 +// before the thread has finished writing. In that case, a new thread
1.34 +// will be created and it will wait on the global DelayedWriteSem semaphore.
1.35 +//
1.36 + {
1.37 + static TInt32 ctr = 0x00000000; // ctr to create unique thd names
1.38 +
1.39 + __PRINT(_L("WriteToDisk"));
1.40 + __PRINT1(_L("wtd:afn%S"), &aFileName);
1.41 +
1.42 + TDelayedWriterInit dwi;
1.43 + dwi.iFileName = &aFileName;
1.44 + dwi.iData = &aBuf;
1.45 +
1.46 + // Create local semaphore this thread can wait on until the child thread has
1.47 + // made copies of the file name and the store data.
1.48 +
1.49 + __PRINT(_L("wtd:cr sem"));
1.50 + TBuf<3 + 8> semName;
1.51 + semName.Format(_L("dws%08x"), ctr++);
1.52 + dwi.iSemName = &semName;
1.53 + RSemaphore svrSem;
1.54 + if (svrSem.CreateGlobal(semName, 0) != KErrNone)
1.55 + return;
1.56 +
1.57 + // Spin off a thread with a unique name.
1.58 +
1.59 + __PRINT(_L("wtd:cr thd"));
1.60 + TName nm;
1.61 + nm.Format(_L("dw%08x"), ctr);
1.62 + RThread t;
1.63 + TInt hminsz = Max(KHeapMinSize, aFileName.Length() + aBuf.Length() + 1024);
1.64 + if (t.Create(
1.65 + nm, DelayedWriter, KDefaultStackSize,
1.66 + hminsz /* aHeapMinSize */, hminsz /* aHeapMaxSize */, &dwi) == KErrNone)
1.67 + {
1.68 + __PRINT(_L("wtd:set pri"));
1.69 + t.SetPriority(EPriorityMuchLess); // run as low priority task
1.70 + __PRINT(_L("wtd:res"));
1.71 + t.Resume();
1.72 + __PRINT(_L("wtd:wait"));
1.73 + svrSem.Wait();
1.74 + __PRINT(_L("wtd:cls thd"));
1.75 + t.Close(); // get rid of our handle
1.76 + }
1.77 +
1.78 + __PRINT(_L("wtd:cls sem"));
1.79 + svrSem.Close();
1.80 + }
1.81 +
1.82 +
1.83 +LOCAL_D TInt DelayedWriter(TAny *aPtr)
1.84 +//
1.85 +// Main thread function for thread that is spun off from WriteToDisk().
1.86 +// After local copies of the data have been allocated (or failed), tell
1.87 +// the server to continue.
1.88 +//
1.89 + {
1.90 + __PRINT(_L("DelayedWriter"));
1.91 +
1.92 + User::SetCritical(User::ESystemCritical);
1.93 +
1.94 + TInt r;
1.95 +
1.96 + TDelayedWriterInit *dwi = (TDelayedWriterInit *) aPtr;
1.97 + RSemaphore svrSem; // signal svr when data copied
1.98 + CTrapCleanup *th = NULL; // thread trap handler
1.99 + TDelayedWriter *dw = NULL; // thread copy of data
1.100 + RSemaphore queueSem; // queued delayed write threads
1.101 +
1.102 + // Allocate a trap handler.
1.103 + __PRINT(_L("dlw:alc tp"));
1.104 + if ((th = CTrapCleanup::New()) == NULL)
1.105 + {
1.106 + r = KErrNoMemory;
1.107 + goto cleanup;
1.108 + }
1.109 +
1.110 + // Make copies of the filename and store data.
1.111 + __PRINT(_L("dlw:cp dat"));
1.112 + TRAP(r, dw = TDelayedWriter::NewL(dwi));
1.113 + if (r != KErrNone)
1.114 + goto cleanup;
1.115 +
1.116 + // Tell file server made local copies of data and so can continue.
1.117 + __PRINT(_L("dlw:sg cp dat"));
1.118 + if ((r = svrSem.OpenGlobal(*dwi->iSemName)) != KErrNone)
1.119 + goto cleanup;
1.120 + svrSem.Signal();
1.121 +
1.122 + // Wait for the other store threads to finish.
1.123 + __PRINT(_L("dlw:wait"));
1.124 + if ((r = queueSem.OpenGlobal(_L("dwsem"))) != KErrNone)
1.125 + goto cleanup;
1.126 + queueSem.Wait();
1.127 +
1.128 + // Write the data and signal the global semaphore so follow up threads can run.
1.129 + __PRINT(_L("dlw:wrt"));
1.130 + TRAP(r, DelayedWriterL(dw));
1.131 + __PRINT1(_L("dlw:wrt r = %d"), r);
1.132 + queueSem.Signal();
1.133 +
1.134 +cleanup: // free any opened resources
1.135 + __PRINT(_L("dlw:cln"));
1.136 + svrSem.Close();
1.137 + delete th;
1.138 + delete dw;
1.139 + queueSem.Close();
1.140 +
1.141 + return KErrNone;
1.142 + }
1.143 +
1.144 +
1.145 +LOCAL_D void DelayedWriterL(const TDelayedWriter *aDW)
1.146 +//
1.147 +// Replace any existing store file; write data and set file as hidden and system.
1.148 +//
1.149 + {
1.150 + __PRINT(_L("DelayedWriterL"));
1.151 +
1.152 + RFs fs; // connect to the file server
1.153 + CleanupClosePushL(fs);
1.154 + User::LeaveIfError(fs.Connect());
1.155 +
1.156 + RFile f; // replace any existing file
1.157 + CleanupClosePushL(f);
1.158 +
1.159 + __PRINT(_L("dlw: opn"));
1.160 +
1.161 + // Create the directory if it doesn't already exist
1.162 + TInt r;
1.163 + r = fs.MkDirAll(*aDW->iFileName);
1.164 + if (r != KErrNone && r != KErrAlreadyExists)
1.165 + {
1.166 + __PRINT(_L("dlw: MkDirAll err"));
1.167 + User::Leave(r);
1.168 + }
1.169 +
1.170 + User::LeaveIfError(f.Replace(fs, *aDW->iFileName, EFileShareExclusive | EFileStream | EFileWrite));
1.171 + __PRINT(_L("dlw: wrt"));
1.172 + User::LeaveIfError(f.Write(*aDW->iData));
1.173 + __PRINT(_L("dlw: sat"));
1.174 +#ifndef __WINS__ // cannot replace hidden | system file in WINS.
1.175 + User::LeaveIfError(f.SetAtt(KEntryAttHidden | KEntryAttSystem, 0x00000000));
1.176 +#endif
1.177 + __PRINT(_L("dlw: dst"));
1.178 + CleanupStack::PopAndDestroy(2); // f, fs
1.179 + }
1.180 +
1.181 +//
1.182 +// TDelayedWriter
1.183 +//
1.184 +
1.185 +TDelayedWriter *TDelayedWriter::NewL(const TDelayedWriterInit *dwi)
1.186 +//
1.187 +// static
1.188 +// Allocates a TDelayedWriter structure on the thread's heap that is used to
1.189 +// persist the data that the writer thread will need during its lifetime.
1.190 +//
1.191 + {
1.192 + __PRINT(_L("TDelayedWriter::NewL"));
1.193 +
1.194 + TDelayedWriter *self = new(ELeave) TDelayedWriter();
1.195 + CleanupStack::PushL(self);
1.196 + self->ConstructL(dwi);
1.197 + CleanupStack::Pop(); // self
1.198 + return self;
1.199 + }
1.200 +
1.201 +
1.202 +TDelayedWriter::TDelayedWriter()
1.203 + {
1.204 + __PRINT(_L("TDelayedWriter::TDelayedWriter"));
1.205 +
1.206 + // empty.
1.207 + }
1.208 +
1.209 +
1.210 +void TDelayedWriter::ConstructL(const TDelayedWriterInit *dwi)
1.211 +//
1.212 +// 2y initialisation. Makes own copy of filename and data.
1.213 +// Fields are not popped onto CleanupStack because will be deleted in dtor
1.214 +//
1.215 + {
1.216 + __PRINT(_L("TDelayedWriter::ConstructL"));
1.217 +
1.218 + iFileName = dwi->iFileName->AllocL();
1.219 + iData = dwi->iData->AllocL();
1.220 + }
1.221 +
1.222 +TDelayedWriter::~TDelayedWriter()
1.223 +//
1.224 +// dtor - frees filename and store data that was allocated in ConstructL().
1.225 +//
1.226 + {
1.227 + __PRINT(_L("TDelayedWriter::~TDelayedWriter"));
1.228 +
1.229 + delete iFileName; // alloc in ConstructL()
1.230 + delete iData; // alloc in server
1.231 + }
1.232 +
1.233 +#else
1.234 +
1.235 +EXPORT_C void WriteToDisk(const TDesC& /*aFileName*/, const TDesC8& /*aBuf*/)
1.236 +//
1.237 +//
1.238 +//
1.239 + {}
1.240 +
1.241 +#endif