serialserver/c32serialserver/INC/cs_roles.h
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serialserver/c32serialserver/INC/cs_roles.h	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,453 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Defines the classes that describe the two roles in the system: dealer, player
+// 
+//
+
+/**
+ @file
+ @internalComponent 
+*/
+
+#ifndef CS_ROLES_H
+#define CS_ROLES_H
+
+
+#include <cfmsgs.h>
+#include <cfshared.h>
+#include <cfutil.h>
+#include <e32cmn.h>
+#include <c32comm.h>
+#include "CS_STD.H"
+#include "cs_thread.h"
+#include "cs_msgs.h"
+#include <comms-infras/c32startcli.h>
+
+class CC32Player;
+class CC32Dealer;
+class CC32WorkerThread;
+
+class TC32WorkerMainIntroductionRespMsg;
+
+
+
+class CC32WorkerDataGlobals : public CommsFW::CWorkerThreadDataGlobals<TC32WorkerThreadRegister, KMaxWorkerThreadId>
+	{
+public:
+	static CC32WorkerDataGlobals* NewL();
+
+	inline CC32WorkerThread* WorkerThread(TWorkerId aWorker) const;
+	};
+
+NONSHARABLE_CLASS(CCSYInfo) : public CBase
+// Store the information the dealer needs to know about a single CSY.
+// These records are owned by the CC32ThreadManager
+{
+public:
+	static CCSYInfo* NewL(const TDesC8& aCSYName, TInt aThreadNum);
+    static TInt CompareCSYInfo(const CCSYInfo& aFirst,const CCSYInfo& aSecond);	// supplied to search functions
+	~CCSYInfo();
+	inline void SetWorkerId(TInt aThreadNum);
+	inline TInt WorkerId() const;
+	inline const HBufC8* GetCSYName()  const; // guaranteed to be non-null if NewL called.
+	void SetCSYHandle(CSerial* aSerialHandle);
+	inline CSerial* GetCSYHandle() const;
+	void SetPortName(const TDesC& aPortName);
+	TInt SetPortNameSizeToMaximum();
+	inline TPtrC GetPortName() const;
+	inline void IncAccessCount();
+	inline void DecAccessCount();
+	inline TInt AccessCount() const;
+	inline TBool IsLoaded() const;
+	inline void SetLoadState(const TBool aLoaded);
+	inline void SetLoadIndex(TInt aIndex);
+	inline TInt LoadIndex() const;
+		
+private:
+	CCSYInfo(TInt aThreadNum);
+	void ConstructL(const TDesC8& aCSYName);
+private:	
+	HBufC8* iCSYName;	//< Name of file to load CSY. Set by CMI file
+	RBuf iCSYPortPrefix; 	// CSY Internal Name. Set on CSY load by dealer when load success msg recvd from player.
+	                        // needs to accomodate TFullName length strings even though c32 has TPortName type since old C32
+	                        // didn't police length and so existing csys may accept a long portname as its portname.
+	CSerial* iCSYHandle; //< Set when CSY is loaded so we can transpose the index number the client supplies from the above GlobalIndexNumber to the local index inside the thread the CSY lives in.
+	TWorkerId iThreadNum; //< Thread that this CSY will live in
+	TBool iLoaded;			//< State of CSY whether loaded or not
+	TInt iAccessCount;		//< Reference Counting for CSY
+	TInt iLoadIndex;       // valid when csy is loaded. Supports index order of csys for getportInfo(index)
+};
+
+
+
+
+NONSHARABLE_CLASS(CC32ThreadManager) : public CBase
+// Manages the Dealer's primary data structure which it uses to help it forward messages. ThreadManager stores
+// information about the threads not covered by the workerThreadRegister including module name and which CSYs
+// it should contain. ThreadManager also tracks the loading of CSYs.
+// It does not track the running state of threads since the PeerReachable facility of the transport and
+// the WorkerPresent facility of the global data covers this case.
+{
+	friend class CCommSession;
+public:
+	~CC32ThreadManager();
+    static CC32ThreadManager* NewL(CC32Dealer* aDealer);
+	void LoadCMIDataL(const TDesC8& aCSYList);
+	void SetDefaults();
+	
+
+    // START - lookup functions
+	TBool FindThreadByPortPrefix(const TDesC& aPortName, TWorkerId& aWorker) const;
+	TInt MapPortprefixToCSYFileName(const TDesC& aPortName, TDes& aCSYFileName); //< mapping of PortPrefix to CSYFileName
+	TBool FindThreadByFileName(const TDesC8& aCSYFileName, TWorkerId &aWorkerId) const;
+	TBool FindThreadOfActiveCSYByName(const TDesC& aName, TWorkerId& aWorkerId) const;	//< RCommServ::GetPortInfo(aName) version, TWorkerId filled with worker
+	TInt FindThreadByGlobalIndex(TInt aIndex) const; // must use TInt rather than TWorkerID so error code can be returned if necessary
+
+	CSerial* FindSerialObjectByGlobalIndex(const TInt aIndex) const;
+	const HBufC8* GetModuleName(TWorkerId aWorkerId);
+	CSerial* GetSerialObjectFromCSYFileName(const TDesC& aCSYFileName);
+	TInt GetIndexFromPortPrefix(const TDesC& aPortName, TInt& aIndex);
+	CSerial* GetSerialObjectByIndex(TInt aIndex);
+	CSerial* GetSerialL(const TDesC& aPortName);
+	// END - lookup functions
+	
+	TInt IncrementCountOnLoad(const TDesC& aCSYFileName);	 //< increments iAccessCount in CCSYInfo on every Load request
+	TInt DecrementCountOnCSYUnLoad(const TDesC& aCSYFileName);	//< decrements iAccessCount in CCSYInfo on every CSY UnLoad request (can be explicit UnLoadCommModule or implicit unload of CSY on session close)
+	TInt GrowCSYPortNameToMaximumIfNotLoaded(const TDesC& aCSYFileName);  // so that biggest possible string exists before we begin load
+	
+	TWorkerId DefaultThread();
+
+
+	void UpdateThreadManagerOnCSYLoad(const TDesC& aCSYFileName, const TDesC& aPortPrefix, CSerial* aSerial);
+	void UpdateThreadManagerOnCSYUnload(const TDesC8& aCSYFileName8);
+	void UpdateThreadManagerOnCSYLoadFailure(const TDesC& aCSYFilename);	
+	CC32Dealer* Dealer();
+	
+	TInt RequestLoadModule(CommsFW::TWorkerId aWorker);
+	
+    void ProcessModuleLoadFailed(CommsFW::TWorkerId aWorker);
+	void ProcessModuleLoadSuccess(CommsFW::TWorkerId aWorker);
+
+private:
+
+
+	NONSHARABLE_CLASS(CC32ThreadInfo) : public CBase
+		{
+	public:
+		static CC32ThreadInfo* NewL(const TDesC8& aModuleName);
+		static TBool CompareThreadInfo(const CC32ThreadInfo& aFirst,const CC32ThreadInfo& aSecond);
+		void SetModuleNameL(const TDesC8& aModuleName); // set possibly never used
+		inline const HBufC8* ModuleName() const;
+		~CC32ThreadInfo();
+	private:
+		CC32ThreadInfo();
+		void ConstructL(const TDesC8& aModuleName);
+	private:
+		HBufC8*	iModuleName;
+		};
+		
+	
+	NONSHARABLE_CLASS(CC32ParsedIniData) : public CBase
+		{
+		friend class CC32ThreadManager;
+	public:
+		static CC32ParsedIniData* NewL(const TDesC8& aIniData, const TBool aIsDealer);
+		void ConstructL(const TDesC8& aIniData, const TBool aIsDealer);
+		inline TBool IsDefaultThread() const;
+		inline TBool IsPlayer() const; 
+		inline TInt WorkerId() const;
+		inline void SetWorkerId(const TInt aThreadNum);
+		inline TInt NumCSYs() const;
+		~CC32ParsedIniData();
+	private:
+		CC32ParsedIniData();
+		void DigestIniDataL(TDes8& aIniData);
+	private:
+		TBool iIsDefault; // true if CSYList includes an asterix (*).
+		TBool iIsPlayer;  // true if "Role=Player" was found
+		TInt iCMIWorkerId;
+		RArray<TPtrC8> iCSYs; // these point to the data in the supplied iniData
+		};
+
+	NONSHARABLE_CLASS(CCPMLoader) : public CActive
+	// single class to track loading of a CPM
+	// exists from when request is first made to when either Worker communicates with Dealer, or load timer expires
+	// Player loading is a highly rare occurance.
+		{
+	public:
+		static CCPMLoader* NewL();
+		~CCPMLoader();
+		void ConstructL();
+		void RequestModuleLoad(CC32ThreadManager* aThreadMgr, CommsFW::TWorkerId aWorker, const TCFModuleName& aName); 
+	private:
+		void RunL();
+		void DoCancel();
+		CCPMLoader();
+		TCFModuleName iName; // keep a copy of string we send since server may read long after we make request
+		RRsConfigurator iCfgSvr;
+		CC32ThreadManager* iThreadManager; //use thread manager pointer & workerid to update TM if load fails
+		TWorkerId iWorkerId;		
+		};
+
+
+private:
+	CC32ThreadManager(CC32Dealer* aDealer);
+#ifdef __FLOG_ACTIVE
+	void DumpThreadInfoAndCSYLists();
+#endif
+private:   
+	RPointerArray< CCSYInfo > iCSYList; //< list of all csys we know about, loaded or otherwise
+
+	RPointerArray<CC32ThreadInfo> iC32ThreadList; //< Index is the thread number, value is module name of thread, and a few other things
+	TWorkerId iDefaultThreadIndex;	//< For finding where to create unknown CSYS
+	CCPMLoader* iCPMLoader[KMaxWorkerThreadId+1];  // AOs that start load via configurator of new cpm. soaks up response
+	CC32Dealer* iDealer;   			// used for CPMLoader and debug printing
+
+	TInt iNumLoadedModules;  // used to calculate loadIndex for a CSY when CSY first loaded
+};
+
+
+/** 
+@class
+CC32Dealer
+The Dealer is an implementation of the Symbian OS server (CServer2) and as such one of its most 
+important possessions is the list of CSession2's kept by the CServer2. On a conceptual level 
+one can say that the Dealer owns the CCommSessions due to their inherited relationship.
+
+The Dealer thread must be started by the Configurator before any worker threads. The C32
+instance loading it must be the only one having the WorkerId 0 (TC32WorkerThreadPublicInfo::EMainThread).
+The Dealer has two main responsibilities:
+    -# Maintain global data structures, accessible to all Workers to which the Dealer pointer is published 
+    (through the TWorkerMainIntroductionMsg). Mostly the workers will access this data using Dealer access 
+    functions which are thread-safe [AddSubSession() and RemoveSubSession()], taking special measures
+    to guarantee this where needed.
+    -# Manage Worker thread : Registering Workers when they start.
+
+All C32 thread instances can have their own heap if set through CMI file.
+Sometimes it happens that one Worker needs to do 
+something that might cause allocation or freeing on another workers heap, such as inserting a 
+sub-session into a Dealers session. So the Dealer offers a function that can determine whether 
+a different heap is needed (maybe the two workers have different heaps, maybe they share one heap)
+and does the switch.
+
+Sub-sessions are also supported in the form of the CCommSubSession.
+These are owned by the provider container (CC32SubSessionIx) in the CCommSession.
+
+It also has AddSubSession() and RemoveSubSession() methods used by the Player, assuring this 
+happens on the right heap.
+*/
+
+NONSHARABLE_CLASS(CC32Dealer) : public CC32Server
+	{
+	typedef CC32Server inherited;
+public:
+	static CC32Dealer* NewL(CC32WorkerThread* aOwnerThread, const TDesC8& aDealerIniData);
+	~CC32Dealer();
+
+	const TDesC& ServerName() const;
+	void DeleteSession(CCommSession* aSession);
+	TInt SubsessionCountInPlayer(CommsFW::TWorkerId aPeerId);
+	TBool CanShutdown();
+	TBool CanUnbindFromWorker(TWorkerId aWorker);
+	void ProcessShutdownRequest(CommsFW::TCFShutdownType aType);
+	TInt Read(TInt aPos, const RMessagePtr2& aMessage , TDes16& aDes, TInt aOffset);
+	void ProcessFailedPlayerLoad(CommsFW::TWorkerId aWorker);
+	void ShutdownIfReady();
+	
+	inline void SetImmediateShutdownPresent();
+	inline TBool TestImmediateShutdownPresent() const;
+	inline void StartShutdown();
+	inline TBool StartupFailed() const;
+
+
+public:
+	void SendIntroductionToWorker(CommsFW::TWorkerId aWorkerId);
+	void ProcessWorkerIntroductionResponse(const TC32WorkerMainIntroductionRespMsg& aMsg);
+	void DeleteCPMLoader(CommsFW::TWorkerId aWorkerId);	
+
+	void ProcessLoadCommModuleSuccessResponse(const RMessage2& aMessage, CSerial* aSerial);
+	void ProcessLoadCommModuleFailureResponse(const RMessage2& aMessage, TInt aFailReason);	
+	
+	void SessionShutdownComplete();
+	
+	TBool WorkerExists(TWorkerId aId) const;
+	inline TBool WorkerDataGlobalsExist() const;
+    inline CC32WorkerDataGlobals& WorkerDataGlobals() const;
+    
+    void PostMessage(CommsFW::TWorkerId aWorkerId, CommsFW::TCFMessage& aMessage);
+	CC32Dealer* Dealer(CommsFW::TWorkerId aWorkerId) const;
+	CC32Player* Player(CommsFW::TWorkerId aWorkerId) const;
+
+	RAllocator* MaybeSwitchHeap(CommsFW::TWorkerId aForeignWorkerId);
+#ifdef _DEBUG
+ 	void SetFailNextForAllHeaps(TInt aFailNext);
+#endif
+
+	// SubSession container (CC32SubSessionIx) manipulation - used by Player
+	TInt AddSubSession(CCommSubSession* aSubSession, CCommSession* aSession, TInt& aHandle);
+	void RemoveSubSession(TInt aHandle, CCommSession* aSession);
+	TInt FindSubSession(CCommSubSession* aSubSession, CCommSession* aSession, TInt& aHandle);
+	TInt LoadCPMOnLoadCommModule(CommsFW::TWorkerId aWorker);
+	void ProcessParkedRequest();
+	void RemoveParkedRequestsOnSessionClose(CCommSession* aSession);
+	TInt ParkRequest(CCommSession* aSession, const RMessage2& aMessage);
+	CC32ThreadManager* ThreadManager() const
+		{
+		return iThreadManager;
+		}
+	
+protected:
+	CC32Dealer(CC32WorkerThread* aOwnerThread);
+	void ConstructL(const TDesC8& aDealerIniData);
+	
+	void ProcessSubSessions(TWorkerId aPeerId, CCommSession::TSubSessionProcessor aSubSessionProcessor, TAny* aPtr);
+	 
+protected:
+	class TSessionMessagePair
+		{
+	public:
+		TSessionMessagePair(CCommSession* aSession, const RMessage2& aMessage)
+		: iSession(aSession),
+		  iMessage(aMessage)
+	 		{
+	 		}
+	public:
+		CCommSession* iSession;
+		RMessage2 iMessage;
+	 	};
+	typedef RArray<TSessionMessagePair> RParkedRequestArray;
+	RParkedRequestArray iParkedRequests;
+
+private:
+	void FreeWorkerReferences(TWorkerId aWorkerId);
+private:
+	CC32WorkerThread* iOwnerThread;
+	CC32WorkerDataGlobals* iWorkerDataGlobals;
+	CC32ThreadManager* iThreadManager;
+		
+	void AddPendingIntroductionResponse();
+	void RemovePendingIntroductionResponse();
+
+	/** 
+	Incremented when a request to bind to another C32 instance has been received and decremented when a
+	binding is complete.
+	When the reference configurator configuration level have reached the point signifying that all core 
+	components have been configured and this TInt is 0, it is safe to delete data structures used only during
+	startup.
+	*/
+	TInt iPendingIntroResponses;
+
+	/** 
+	ETrue if the Dealer  is in the process of shutting down. Set when optional or graceful shutdown 
+	is received by C32_Main from the RootServer. 
+	*/
+
+	/** 
+	Set ETrue when immediate shutdown is received by the dealer (acting as pitboss) from the RootServer or if 
+	optional/graceful shutdown has been received at some point and the last session is closed. 
+	*/
+	TBool iSessionShutdownComplete;
+
+	/** 
+	Set ETrue when immediate shutdown is received from the RootServer. 
+	*/
+	TBool iImmediateShutdownMark;
+
+	/**
+	If we are unable to start to a reliable state, mark ourselves as such and don't start the server.
+	Such a scenario may be low memory during startup. This allows the phone to at least continue
+	booting and we just sit lame until the next boot.
+	*/
+	TBool iFailedStartup;
+
+	};
+
+
+
+/** 
+@class
+CC32Player
+The main responsibility of the Player is receiving the provider operations/queries 
+from the Dealer and serving them using the protocol plug-ins. 
+It is also responsible for adding/removing sub-sessions from the provider container 
+in the related session object as well as keeping a list of all sub-sessions handled 
+by the Player instance (iSubSessions).
+*/
+NONSHARABLE_CLASS(CC32Player) : public CBase
+	{
+public:
+	static CC32Player* NewL(CC32WorkerThread* aOwnerThread);
+	~CC32Player();
+
+	void ProcessMessageL(const RMessage2& aMsg, CCommSubSession* aSubSession);
+
+	inline CC32WorkerThread& WorkerThread() const;
+	inline TWorkerId WorkerId() const;
+	inline CC32Dealer& CC32DealerByRef() const;
+	
+	typedef RPointerArray<CCommSubSession> TSubSessionContainer;
+	inline TSubSessionContainer& SubSessions();
+
+	TBool CanUnbindFromWorker(TWorkerId aWorker);
+
+	void MaybeSetPlayerShutdownComplete(TBool aForceShutdownNow);
+	void ProcessShutdownRequest(CommsFW::TCFShutdownType aType);
+
+	void CloseSession(CCommSession* aSession);
+
+	void DontCompleteCurrentRequest();
+	void SafeComplete(const RMessagePtr2& aMessage, TInt aCompletionCode);
+	
+	inline const RMessage2& Message() const;
+	void CloseAllOwnedSubSessions(CCommSession* aSession);
+	void ProcessUnLoadCommModuleMsg(CSerial* aSerial);
+
+//
+//	CC32Player functions specific to C32 APIs
+//
+	void LoadCommModule(const RMessage2& aMessage);
+	void CloseCommModule(const RMessage2& aMessage);
+	void NewPortL(const RMessage2& aMessage);
+	TInt ExtractPortNameAndNumber(const RMessagePtr2& aMessage, TDes& aPortName, TUint& aPortNumber, TInt& aLength);	//< duplicate function as in CCommSession
+	void PortInfo(const RMessage2& aMessage, CSerial* aSerialPtr);
+	void PortInfo(const RMessage2& aMessage,const TPortName& aPortName);	//< msg is forwarded to player owning CSY which writes the TSerialInfo back to client using Write() API in player
+	CPort* CPortFromSubSession(CCommSubSession* aSubSession);
+
+	TInt Write(TInt aPos, const RMessagePtr2& aMessage, const TDesC8& aDes, TInt aOffset=0);
+	TInt Read(TInt aPos, const RMessagePtr2& aMessage, TDes8& aDes, TInt aOffset=0);
+	TInt Write(TInt aPos, const RMessagePtr2& aMessage, const TDesC16& aDes, TInt aOffset=0);
+	TInt Read(TInt aPos, const RMessagePtr2& aMessage, TDes16& aDes,TInt aOffset=0);
+	
+private:
+	CC32Player(CC32WorkerThread* aOwnerThread);
+	void ConstructL();
+
+	TInt WriteSubSessionHandle(TInt aHandle);
+	void CloseSubSession(const RMessage2& aMessage, CCommSubSession* aSubSession);
+
+private:
+	CC32WorkerThread* iOwnerThread;					//< Thread owning this Player
+	TBool iComplete;								//< check if current message can be completed
+	CCommSession* iSession;							//< Current session, which might possibly belong to Dealer in different thread - only valid within current ProcessL().
+	const RMessage2* iCurrentMessage;				//< Current RMessage - only valid within current ProcessMessageL().
+	TSubSessionContainer iSubSessions;				//< All sub-sessions belonging to this Player.
+	CPortManager* iPortManager;						//< CPortManager in this player
+	};
+
+#include "cs_roles.inl"
+
+
+#endif // CS_ROLES_H
+
+