diff -r 000000000000 -r af10295192d8 tcpiputils/dnd/src/cache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcpiputils/dnd/src/cache.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,263 @@ +// Copyright (c) 2004-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: +// cache.cpp - the record cache +// + +// This file contains the implementations of the CDndCache object. +#include "engine.h" +#include "node.h" +#include "cache.h" +#include +#include "inet6log.h" + +// Cache root node for a specific name space +class CDndNameSpace : public CDndNode + { +public: + CDndNameSpace(TUint32 aNameSpaceId) : CDndNode(NULL, 0, _L8("")), iNameSpaceId(aNameSpaceId), iState(1) {} + ~CDndNameSpace(); + const TUint32 iNameSpaceId; //< The name space ID + TInt iState; //< Address state (initially = 1) + TInetAddr iAddr; //< Server Address and port (if any) + CDndNameSpace *iNext; //< Next name space root + }; + +/** +// The destructor has really nothing functional to do. +// The precondition for destruct is that ALL nodes and +// records under the root node have already been destroyed. +*/ +CDndNameSpace::~CDndNameSpace() + { + ASSERT(IsEmpty()); + } + + +// CDndCache::CDndCache +// ******************** +CDndCache::CDndCache() + {} + + +// CDndCache::ContstructL +// ********************** +void CDndCache::ConstructL() + { + LOG(Log::Printf(_L("CDndCache::ConstructL() size=%d\r\n"), (TInt)sizeof(*this))); + } + + +// CDndCache::~CDndCache +// ********************* +/** +// Delete ALL records, and as a side effect all nodes +// (except the roots are freed). And, then delete all +// root nodes. +// +// If there are locked records, which prevent deletion +// of all nodes, then cache destructor has been called +// incorrectly! (=> ~CDndNameSpace() will panic) +*/ +CDndCache::~CDndCache() + { + iRecordList.Cleanup(0); // Delete all unlocked records + // + // Delete (now supposedly empty) root nodes + // + while (iRootList) + { + CDndNameSpace *ns = iRootList; + iRootList = iRootList->iNext; + delete ns; + } + } + +// CDndCache::Flush +// **************** +/** +// Empty the cache. +*/ +void CDndCache::Flush() + { + iRecordList.Cleanup(0); + } + +// CDndCache::GetServerAddress +// *************************** +/** +// Get currently known server address for the name space. +// +// The address state is inially 1 (> 0). It is only changed by the +// CDndCache::SetServerAddress . +// +// If the name-space does not have a root node, the root node +// is created by this call (CDndCache::GetNameSpaceL). +// +// @param aNameSpace the name space id +// @retval aAddr the server address currently associated with the name space +// @returns the state of the returned address as: +// @li > 0, no address has been set +// @li = 0, address set +// @li < 0, address set with error state, or +// @li KErrNoMemory, if needed to create the root node and failed +*/ +TInt CDndCache::GetServerAddress(const TUint32 aNameSpace, TInetAddr &aAddr) + { + CDndNameSpace *const ns = GetNameSpace(aNameSpace); + if (ns == NULL) + return KErrNoMemory; + + aAddr = ns->iAddr; + return ns->iState; + } + +// CDndCache::SetServerAddress +// *************************** +/** +// Set the server address/state for the name space. +// +// If the name-space does not have a root node, the root node +// is created by this call (CDndCache::GetNameSpaceL). +// +// @param aNameSpace the name space id +// @param aAddr the server address to be set +// @param aState the state of the address +*/ +void CDndCache::SetServerAddress(const TUint32 aNameSpace, const TInetAddr &aAddr, const TInt aState) + { + CDndNameSpace *const ns = GetNameSpace(aNameSpace); + if (ns != NULL) + { + ns->iAddr = aAddr; + ns->iState = aState; + } + } + +// CDndCache::GetNameSpace +// *********************** +/** +// Locate the name space root or try to create it if not found. +// +// @param aNameSpace the name-space id +// @returns the name-space root or NULL, if not found and create +// failed. +*/ +CDndNameSpace *CDndCache::GetNameSpace(const TUint32 aNameSpace) + { + CDndNameSpace *ns = iRootList; + + // Does a request namespace already exist? + for ( ; ns != NULL; ns = ns->iNext) + if (ns->iNameSpaceId == aNameSpace) + return ns; + + // Does not exist, a new namespace needed, create a new root + ns = new CDndNameSpace(aNameSpace); + if (ns) + { + ns->iNext = iRootList; + iRootList = ns; + } + return ns; + } + + +// CDndCache::FindL +// **************** +/** +// Find record from the cache. +// +// Finds the record from the cache which +// matches the name, type and class. If it has expired, it is invalidated +// and returned. If no such record exists, one new record is inserted and +// returned. +// +// If the name-space does not have a root node, the root node +// is created by this call (CDndCache::GetNameSpaceL). +// +// @param aNameSpace +// the name-space id. If ZERO, only search is performed +// across all currently existing name-spaces. No new +// state is created. +// @param aName +// the fully qualified domain-name which owns the record (dotted format) +// @param aType +// the record type +// @param aClass +// the record class +// @param aReqTime +// the time of the request. This is used to detect records whose TTL +// is expired +// @returns +// always a non-NULL pointer to the record matching (aNameSpace,aName,aType,aClass). The FindL +// will create the necessary node structures, if they do not exist before the call. If the +// record didn't exist before, the initial state of the new record is "Invalid". +// @exception KErrNoMemory +// the main potential reason for FindL to fail (not enough memory to create the objects) +// @exception KErrDndNoRecord +// can occur only when called with aNameSpace == 0, and the record does not exist. +*/ +CDndRecord * CDndCache::FindL(const TUint32 aNameSpace, const TDesC8 &aName, const EDnsQType aType, const EDnsQClass aClass, + const TTime &aReqTime) + { + CDndRecord *record = NULL; + + if (aNameSpace == 0) + { + // If no name space is specified, then just search for match, never add record + for (CDndNameSpace *ns = iRootList; ; ns = ns->iNext) + { + if (ns == NULL) + User::Leave(KErrDndNoRecord); + record = ns->FindL(aName, FALSE, aType, aClass, iRecordList, aReqTime); + if (record) + break; + } + // record != NULL here, ALWAYS! + } + else + { + // When namespace is defined, always create the record and other necessary structures + // if neeeded. + // + iRecordList.Cleanup(KDndMaxRecords); + // Locate or create the name-space root + CDndNameSpace *const ns = GetNameSpace(aNameSpace); + if (ns == NULL) + User::Leave(KErrNoMemory); + // Locate (or create) the matching record + record = ns->FindL(aName, TRUE, aType, aClass, iRecordList, aReqTime); + // record != NULL here ALWAYS! + } + + record->HitLRU(); + return record; + } + + +#ifdef _LOG +// CDndCache::Dump +// *************** +/** +// Print out the entire cache (for DEBUG only) +*/ +void CDndCache::Dump(CDndEngine &aControl) + { + if (!iRootList) + aControl.ShowText(_L("No cache in the system")); + else + for (CDndNameSpace *ns = iRootList; ns != NULL; ns = ns->iNext) + ns->Print(aControl); + } +#endif