|
1 // Copyright (c) 2004-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 // cache.cpp - the record cache |
|
15 // |
|
16 |
|
17 // This file contains the implementations of the CDndCache object. |
|
18 #include "engine.h" |
|
19 #include "node.h" |
|
20 #include "cache.h" |
|
21 #include <networking/dnd_err.h> |
|
22 #include "inet6log.h" |
|
23 |
|
24 // Cache root node for a specific name space |
|
25 class CDndNameSpace : public CDndNode |
|
26 { |
|
27 public: |
|
28 CDndNameSpace(TUint32 aNameSpaceId) : CDndNode(NULL, 0, _L8("")), iNameSpaceId(aNameSpaceId), iState(1) {} |
|
29 ~CDndNameSpace(); |
|
30 const TUint32 iNameSpaceId; //< The name space ID |
|
31 TInt iState; //< Address state (initially = 1) |
|
32 TInetAddr iAddr; //< Server Address and port (if any) |
|
33 CDndNameSpace *iNext; //< Next name space root |
|
34 }; |
|
35 |
|
36 /** |
|
37 // The destructor has really nothing functional to do. |
|
38 // The precondition for destruct is that ALL nodes and |
|
39 // records under the root node have already been destroyed. |
|
40 */ |
|
41 CDndNameSpace::~CDndNameSpace() |
|
42 { |
|
43 ASSERT(IsEmpty()); |
|
44 } |
|
45 |
|
46 |
|
47 // CDndCache::CDndCache |
|
48 // ******************** |
|
49 CDndCache::CDndCache() |
|
50 {} |
|
51 |
|
52 |
|
53 // CDndCache::ContstructL |
|
54 // ********************** |
|
55 void CDndCache::ConstructL() |
|
56 { |
|
57 LOG(Log::Printf(_L("CDndCache::ConstructL() size=%d\r\n"), (TInt)sizeof(*this))); |
|
58 } |
|
59 |
|
60 |
|
61 // CDndCache::~CDndCache |
|
62 // ********************* |
|
63 /** |
|
64 // Delete ALL records, and as a side effect all nodes |
|
65 // (except the roots are freed). And, then delete all |
|
66 // root nodes. |
|
67 // |
|
68 // If there are locked records, which prevent deletion |
|
69 // of all nodes, then cache destructor has been called |
|
70 // incorrectly! (=> ~CDndNameSpace() will panic) |
|
71 */ |
|
72 CDndCache::~CDndCache() |
|
73 { |
|
74 iRecordList.Cleanup(0); // Delete all unlocked records |
|
75 // |
|
76 // Delete (now supposedly empty) root nodes |
|
77 // |
|
78 while (iRootList) |
|
79 { |
|
80 CDndNameSpace *ns = iRootList; |
|
81 iRootList = iRootList->iNext; |
|
82 delete ns; |
|
83 } |
|
84 } |
|
85 |
|
86 // CDndCache::Flush |
|
87 // **************** |
|
88 /** |
|
89 // Empty the cache. |
|
90 */ |
|
91 void CDndCache::Flush() |
|
92 { |
|
93 iRecordList.Cleanup(0); |
|
94 } |
|
95 |
|
96 // CDndCache::GetServerAddress |
|
97 // *************************** |
|
98 /** |
|
99 // Get currently known server address for the name space. |
|
100 // |
|
101 // The address state is inially 1 (> 0). It is only changed by the |
|
102 // CDndCache::SetServerAddress . |
|
103 // |
|
104 // If the name-space does not have a root node, the root node |
|
105 // is created by this call (CDndCache::GetNameSpaceL). |
|
106 // |
|
107 // @param aNameSpace the name space id |
|
108 // @retval aAddr the server address currently associated with the name space |
|
109 // @returns the state of the returned address as: |
|
110 // @li > 0, no address has been set |
|
111 // @li = 0, address set |
|
112 // @li < 0, address set with error state, or |
|
113 // @li KErrNoMemory, if needed to create the root node and failed |
|
114 */ |
|
115 TInt CDndCache::GetServerAddress(const TUint32 aNameSpace, TInetAddr &aAddr) |
|
116 { |
|
117 CDndNameSpace *const ns = GetNameSpace(aNameSpace); |
|
118 if (ns == NULL) |
|
119 return KErrNoMemory; |
|
120 |
|
121 aAddr = ns->iAddr; |
|
122 return ns->iState; |
|
123 } |
|
124 |
|
125 // CDndCache::SetServerAddress |
|
126 // *************************** |
|
127 /** |
|
128 // Set the server address/state for the name space. |
|
129 // |
|
130 // If the name-space does not have a root node, the root node |
|
131 // is created by this call (CDndCache::GetNameSpaceL). |
|
132 // |
|
133 // @param aNameSpace the name space id |
|
134 // @param aAddr the server address to be set |
|
135 // @param aState the state of the address |
|
136 */ |
|
137 void CDndCache::SetServerAddress(const TUint32 aNameSpace, const TInetAddr &aAddr, const TInt aState) |
|
138 { |
|
139 CDndNameSpace *const ns = GetNameSpace(aNameSpace); |
|
140 if (ns != NULL) |
|
141 { |
|
142 ns->iAddr = aAddr; |
|
143 ns->iState = aState; |
|
144 } |
|
145 } |
|
146 |
|
147 // CDndCache::GetNameSpace |
|
148 // *********************** |
|
149 /** |
|
150 // Locate the name space root or try to create it if not found. |
|
151 // |
|
152 // @param aNameSpace the name-space id |
|
153 // @returns the name-space root or NULL, if not found and create |
|
154 // failed. |
|
155 */ |
|
156 CDndNameSpace *CDndCache::GetNameSpace(const TUint32 aNameSpace) |
|
157 { |
|
158 CDndNameSpace *ns = iRootList; |
|
159 |
|
160 // Does a request namespace already exist? |
|
161 for ( ; ns != NULL; ns = ns->iNext) |
|
162 if (ns->iNameSpaceId == aNameSpace) |
|
163 return ns; |
|
164 |
|
165 // Does not exist, a new namespace needed, create a new root |
|
166 ns = new CDndNameSpace(aNameSpace); |
|
167 if (ns) |
|
168 { |
|
169 ns->iNext = iRootList; |
|
170 iRootList = ns; |
|
171 } |
|
172 return ns; |
|
173 } |
|
174 |
|
175 |
|
176 // CDndCache::FindL |
|
177 // **************** |
|
178 /** |
|
179 // Find record from the cache. |
|
180 // |
|
181 // Finds the record from the cache which |
|
182 // matches the name, type and class. If it has expired, it is invalidated |
|
183 // and returned. If no such record exists, one new record is inserted and |
|
184 // returned. |
|
185 // |
|
186 // If the name-space does not have a root node, the root node |
|
187 // is created by this call (CDndCache::GetNameSpaceL). |
|
188 // |
|
189 // @param aNameSpace |
|
190 // the name-space id. If ZERO, only search is performed |
|
191 // across all currently existing name-spaces. No new |
|
192 // state is created. |
|
193 // @param aName |
|
194 // the fully qualified domain-name which owns the record (dotted format) |
|
195 // @param aType |
|
196 // the record type |
|
197 // @param aClass |
|
198 // the record class |
|
199 // @param aReqTime |
|
200 // the time of the request. This is used to detect records whose TTL |
|
201 // is expired |
|
202 // @returns |
|
203 // always a non-NULL pointer to the record matching (aNameSpace,aName,aType,aClass). The FindL |
|
204 // will create the necessary node structures, if they do not exist before the call. If the |
|
205 // record didn't exist before, the initial state of the new record is "Invalid". |
|
206 // @exception KErrNoMemory |
|
207 // the main potential reason for FindL to fail (not enough memory to create the objects) |
|
208 // @exception KErrDndNoRecord |
|
209 // can occur only when called with aNameSpace == 0, and the record does not exist. |
|
210 */ |
|
211 CDndRecord * CDndCache::FindL(const TUint32 aNameSpace, const TDesC8 &aName, const EDnsQType aType, const EDnsQClass aClass, |
|
212 const TTime &aReqTime) |
|
213 { |
|
214 CDndRecord *record = NULL; |
|
215 |
|
216 if (aNameSpace == 0) |
|
217 { |
|
218 // If no name space is specified, then just search for match, never add record |
|
219 for (CDndNameSpace *ns = iRootList; ; ns = ns->iNext) |
|
220 { |
|
221 if (ns == NULL) |
|
222 User::Leave(KErrDndNoRecord); |
|
223 record = ns->FindL(aName, FALSE, aType, aClass, iRecordList, aReqTime); |
|
224 if (record) |
|
225 break; |
|
226 } |
|
227 // record != NULL here, ALWAYS! |
|
228 } |
|
229 else |
|
230 { |
|
231 // When namespace is defined, always create the record and other necessary structures |
|
232 // if neeeded. |
|
233 // |
|
234 iRecordList.Cleanup(KDndMaxRecords); |
|
235 // Locate or create the name-space root |
|
236 CDndNameSpace *const ns = GetNameSpace(aNameSpace); |
|
237 if (ns == NULL) |
|
238 User::Leave(KErrNoMemory); |
|
239 // Locate (or create) the matching record |
|
240 record = ns->FindL(aName, TRUE, aType, aClass, iRecordList, aReqTime); |
|
241 // record != NULL here ALWAYS! |
|
242 } |
|
243 |
|
244 record->HitLRU(); |
|
245 return record; |
|
246 } |
|
247 |
|
248 |
|
249 #ifdef _LOG |
|
250 // CDndCache::Dump |
|
251 // *************** |
|
252 /** |
|
253 // Print out the entire cache (for DEBUG only) |
|
254 */ |
|
255 void CDndCache::Dump(CDndEngine &aControl) |
|
256 { |
|
257 if (!iRootList) |
|
258 aControl.ShowText(_L("No cache in the system")); |
|
259 else |
|
260 for (CDndNameSpace *ns = iRootList; ns != NULL; ns = ns->iNext) |
|
261 ns->Print(aControl); |
|
262 } |
|
263 #endif |