persistentstorage/dbms/sdbms/SD_SRV.CPP
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // DBMS server implementation
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "SD_STD.H"
       
    19 #include "Sd_PlatDep.h"
       
    20 
       
    21 using namespace DBSC;
       
    22 
       
    23 //CDbmsActiveScheduler class just exposes the access to 
       
    24 //CActiveScheduler::Level() method, which is needed to 
       
    25 //make a decision when to call CDbmsActiveScheduler::Stop().
       
    26 class CDbmsActiveScheduler : public CActiveScheduler
       
    27 	{
       
    28 public:
       
    29 	inline TInt Level() const
       
    30 		{
       
    31 		return CActiveScheduler::Level();
       
    32 		}
       
    33 	};
       
    34 
       
    35 ///////////////////////
       
    36 // Class CDbsServer
       
    37 inline CDbsServer::CDbsServer() :
       
    38 	CServer2(0, ESharableSessions), 
       
    39 	iSources(iCache),
       
    40 	iDbPropsFactory(iFs),
       
    41 	iDriveSpaceCol(iFs)
       
    42 	{
       
    43 	DbgPrint1(_L("###CDbsServer::CDbsServer(), Server ProcID=%d\n"), RDbProcess().Id());
       
    44 	}
       
    45 
       
    46 //"iCache.Hold(this,KDbsExitDelay)" statement will put CDbsServer instance in the cache, 
       
    47 //which ensures that CDbsServer instance will be automatically destroyed if nobody
       
    48 //uses it next KDbsExitDelay microseconds.
       
    49 CDbsServer* CDbsServer::NewL()
       
    50 	{
       
    51 	DbgPrint1(_L("###CDbsServer::NewL(), Server ProcId=%d\n"), RDbProcess().Id());
       
    52 	CDbsServer* self= new (ELeave) CDbsServer;
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL();
       
    55 	CleanupStack::Pop(self);
       
    56 	self->iCache.Hold(self, KDbsExitDelay);		// the last thing we do here
       
    57 	//Intentional behaviour, resources freed after timeout only
       
    58 	//coverity[use_after_free]
       
    59 	return self;
       
    60 	}
       
    61 
       
    62 //
       
    63 // 2nd phase construction - ensure the timer and server objects are running
       
    64 //
       
    65 void CDbsServer::ConstructL()
       
    66 	{
       
    67 	DbgPrint1(_L("###CDbsServer::ConstructL(), Server ProcId=%d\n"), RDbProcess().Id());
       
    68 	__LEAVE_IF_ERROR(Dll::SetTls(this));
       
    69 	StartL(KDbsServerName);
       
    70 	__LEAVE_IF_ERROR(iFs.Connect());
       
    71 	iDbPropsFactory.OpenL();
       
    72 	//EDriveZ - Symbian OS ROM drive !?!?
       
    73 	iDbPropsFactory.GetPrivatePathL(EDriveZ, iFileName);
       
    74 	iPolicyProxy = CPolicyProxy::NewL(iFs,iFileName);
       
    75 	User::LeaveIfError(iCache.Open(ECacheSize, ETrue));	// create a timed cache
       
    76 	}
       
    77 
       
    78 //
       
    79 // Invoked via cache entry expiry (or cleanup)
       
    80 //
       
    81 CDbsServer::~CDbsServer()
       
    82 	{
       
    83 	DbgPrint1(_L("###CDbsServer::~CDbsServer(), Server ProcId=%d\n"), RDbProcess().Id());
       
    84 	iDriveSpaceCol.Close();
       
    85 	delete iPolicyProxy;
       
    86 	iDbPropsFactory.Close();
       
    87 	iCache.Close();
       
    88 	iSources.Close();
       
    89 	iFs.Close();
       
    90 	//Stop the scheduler if the nesting level > 0.
       
    91 	//Sometime it happens that more than one thread tries to run the server and you will have
       
    92 	//CDbmsActiveScheduler::Install() called multiple times. But you have to stop the 
       
    93 	//scheduler only once!
       
    94 	CDbmsActiveScheduler* scheduler = static_cast <CDbmsActiveScheduler*> (CActiveScheduler::Current());
       
    95 	if(scheduler->Level() > 0)
       
    96 		{
       
    97 		DbgPrint2(_L("###CDbsServer::~CDbsServer(), stop the scheduler, Server ProcId=%d, scheduler=%x\n"), RDbProcess().Id(), (TInt)scheduler);
       
    98 		CDbmsActiveScheduler::Stop();
       
    99 		}
       
   100 	}
       
   101 
       
   102 //
       
   103 // Creates a new client session. This should really check the version number.
       
   104 //
       
   105 CSession2* CDbsServer::NewSessionL(const TVersion& aVersion,const RMessage2&) const
       
   106 	{
       
   107 	if(!User::QueryVersionSupported(RDbs::Version(), aVersion))
       
   108 		{
       
   109 		__LEAVE(KErrNotSupported);
       
   110 		}
       
   111 	CSession2* session = new (ELeave) CDbsSession;
       
   112 	iCache.Release(*this);
       
   113 	return session;
       
   114 	}
       
   115 
       
   116 //
       
   117 // Returns the instance of the server
       
   118 //
       
   119 CDbsServer* CDbsServer::Instance()
       
   120 	{
       
   121 	return (CDbsServer*)Dll::Tls();
       
   122 	}
       
   123 
       
   124 //
       
   125 // initiates exit if the last client is closing
       
   126 //
       
   127 void CDbsServer::RemoveSession()
       
   128 	{
       
   129 	iSessionIter.SetToFirst();
       
   130 	iSessionIter++;
       
   131 	if(iSessionIter++ == 0)
       
   132 		{
       
   133 		iCache.Hold(this, KDbsExitDelay);
       
   134 		}
       
   135 	}
       
   136 
       
   137 //
       
   138 // Performs all server initialisation, in particular creation of the
       
   139 // scheduler and server.
       
   140 // Noting has to be leaved in the cleanup stack!
       
   141 // Both: DBMS server and the active scheduler will be destroyed
       
   142 // later. The active scheduler - in CDbsServer destructor.
       
   143 // CDbsServer instance - by iCache instance (RDbCache).
       
   144 static void CreateServerL()
       
   145 	{
       
   146 	DbgPrint1(_L("###DBMS-CreateServerL(), Server ProcId=%d\n"), RDbProcess().Id());
       
   147 	// naming the server thread after the server helps to debug panics
       
   148 	User::LeaveIfError(User::RenameThread(KDbsServerName));
       
   149 	// ensure the server thread has a handle on EDBMS.DLL
       
   150 	LoadDbmsLibraryL();
       
   151 
       
   152 	// create and install the active scheduler we need
       
   153 	CDbmsActiveScheduler* scheduler = new (ELeave) CDbmsActiveScheduler;
       
   154 	CleanupStack::PushL(scheduler);
       
   155 	CDbmsActiveScheduler::Install(scheduler);
       
   156 
       
   157 	// create the server
       
   158 	(void)CDbsServer::NewL();
       
   159 
       
   160 	CleanupStack::Pop(scheduler);
       
   161 
       
   162 	// Initialisation complete, now signal the client
       
   163 	RDbProcess::Rendezvous(KErrNone);
       
   164 	}
       
   165 
       
   166 //
       
   167 // Performs all server initialisation, in particular creation of the
       
   168 // scheduler and server and then run the scheduler
       
   169 //
       
   170 static void RunServerL()
       
   171 	{
       
   172 	DbgPrint1(_L("###DBMS-RunServerL(), Server ProcId=%d\n"), RDbProcess().Id());
       
   173 	::CreateServerL();
       
   174 	//After successfull creation CreateServerL() call leaves the active scheduler instance
       
   175 	//and the DBMS server instance in the heap - they will be destroyed later.
       
   176 	__UHEAP_MARK;
       
   177 	//Start the scheduler. The execution control is transferred to the curent
       
   178 	//active scheduler. The statement after "CDbmsActiveScheduler::Start();" will
       
   179 	//be reached after the stop of active scheduler.
       
   180 	CDbmsActiveScheduler::Start();
       
   181 	__UHEAP_MARKEND;
       
   182 	}
       
   183 
       
   184 //
       
   185 // Server process entry-point
       
   186 //
       
   187 EXPORT_C TInt Dbs::Run()
       
   188 	{
       
   189 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
   190 	TInt err = KErrNoMemory;
       
   191 	if(cleanup)
       
   192 		{
       
   193 		TRAP(err, ::RunServerL());
       
   194 		delete cleanup;
       
   195 		}
       
   196 	DbgPrint2(_L("###Dbs::Run(), end, Server ProcId=%d, err=%d\n"), RDbProcess().Id(), err);
       
   197 	return err;
       
   198 	}
       
   199 	
       
   200 ///////////////////////
       
   201 // Client called code
       
   202 
       
   203 //
       
   204 // Starts the DBMS server
       
   205 //
       
   206 TInt Dbs::Start()
       
   207 	{
       
   208 	DbgPrint1(_L("#-#Dbs::Start(), Client ProcId=%d\n"), RDbProcess().Id());
       
   209 	RDbProcess server;
       
   210 	TInt err = ::CreateDbmsProcess(server);
       
   211 	if(err != KErrNone)
       
   212 		{
       
   213 		DbgPrint2(_L("#-#Dbs::Start(), CreateDbmsProcess, Client ProcId=%d, err=%d\n"), RDbProcess().Id(), err);
       
   214 		return err;
       
   215 		}
       
   216 
       
   217 	TRequestStatus stat;
       
   218 	server.Rendezvous(stat);
       
   219 	if(stat != KRequestPending)
       
   220 		{
       
   221 		server.Kill(0);		// abort startup
       
   222 		}
       
   223 	else
       
   224 		{
       
   225 		server.Resume();	// logon OK - start the server
       
   226 		}
       
   227 	User::WaitForRequest(stat);		// wait for start or death
       
   228 
       
   229 	// we can't use the 'exit reason' if the server panicked as this
       
   230 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
   231 	// from KErrNone
       
   232 	err = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
       
   233 	server.Close();
       
   234 	DbgPrint2(_L("#-#Dbs::Start(), end, Client ProcId=%d, err=%d\n"), RDbProcess().Id(), err);
       
   235 	return err;
       
   236 	}
       
   237