• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #ifndef STRING_KEYVALUE_STORE_H_INCLUDED
19 #define STRING_KEYVALUE_STORE_H_INCLUDED
20 
21 #ifndef OSCL_BASE_H_INCLUDED
22 #include "oscl_base.h"
23 #endif
24 #ifndef OSCL_MEM_H_INCLUDED
25 #include "oscl_mem.h"
26 #endif
27 #ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
28 #include "oscl_mem_mempool.h"
29 #endif
30 #ifndef OSCL_STR_PTR_LEN_H_INCLUDED
31 #include "oscl_str_ptr_len.h"
32 #endif
33 #ifndef OSCL_VECTOR_H_INCLUDED
34 #include "oscl_vector.h"
35 #endif
36 
37 #define KEYVALUESTORE_HASH_TABLE_SIZE_FOR_KEYS 1000
38 #define KEYVALUESTORE_MAX_SIZE 4000                 // same as the RTSP parcom, but this size shouldn't include entity body size, which the composer library has no control
39 #define KEYVALUESTORE_VECTOR_RESERVE_VALUE 10       // for iStrCSumPtrLenWrapperVector.reserve()
40 
41 
42 // This StrCSumPtrLen wrapper wraps StrCSumPtrLen with the following new features.
43 // (1) changed checksum calculation algorithm to make checksum as an identifier to differentiate different StrCSumPtrLen object.
44 //     This will be used in quick string comparison/search for field key of HTTP header.
45 //     Note that in StrCSumPtrLen, the checksum is calulated as the sum of the ASCII codes of all string charaters (lowercase).
46 //     And this is not quite efficient. The modified version is contrained within 500 (see the following getChecksum()), with tiny
47 //     performance loss.
48 // (2) support simplified link list. This is mainly used for multiple same header field cases (i.e. same field key, but multiple field
49 //     values).
50 
51 struct StrCSumPtrLenWrapper
52 {
53 public:
54     // constructor
StrCSumPtrLenWrapperStrCSumPtrLenWrapper55     StrCSumPtrLenWrapper() : iNext(NULL)
56     {
57         ;
58     }
59 
60     // copy constructor
StrCSumPtrLenWrapperStrCSumPtrLenWrapper61     StrCSumPtrLenWrapper(const StrCSumPtrLen &x) : iStr(x), iNext(NULL)
62     {
63         ;
64     }
StrCSumPtrLenWrapperStrCSumPtrLenWrapper65     StrCSumPtrLenWrapper(const char *x) : iStr(x), iNext(NULL)
66     {
67         ;
68     }
StrCSumPtrLenWrapperStrCSumPtrLenWrapper69     StrCSumPtrLenWrapper(const char *x, const uint32 len) : iStr(x, len), iNext(NULL)
70     {
71         ;
72     }
73 
74     // destructor
~StrCSumPtrLenWrapperStrCSumPtrLenWrapper75     ~StrCSumPtrLenWrapper()
76     {
77         clear();
78     }
79 
80     // use checksum (with some changes) as an identifier, will be used to differentiate different StrCSumPtrLen objects.
getChecksumStrCSumPtrLenWrapper81     uint32 getChecksum()
82     {
83         // algorithm: checksum = (checksum % 1000) / 2
84         return (uint32)((uint32)iStr.getCheckSum() % KEYVALUESTORE_HASH_TABLE_SIZE_FOR_KEYS) / 2;
85     }
86 
87     // add to linked list
push_backStrCSumPtrLenWrapper88     void push_back(StrCSumPtrLenWrapper *aStrLinkTo)
89     {
90         StrCSumPtrLenWrapper **pWrapper = &iNext;
91         while (*pWrapper) pWrapper = &((*pWrapper)->iNext);
92         *pWrapper = aStrLinkTo;
93     }
94 
95     // get next element
getNextStrCSumPtrLenWrapper96     StrCSumPtrLenWrapper *getNext()
97     {
98         return iNext;
99     }
100 
101     // clear
clearStrCSumPtrLenWrapper102     void clear()
103     {
104         iStr.setPtrLen("", 0);
105         iNext = NULL;
106     }
107 
108     // empty
emptyStrCSumPtrLenWrapper109     bool empty()
110     {
111         return (iNext == NULL && iStr.length() == 0);
112     }
113 
114     // wrap some functions of StrCSumPtrLen
c_strStrCSumPtrLenWrapper115     const char* c_str() const
116     {
117         return iStr.c_str();
118     }
lengthStrCSumPtrLenWrapper119     uint32 length() const
120     {
121         return (uint32)iStr.length();
122     }
sizeStrCSumPtrLenWrapper123     uint32 size() const
124     {
125         return (uint32)iStr.size();
126     }
isCIEquivalentToStrCSumPtrLenWrapper127     bool isCIEquivalentTo(const StrCSumPtrLen& rhs) const
128     {
129         return (iStr.isCIEquivalentTo(rhs) > 0);
130     }
isCIEquivalentToStrCSumPtrLenWrapper131     bool isCIEquivalentTo(const char*s, const uint32 len) const
132     {
133         StrCSumPtrLen str(s, len);
134         return (iStr.isCIEquivalentTo(str) > 0);
135     }
setPtrLenStrCSumPtrLenWrapper136     void setPtrLen(const char* newPtr, uint32 newLen)
137     {
138         iStr.setPtrLen(newPtr, newLen);
139         iNext = NULL;
140     }
141 
setPtrLenStrCSumPtrLenWrapper142     void setPtrLen(const StrPtrLen &aString)
143     {
144         iStr.setPtrLen(aString.c_str(), aString.length());
145         iNext = NULL;
146     }
147 
148     // operator =
149     StrCSumPtrLenWrapper& operator=(const StrCSumPtrLen& rhs)
150     {
151         iStr = rhs;
152         iNext = NULL;
153         return *this;
154     }
155 
156     StrCSumPtrLenWrapper& operator=(const StrPtrLen& rhs)
157     {
158         iStr = rhs;
159         iNext = NULL;
160         return *this;
161     }
162 
163     StrCSumPtrLenWrapper& operator=(const StrCSumPtrLenWrapper& rhs)
164     {
165         iStr = rhs.iStr;
166         iNext = rhs.iNext;
167         return *this;
168     }
169 
170 private:
171     StrCSumPtrLen iStr;
172     StrCSumPtrLenWrapper *iNext;
173 };
174 
175 // class declaration
176 class OsclMemPoolVariableChunkAllocator;
177 
178 // class for encapsulating string based key-value pair handlings
179 // The major feature for this class is hash-table based key search. To handle hash table conllision, linear search
180 // table is used. Basically a whole hash table is divided into two parts, the first part is for real hash table,
181 // the second part is for collision.
182 class StringKeyValueStore
183 {
184     public:
185         // add a key-value pair, key-value will be made a copy inside the store
186         // return code is one of following StringKeyValueStoreReturnCodes
187         int32 addKeyValuePair(const StrCSumPtrLen &aNewKey, const StrPtrLen &aNewValue, const bool aNeedReplaceOldValue = false);
188         int32 addKeyValuePair(const StrCSumPtrLen &aNewKey, const char *aNewValue, const bool aNeedReplaceOldValue = false);
189 
190         // This overloaded function is for this case, when the key and value are parsed from the data stream, to avoid memory copy,
191         // we locate the segment in the data stream for the key and value, which has no NULL terminatior.
192         int32 addKeyValuePair(const char *aNewKey, const uint32 aKeyLength, const char *aNewValue, const uint32 aValueLength,
193                               const bool aNeedReplaceOldValue = false);
194 
195         // get number of key-value pairs, which could be different from the number of keys,
196         // when there might be a key with multiple values
getNumberOfKeyValuePairs()197         uint32 getNumberOfKeyValuePairs()
198         {
199             return iTotalNumberOfKeyValuePairs;
200         }
getNumberOfKeys()201         uint32 getNumberOfKeys()
202         {
203             return iFieldKeyTableIndexVector.size();
204         }
getTotalKeyValueLength()205         uint32 getTotalKeyValueLength()
206         {
207             return iTotalKeyValueLength;
208         }
209         // aListSize=0 means retrieves whatever the library has
210         // return the actual list size
211         uint32 getCurrentKeyList(StrPtrLen *&aFieldKeyList, const uint32 aListSize = 0);
212         bool getValueByKey(const StrCSumPtrLen &aKey, StrPtrLen &aValue, const uint32 index = 0);
213 
214         // for one key multiple value cases.
215         // return value: 0 => no value for the given key, 1 or more => number of values for the given key
216         uint32 getNumberOfValuesByKey(const StrCSumPtrLen &aKey);
217 
218         // search
219         bool isKeyValueAvailable(const StrCSumPtrLen &aKey);
220 
221         // remove
222         bool removeKeyValuePair(const StrCSumPtrLen &aKey);
223 
224         // clear
225         void clear();
226 
227         // copy
228         bool copy(StringKeyValueStore& aStore);
229 
230 
231         // query store infomation
232         uint32 getCurrentMemoryUsage();
233         uint32 getStoreSize();
234         uint32 getAvailableSize();
235 
236         // constructor
StringKeyValueStore()237         StringKeyValueStore() : iVariableSizeMemPool(NULL)
238         {
239             ;
240         }
241 
242         // destructor
243         ~StringKeyValueStore();
244 
245         // factory method
246         static StringKeyValueStore* create(const uint32 aStoreSize = KEYVALUESTORE_MAX_SIZE);
247 
248         enum StringKeyValueStoreReturnCodes
249         {
250             StringKeyValueStore_Success = 0,
251             StringKeyValueStore_Failure = -1,
252             StringKeyValueStore_NoMemory = -2
253         };
254 
255     private:
256         uint32 calculateChecksum(const char *aBuffer, uint32 aBufferLength);
257         bool construct(const uint32 aStoreSize);
258 
259         // for conflict handling
260         // To handle hash table collisions, the hash table is divided into two parts, one part is for first hit elements, and
261         // all the conflict elements is collected into another part. The reason for not choosing link list approach is, usually
262         // conllision possibilities are very low, so no need to keep link list for every table element. (Note that if the collision
263         // possibilities go high, hash function should be updated to keep this collision possibility low) Another reason is, don't
264         // want to change the current structure too much.
265 
266         // aFindKey=true, the purpose of getting table index is for element search or removal;
267         // aFindKey=false, the purpose is for adding a new element
268         // return value: table index, for operation failure, return -1
269         int32 getHashTableIndex(const StrCSumPtrLen &aKey, const bool aFindKey = true);
270         // linear seach in linear search area of hash table for the given key
271         // return table index for linear search area, -1 means the input key is not found
272         int32 query(const StrCSumPtrLen &aKey);
273 
274         // supporting function for addKeyValuePair() and removeKeyValuePair()
275         // return code is one of StringKeyValueStoreReturnCodes
276         int32 addKeyToStore(const StrCSumPtrLen &aNewKey, int32 tableIndex);
277 
278         // centralize memory related operations within these two fucntions
279         bool storeNewKeyValueItem(const char *aItem, const int32 aItemLength, char *&aNewLocation);
280         void releaseOldKeyValueItem(const char *aItem, const int32 aItemLength);
281 
282     private:
283 
284         uint32 iTotalNumberOfKeyValuePairs;
285         uint32 iTotalKeyValueLength;
286 
287         // field key@value tables (field key table is a hash table per se)
288         StrCSumPtrLenWrapper iFieldKeys[KEYVALUESTORE_HASH_TABLE_SIZE_FOR_KEYS];
289         StrPtrLen iFieldVals[KEYVALUESTORE_HASH_TABLE_SIZE_FOR_KEYS];
290 
291         // use variable-size memory pool to replace fixed-size memory storage
292         // OsclMemPoolResizableAllocator is not used because of overhead.
293         // That variable-size memory pool has fixed 28-byte header for each allocated memory segment. This
294         // overhead is too much in the current user scenario, storing field key and value. Especially for
295         // field key, it is usually less than 20 bytes. So that allocator is two expensive.
296         OsclMemPoolVariableChunkAllocator* iVariableSizeMemPool;
297 
298         // storage for multiple field values with the same field key
299         Oscl_Vector<StrCSumPtrLenWrapper, OsclMemAllocator> iStrCSumPtrLenWrapperVector;
300 
301         // save the parsed field key index of the field key table
302         // The reason for this, usually less than a dozen of header fields are set for a message, comparing the
303         // relatively big hash table, saving the table indices will save lots of search operations.
304         Oscl_Vector<uint32, OsclMemAllocator> iFieldKeyTableIndexVector;
305         uint32 iNumConflicts;
306 };
307 
308 #endif // STRING_KEYVALUE_STORE_H_INCLUDED
309 
310