--- /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 <networking/dnd_err.h>
+#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