1 #ifndef CONNECT_SERVICES__COMPOUND_ID_IMPL__HPP
2 #define CONNECT_SERVICES__COMPOUND_ID_IMPL__HPP
3
4 /* $Id: compound_id_impl.hpp 414910 2013-09-27 16:05:05Z kazimird $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Authors: Dmitry Kazimirov
30 *
31 * File Description:
32 * Compound IDs are Base64-encoded string that contain application-specific
33 * information to identify and/or locate objects.
34 *
35 */
36
37 /// @file compound_id_impl.hpp
38 /// Internal declarations of the CompoundID classes.
39
40 #include <connect/services/compound_id.hpp>
41
42 #include <util/random_gen.hpp>
43
44 #include <corelib/ncbimtx.hpp>
45
46 BEGIN_NCBI_SCOPE
47
48 struct SFieldListLink
49 {
50 SCompoundIDFieldImpl* m_Prev;
51 SCompoundIDFieldImpl* m_Next;
52 };
53
54 struct SNeighborListLink : SFieldListLink
55 {
56 };
57
58 struct SSameTypeListLink : SFieldListLink
59 {
60 };
61
62 struct SCompoundIDFieldImpl : public CObject,
63 public SNeighborListLink, public SSameTypeListLink
64 {
65 virtual void DeleteThis();
66
67 CCompoundID m_CID;
68
69 ECompoundIDFieldType m_Type;
70
71 union {
72 Uint8 m_Uint8Value;
73 Int8 m_Int8Value;
74 Uint4 m_Uint4Value;
75 struct {
76 Uint4 m_IPv4Addr;
77 Uint2 m_Port;
78 } m_IPv4SockAddr;
79 bool m_BoolValue;
80
81 SCompoundIDFieldImpl* m_NextObjectInPool;
82 };
83 string m_StringValue;
84 CCompoundID m_NestedCID;
85 };
86
87 template <typename Link>
88 struct SFieldList
89 {
ClearSFieldList90 void Clear()
91 {
92 m_Tail = m_Head = NULL;
93 }
94
IsEmptySFieldList95 bool IsEmpty() const {return m_Head == NULL;}
96
GetLinkSFieldList97 static Link* GetLink(SCompoundIDFieldImpl* entry)
98 {
99 return static_cast<Link*>(entry);
100 }
101
GetPrevSFieldList102 static SCompoundIDFieldImpl* GetPrev(SCompoundIDFieldImpl* entry)
103 {
104 return GetLink(entry)->m_Prev;
105 }
106
GetNextSFieldList107 static SCompoundIDFieldImpl* GetNext(SCompoundIDFieldImpl* entry)
108 {
109 return GetLink(entry)->m_Next;
110 }
111
SetPrevSFieldList112 static void SetPrev(SCompoundIDFieldImpl* entry, SCompoundIDFieldImpl* prev)
113 {
114 GetLink(entry)->m_Prev = prev;
115 }
116
SetNextSFieldList117 static void SetNext(SCompoundIDFieldImpl* entry, SCompoundIDFieldImpl* next)
118 {
119 GetLink(entry)->m_Next = next;
120 }
121
AppendSFieldList122 void Append(SCompoundIDFieldImpl* new_entry)
123 {
124 SetNext(new_entry, NULL);
125 SetPrev(new_entry, m_Tail);
126 if (m_Tail != NULL)
127 SetNext(m_Tail, new_entry);
128 else
129 m_Head = new_entry;
130 m_Tail = new_entry;
131 }
132
RemoveSFieldList133 void Remove(SCompoundIDFieldImpl* entry)
134 {
135 if (GetPrev(entry) == NULL)
136 if ((m_Head = GetNext(entry)) == NULL)
137 m_Tail = NULL;
138 else
139 SetPrev(GetNext(entry), NULL);
140 else if (GetNext(entry) == NULL)
141 SetNext(m_Tail = GetPrev(entry), NULL);
142 else {
143 SetNext(GetPrev(entry), GetNext(entry));
144 SetPrev(GetNext(entry), GetPrev(entry));
145 }
146 }
147
148 SCompoundIDFieldImpl* m_Head;
149 SCompoundIDFieldImpl* m_Tail;
150 };
151
152 typedef SFieldList<SNeighborListLink> TFieldList;
153 typedef SFieldList<SSameTypeListLink> THomogeneousFieldList;
154
155 struct SCompoundIDImpl : public CObject
156 {
ResetSCompoundIDImpl157 void Reset(SCompoundIDPoolImpl* pool, ECompoundIDClass id_class)
158 {
159 m_Class = id_class;
160 m_Pool = pool;
161 m_Length = 0;
162 m_Dirty = true;
163 m_FieldList.Clear();
164 for (unsigned i = 0; i < eCIT_NumberOfTypes; ++i)
165 m_HomogeneousFields[i].Clear();
166 }
167
168 void Remove(SCompoundIDFieldImpl* field);
169
170 string PackV0();
171
172 SCompoundIDFieldImpl* AppendField(ECompoundIDFieldType field_type);
173
174 virtual void DeleteThis();
175
176 ECompoundIDClass m_Class;
177
178 TFieldList m_FieldList;
179 THomogeneousFieldList m_HomogeneousFields[eCIT_NumberOfTypes];
180
181 unsigned m_Length;
182
183 CCompoundIDPool m_Pool;
184 SCompoundIDImpl* m_NextObjectInPool;
185
186 string m_PackedID;
187 bool m_Dirty;
188 };
189
190 template <typename Poolable, typename FieldTypeOrIDClass>
191 struct SCompoundIDObjectPool
192 {
SCompoundIDObjectPoolSCompoundIDObjectPool193 SCompoundIDObjectPool() : m_Head(NULL)
194 {
195 }
196
197 CFastMutex m_Mutex;
198 Poolable* m_Head;
199
AllocSCompoundIDObjectPool200 Poolable* Alloc()
201 {
202 CFastMutexGuard guard(m_Mutex);
203
204 if (m_Head == NULL)
205 return new Poolable;
206 else {
207 Poolable* element = m_Head;
208 m_Head = element->m_NextObjectInPool;
209 return element;
210 }
211 }
212
ReturnToPoolSCompoundIDObjectPool213 void ReturnToPool(Poolable* element)
214 {
215 CFastMutexGuard guard(m_Mutex);
216
217 element->m_NextObjectInPool = m_Head;
218 m_Head = element;
219 }
220
~SCompoundIDObjectPoolSCompoundIDObjectPool221 ~SCompoundIDObjectPool()
222 {
223 Poolable* element = m_Head;
224 while (element != NULL) {
225 Poolable* next_element = element->m_NextObjectInPool;
226 delete element;
227 element = next_element;
228 }
229 }
230
231 };
232
233 struct SCompoundIDPoolImpl : public CObject
234 {
GetRandSCompoundIDPoolImpl235 Uint4 GetRand()
236 {
237 CFastMutexGuard guard(m_RandomGenMutex);
238 return m_RandomGen.GetRand();
239 }
240
241 CCompoundID UnpackV0(const string& packed_id);
242
243 SCompoundIDObjectPool<SCompoundIDFieldImpl,
244 ECompoundIDFieldType> m_FieldPool;
245 SCompoundIDObjectPool<SCompoundIDImpl, ECompoundIDClass> m_CompoundIDPool;
246 CFastMutex m_RandomGenMutex;
247 CRandom m_RandomGen;
248 };
249
Remove(SCompoundIDFieldImpl * field)250 inline void SCompoundIDImpl::Remove(SCompoundIDFieldImpl* field)
251 {
252 m_FieldList.Remove(field);
253 m_HomogeneousFields[field->m_Type].Remove(field);
254 m_Pool->m_FieldPool.ReturnToPool(field);
255 --m_Length;
256 m_Dirty = true;
257 }
258
259 extern void g_PackID(void* binary_id, size_t binary_id_len, string& packed_id);
260
261 extern bool g_UnpackID(const string& packed_id, string& binary_id);
262
263 END_NCBI_SCOPE
264
265 #endif /* CONNECT_SERVICES__COMPOUND_ID_IMPL__HPP */
266