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