networkcontrol/qosfwconfig/qos/src/modules.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkcontrol/qosfwconfig/qos/src/modules.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,222 @@
+// Copyright (c) 2006-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:
+//
+
+#include "qos_prot.h"
+#include "policies.h"
+#include "modules.h"
+
+// CModuleData
+CModuleData* CModuleData::NewLC(const TDesC& aModuleName, TUint aProtocolId, TUint aTimeoutDelay, TDblQue<CModuleData>& aList)
+	{
+	LOG(Log::Printf(_L("NewL\tqos module[%S] prot=%u delay=%u"), &aModuleName, aProtocolId, aTimeoutDelay));
+
+	CModuleData* module = new (ELeave) CModuleData(aProtocolId, aTimeoutDelay);
+
+	LOG(module->iName = aModuleName.Left(module->iName.MaxLength() < aModuleName.Length() ? module->iName.MaxLength() : aModuleName.Length()));
+
+	aList.AddLast(*module);
+	// Although the "module" is already recorded into the aList, the address is
+	// still pushed into the cleanup stack. The destructor of the CModuleData
+	// always removes the object the list, and if any of the following initializations
+	// (including those in the caller of this method) fail, the half initialized
+	// object will get destroyed (and not left in the list!).
+	CleanupStack::PushL(module);
+	module->ConstructL(aModuleName);
+	return module;
+	}
+
+void CModuleData::ConstructL(const TDesC& aModuleName)
+	{
+	TCallBack callback(WatchDogCallBack, this);
+	iTimeout = CModuleTimeout::NewL(callback);
+
+	User::LeaveIfError(iLib.Load(aModuleName));
+	TProtocolNew entry = (TProtocolNew)iLib.Lookup(1);
+	if (!entry)
+		User::Leave(KErrNoMemory);
+	
+	// Each module must be implemented as PRT module. One PRT
+	// can contain one module (= protocol).
+	// [Because the family and "protocol"
+	// are created and deleted as a pair here].
+	iFamily = (*entry)();
+	if (!iFamily)
+		User::Leave(KErrBadLibraryEntryPoint);
+	iFamily->Install();
+
+	iModule = (CModuleBase*)iFamily->NewProtocolL(KSockDatagram, iProtocolId);
+	if (!iModule)
+		User::LeaveIfError(KErrNotSupported);
+
+	// Get the module capabilities from the module
+	TInt flags=0;
+	TPckg<TInt> option(flags);
+	TInt ret = iModule->Configure(KSOLQoSModule, KSoCapabilities, option);
+	if (ret == KErrNone)
+		iFlags = flags;
+	}
+
+CModuleData::CModuleData(TUint aProtocolId, TUint aTimeoutDelay)
+	{
+	iTimeoutDelay = aTimeoutDelay;
+	iProtocolId = aProtocolId;
+	iModule = NULL;
+	iFamily = NULL;
+	iRefCount = 0;
+	iFlags = 0;
+	}
+
+CModuleData::~CModuleData()
+	{
+	LOG(Log::Printf(_L("~\tqos module[%S] destructor -- start"), &iName));
+	ASSERT(iRefCount == 0);	// Reference count MUST BE ZERO at this point!
+	iLink.Deque();			// Remove from CModuleManager::iModuleList!
+	delete iTimeout;		// ...cancels also the timer, if active.
+	delete iModule;
+	delete iFamily;
+	iLib.Close();
+	LOG(Log::Printf(_L("~\tqos module[%S] destructor -- end"), &iName));
+	}
+
+void CModuleData::Close()
+	{
+	ASSERT(iRefCount > 0);
+	if (--iRefCount <= 0)
+		{
+		LOG(Log::Printf(_L("\tqos module[%S] StartWatchdog"), &iName));
+		StartWatchDog();
+		}
+	}
+
+TInt CModuleData::WatchDogCallBack(TAny* aProvider)
+	{
+	CModuleData* module = (CModuleData*)aProvider;
+	LOG(Log::Printf(_L("<>\tqos module[%S] WatchDogCallback -- iRefCount=%d"), &module->iName, module->iRefCount));
+	if (module->iRefCount<=0)
+		{
+		// No references have appeared while waiting -- delete object
+		delete module;
+		}
+	return KErrNone;
+	}
+
+
+// CModuleManager
+CModuleManager* CModuleManager::NewL(CProtocolQoS& aProtocol)
+	{
+	return new (ELeave) CModuleManager(aProtocol);
+	}
+
+
+CModuleManager::CModuleManager(CProtocolQoS& aProtocol) : iProtocol(aProtocol)
+	{
+	LOG(Log::Printf(_L("new\tqos Module Manager[%u] size=%d"), (TInt)this, sizeof(CModuleManager)));
+	iModuleList.SetOffset(_FOFF(CModuleData, iLink));
+	}
+
+CModuleManager::~CModuleManager()
+	{
+	// UnloadAllModules();
+	while (!iModuleList.IsEmpty())
+		{
+		CModuleData* module = iModuleList.First();
+		delete module;	// ~CModuleData() deques the object from the iModuleList
+		}
+	LOG(Log::Printf(_L("~\tqos Module Manager[%u] deleted"), (TInt)this));
+	}
+
+
+RModule* CModuleManager::LoadModuleL(CModuleSpec& aModuleSpec, CProtocolBase* aIpProtocol)
+	{
+	return LoadModuleL(aIpProtocol, aModuleSpec.FileName(), aModuleSpec.ProtocolId(), aModuleSpec.PolicyData());
+	}
+
+
+RModule* CModuleManager::LoadModuleL(CProtocolBase* aIpProtocol, const TDesC& aModuleName, TUint aProtocolId, CExtension* aData)
+	{
+	TInt pops = 0;
+	// ??? If a Lookup finds an existing object, does it matter if it was
+	// ??? created with different value for aData (CExtension *) ?
+	// ??? (Note: GUQOS currently ignores that parameter, and thus not a problem YET!)
+	CModuleData* info = Lookup(aProtocolId);
+	if (!info)
+		{
+		info = CModuleData::NewLC(aModuleName, aProtocolId, Protocol().ConfigOptions().iUnloadDelay, iModuleList);
+		++pops;
+		info->iModule->BindToIP6L(aIpProtocol);
+		info->iModule->InitModuleL(Protocol(), aData);
+		}
+	RModule *module = new (ELeave) RModule(*info);
+	// Note: Having the "Pop" here solves the case where CModuleData contruction is complete, but
+	// the RModule allocation leaves. This prevents the case where the iModuleList contains object
+	// with iRefCount == 0, but no timer running => it would not get deleted until module manager dies or
+	// some reference is added and removed.
+	CleanupStack::Pop(pops);
+	return module;
+	}
+
+RModule* CModuleManager::OpenModuleL(TUint aProtocolId)
+	{
+	RModule* module=NULL;
+	CModuleData* moduleData = Lookup(aProtocolId);
+	if (moduleData)
+		module = new (ELeave) RModule(*moduleData);
+	return module;
+	}
+
+
+TBool CModuleManager::IsLoaded(TUint aProtocolId)
+	{
+	return (Lookup(aProtocolId) == NULL) ? EFalse : ETrue;
+	}
+
+void CModuleManager::Unbind(CProtocolBase* aProtocol, TInt aId)
+	{
+	TDblQueIter<CModuleData> iter(iModuleList);
+	CModuleData* module;
+	while ((module = iter++) != NULL)
+		module->iModule->Unbind(aProtocol, aId);
+	}
+
+
+CModuleData* CModuleManager::Lookup(TUint aProtocolId)
+	{
+	TDblQueIter<CModuleData> iter(iModuleList);
+	CModuleData* moduleData;
+
+	while ((moduleData = iter++) != NULL)
+		{
+		if (moduleData->iProtocolId == aProtocolId)
+			return moduleData;
+		}
+	return NULL;
+	}
+
+// RModule
+RModule::RModule(CModuleData& aModuleData) : iModuleData(aModuleData)
+	{ 
+	iModuleData.Open();
+	}
+
+RModule::RModule(const RModule& aModule) : iModuleData(aModule.iModuleData)
+	{
+	iModuleData.Open();
+	}
+
+RModule::~RModule()
+	{
+	iModuleData.Close();
+	}
+