-
Notifications
You must be signed in to change notification settings - Fork 0
/
fds.h
executable file
·386 lines (349 loc) · 12.4 KB
/
fds.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/////////////////////////////////////////////////
// Forward
template <class TKey, class TFDat, class TVDat>
class TFHash;
typedef enum {fhbtUndef, fhbtKey, fhbtVDat} TFHashBlobType;
/////////////////////////////////////////////////
// File-Hash-Table-Key-Data
template <class TKey, class TFDat, class TVDat>
class TFHashKey{
private:
TCRef CRef;
bool Modified;
public:
typedef TPt<TFHashKey<TKey, TFDat, TVDat> > PFHashKey;
typedef TFHash<TKey, TFDat, TVDat> THash;
TBlobPt Next;
TKey Key;
TFDat FDat;
TBlobPt VDatBPt;
public:
TFHashKey():
Modified(false), Next(), Key(), FDat(), VDatBPt(){}
TFHashKey(const TBlobPt& _Next,
const TKey& _Key, const TFDat& _FDat, const TBlobPt& _VDatBPt=TBlobPt()):
Modified(false), Next(_Next), Key(_Key), FDat(_FDat), VDatBPt(_VDatBPt){}
~TFHashKey(){}
TFHashKey(TSIn& SIn):
Modified(false), Next(SIn), Key(SIn), FDat(SIn), VDatBPt(SIn){}
static PFHashKey Load(TSIn& SIn){return new TFHashKey(SIn);}
void Save(TSOut& SOut){
Next.Save(SOut); Key.Save(SOut); FDat.Save(SOut); VDatBPt.Save(SOut);}
TFHashKey& operator=(const TFHashKey& FHashKey){
if (this!=&FHashKey){
Modified=true; Next=FHashKey.Next;
Key=FHashKey.Key; FDat=FHashKey.FDat; VDatBPt=FHashKey.VDatBPt;}
return *this;}
int GetMemUsed() const {
return sizeof(THash*)+Next.GetMemUsed()+
Key.GetMemUsed()+FDat.GetMemUsed()+VDatBPt.GetMemUsed();}
void PutModified(const bool& _Modified){Modified=_Modified;}
void OnDelFromCache(const TBlobPt& BlobPt, void* RefToBs);
friend class TPt<TFHashKey<TKey, TFDat, TVDat> >;
};
template <class TKey, class TFDat, class TVDat>
void TFHashKey<TKey, TFDat, TVDat>::OnDelFromCache(
const TBlobPt& BlobPt, void* RefToBs){
if (Modified){
// prepare hash table object
THash* FHash=(THash*)RefToBs;
// save the key
TMOut MOut; TInt(int(fhbtKey)).Save(MOut); Save(MOut);
TBlobPt NewBlobPt=FHash->GetHashBBs()->PutBlob(BlobPt, MOut.GetSIn());
// blob-pointer for key should not change
IAssert(NewBlobPt==BlobPt);
}
}
/////////////////////////////////////////////////
// File-Hash-Table
template <class TKey, class TFDat, class TVDat>
class TFHash{
private:
TCRef CRef;
private:
typedef TPt<TFHash<TKey, TFDat, TVDat> > PFHash;
typedef TFHashKey<TKey, TFDat, TVDat> THashKey;
typedef TPt<THashKey> PHashKey;
TFAccess Access;
PBlobBs HashBBs;
TBlobPtV PortV;
TInt Keys;
TCache<TBlobPt, PHashKey> FHashKeyCache;
private:
void* GetVoidThis() const {return (void*)this;}
PBlobBs GetHashBBs(){return HashBBs;}
PHashKey GetFHashKey(const TBlobPt& KeyId){
PHashKey FHashKey;
if (!FHashKeyCache.Get(KeyId, FHashKey)){ // if the key is in cache
// read the key from blob-base
PSIn SIn=HashBBs->GetBlob(KeyId);
TFHashBlobType Type=TFHashBlobType(int(TInt(*SIn))); IAssert(Type==fhbtKey);
FHashKey=PHashKey(new THashKey(*SIn));
}
FHashKeyCache.Put(KeyId, FHashKey); // refresh/put key in cache
return FHashKey;
}
void GetKeyInfo(const TKey& Key,
int& PortN, TBlobPt& PrevKeyId, TBlobPt& KeyId, PHashKey& FHashKey);
void GetKeyInfo(const TKey& Key, TBlobPt& KeyId, PHashKey& FHashKey){
int PortN=-1; TBlobPt PrevKeyId;
GetKeyInfo(Key, PortN, PrevKeyId, KeyId, FHashKey);}
private:
TBlobPt AddKey(const TKey& Key,
const bool& ChangeFDat, const TFDat& FDat,
const bool& ChangeVDatBPt, const TBlobPt& VDatBPt);
TBlobPt AddDat(
const TKey& Key,
const bool& ChangeFDat, const TFDat& FDat,
const bool& ChangeVDat, const TVDat& VDat);
public:
TFHash(const TStr& HashFNm, const TFAccess& _Access,
const int& Ports, const int& MxMemUsed);
~TFHash();
TFHash(TSIn&){Fail;}
static PFHash Load(TSIn&){Fail; return NULL;}
void Save(TSOut&){Fail;}
TFHash& operator=(const TFHash&){Fail; return *this;}
int GetMemUsed(){
return PortV.GetMemUsed()+(int)FHashKeyCache.GetMemUsed();} //TODO:64bit
void CacheFlushAndClr(){FHashKeyCache.FlushAndClr();}
bool Empty() const {return Keys==0;}
int Len() const {return Keys;}
TBlobPt AddFDat(const TKey& Key, const TFDat& FDat){
return AddKey(Key, true, FDat, false, TBlobPt());}
TBlobPt AddVDat(const TKey& Key, const TVDat& VDat){
return AddDat(Key, false, TFDat(), true, VDat);}
TBlobPt AddFVDat(const TKey& Key, const TFDat& FDat, const TVDat& VDat){
return AddDat(Key, true, FDat, true, VDat);}
void DelKey(const TKey& Key);
void DelKeyId(const TBlobPt& KeyId){
TKey Key; GetKey(KeyId, Key); DelKey(Key);}
void GetKey(const TBlobPt& KeyId, TKey& Key){
PHashKey FHashKey=GetFHashKey(KeyId); Key=FHashKey->Key;}
TBlobPt GetKeyId(const TKey& Key){
TBlobPt KeyId; PHashKey FHashKey; GetKeyInfo(Key, KeyId, FHashKey);
return KeyId;}
bool IsKey(const TKey& Key){
return !GetKeyId(Key).Empty();}
bool IsKey(const TKey& Key, TBlobPt& KeyId){
KeyId=GetKeyId(Key); return !KeyId.Empty();}
TBlobPt GetFDat(const TKey& Key, TFDat& FDat);
TBlobPt GetVDat(const TKey& Key, TVDat& VDat);
TBlobPt GetFVDat(const TKey& Key, TFDat& FDat, TVDat& VDat);
void GetKeyFDat(const TBlobPt& KeyId, TKey& Key, TFDat& FDat);
void GetKeyFVDat(const TBlobPt& KeyId, TKey& Key, TFDat& FDat, TVDat& VDat);
TBlobPt FFirstKeyId();
bool FNextKeyId(TBlobPt& TrvBlobPt, TBlobPt& KeyId);
friend class TFHashKey<TKey, TFDat, TVDat>;
friend class TPt<TFHash<TKey, TFDat, TVDat> >;
};
template <class TKey, class TFDat, class TVDat>
void TFHash<TKey, TFDat, TVDat>::GetKeyInfo(
const TKey& Key,
int& PortN, TBlobPt& PrevKeyId, TBlobPt& KeyId, PHashKey& FHashKey){
// prepare key data
PortN=abs(Key.GetPrimHashCd())%PortV.Len();
PrevKeyId.Clr();
KeyId=PortV[PortN];
// test if the key exists
if (!KeyId.Empty()){
FHashKey=GetFHashKey(KeyId);
while ((!KeyId.Empty())&&(FHashKey->Key!=Key)){
PrevKeyId=KeyId;
KeyId=FHashKey->Next;
if (!KeyId.Empty()){FHashKey=GetFHashKey(KeyId);}
}
}
}
template <class TKey, class TFDat, class TVDat>
TFHash<TKey, TFDat, TVDat>::TFHash(
const TStr& HashFNm, const TFAccess& _Access,
const int& Ports, const int& MxMemUsed):
Access(_Access), HashBBs(), PortV(), Keys(0),
FHashKeyCache(MxMemUsed, 100003, GetVoidThis()){
if (Access==faCreate){
IAssert(Ports>0);
// create blob-base
HashBBs=PBlobBs(new TGBlobBs(HashFNm, faCreate));
// save initial no. of keys and port-vector
PortV.Gen(Ports);
TMOut HdSOut; Keys.Save(HdSOut); PortV.Save(HdSOut);
HashBBs->PutBlob(HdSOut.GetSIn());
} else {
IAssert((Access==faUpdate)||(Access==faRdOnly));
IAssert(Ports==-1);
// open blob-base
HashBBs=PBlobBs(new TGBlobBs(HashFNm, Access));
// load initial no. of keys and port-vector
TBlobPt HdBPt=HashBBs->GetFirstBlobPt();
PSIn HdSIn=HashBBs->GetBlob(HdBPt);
Keys=TInt(*HdSIn);
PortV=TBlobPtV(*HdSIn);
}
}
template <class TKey, class TFDat, class TVDat>
TFHash<TKey, TFDat, TVDat>::~TFHash(){
if ((Access==faCreate)||(Access==faUpdate)){
// flush hash-key cache
FHashKeyCache.Flush();
// save port-vector
TBlobPt HdBPt=HashBBs->GetFirstBlobPt();
TMOut HdSOut; Keys.Save(HdSOut); PortV.Save(HdSOut);
HashBBs->PutBlob(HdBPt, HdSOut.GetSIn());
}
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::AddKey(
const TKey& Key,
const bool& ChangeFDat, const TFDat& FDat,
const bool& ChangeVDatBPt, const TBlobPt& VDatBPt){
// prepare key info
int PortN=-1; TBlobPt PrevKeyId; TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, PortN, PrevKeyId, KeyId, FHashKey);
if (KeyId.Empty()){
// generate key
FHashKey=PHashKey(new THashKey(TBlobPt(), Key, FDat, VDatBPt));
// save key to blob-base
TMOut FHashKeyMOut;
TInt(int(fhbtKey)).Save(FHashKeyMOut); FHashKey->Save(FHashKeyMOut);
TBlobPt FHashKeyBPt=HashBBs->PutBlob(FHashKeyMOut.GetSIn());
// save key to key-cache
FHashKeyCache.Put(FHashKeyBPt, FHashKey);
FHashKey->PutModified(false);
// connect key to the structure
KeyId=FHashKeyBPt;
Keys++;
if (PrevKeyId.Empty()){
PortV[PortN]=KeyId;
} else {
PHashKey PrevFHashKey=GetFHashKey(PrevKeyId);
PrevFHashKey->Next=KeyId;
PrevFHashKey->PutModified(true);
}
} else {
// update the data
if (ChangeFDat){FHashKey->FDat=FDat;}
if (ChangeVDatBPt){FHashKey->VDatBPt=VDatBPt;}
if (ChangeFDat||ChangeVDatBPt){
FHashKey->PutModified(true);}
}
return KeyId;
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::AddDat(
const TKey& Key,
const bool& ChangeFDat, const TFDat& FDat,
const bool& ChangeVDat, const TVDat& VDat){
// prepare key info
TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, KeyId, FHashKey);
// prepare new variable-data blob-pointer
TBlobPt VDatBPt;
if (ChangeVDat){
// save variable-data
TMOut VDatMOut;
TInt(int(fhbtVDat)).Save(VDatMOut); VDat.Save(VDatMOut);
if (KeyId.Empty()){
VDatBPt=HashBBs->PutBlob(VDatMOut.GetSIn());
} else {
VDatBPt=HashBBs->PutBlob(FHashKey->VDatBPt, VDatMOut.GetSIn());
}
}
// save the data
KeyId=AddKey(Key, ChangeFDat, FDat, ChangeVDat, VDatBPt);
return KeyId;
}
template <class TKey, class TFDat, class TVDat>
void TFHash<TKey, TFDat, TVDat>::DelKey(const TKey& Key){
// prepare key info
int PortN=-1; TBlobPt PrevKeyId; TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, PortN, PrevKeyId, KeyId, FHashKey);
// disconnect key
IAssert(!KeyId.Empty());
if (PrevKeyId.Empty()){
PortV[PortN]=FHashKey->Next;
} else {
PHashKey PrevFHashKey=GetFHashKey(PrevKeyId);
PrevFHashKey->Next=FHashKey->Next;
PrevFHashKey->PutModified(true);
}
// delete variable data
if (!FHashKey->VDatBPt.Empty()){
HashBBs->DelBlob(FHashKey->VDatBPt);}
// delete key/fixed data
HashBBs->DelBlob(KeyId);
FHashKeyCache.Del(KeyId, false);
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::GetFDat(
const TKey& Key, TFDat& FDat){
// prepare key info
TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, KeyId, FHashKey);
// get fixed data
FDat=FHashKey->FDat;
return KeyId;
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::GetVDat(const TKey& Key, TVDat& VDat){
// prepare key info
TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, KeyId, FHashKey);
// get variable data
PSIn SIn=HashBBs->GetBlob(FHashKey->VDatBPt);
TFHashBlobType Type=TFHashBlobType(int(TInt(*SIn))); IAssert(Type==fhbtVDat);
VDat=TVDat(*SIn);
return KeyId;
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::GetFVDat(
const TKey& Key, TFDat& FDat, TVDat& VDat){
// prepare key info
TBlobPt KeyId; PHashKey FHashKey;
GetKeyInfo(Key, KeyId, FHashKey);
// get fixed data
FDat=FHashKey->FDat;
// get variable data
PSIn SIn=HashBBs->GetBlob(FHashKey->VDatBPt);
TFHashBlobType Type=TFHashBlobType(int(TInt(*SIn))); IAssert(Type==fhbtVDat);
VDat=TVDat(*SIn);
return KeyId;
}
template <class TKey, class TFDat, class TVDat>
void TFHash<TKey, TFDat, TVDat>::GetKeyFDat(
const TBlobPt& KeyId, TKey& Key, TFDat& FDat){
// prepare key info
PHashKey FHashKey=GetFHashKey(KeyId);
// get key
Key=FHashKey->Key;
// get fixed data
FDat=FHashKey->FDat;
}
template <class TKey, class TFDat, class TVDat>
void TFHash<TKey, TFDat, TVDat>::GetKeyFVDat(
const TBlobPt& KeyId, TKey& Key, TFDat& FDat, TVDat& VDat){
// prepare key info
PHashKey FHashKey=GetFHashKey(KeyId);
// get key
Key=FHashKey->Key;
// get fixed data
FDat=FHashKey->FDat;
// get variable data
PSIn SIn=HashBBs->GetBlob(FHashKey->VDatBPt);
TFHashBlobType Type=TFHashBlobType(int(TInt(*SIn))); IAssert(Type==fhbtVDat);
VDat=TVDat(*SIn);
}
template <class TKey, class TFDat, class TVDat>
TBlobPt TFHash<TKey, TFDat, TVDat>::FFirstKeyId(){
return HashBBs->FFirstBlobPt();
}
template <class TKey, class TFDat, class TVDat>
bool TFHash<TKey, TFDat, TVDat>::FNextKeyId(
TBlobPt& TrvBlobPt, TBlobPt& KeyId){
PSIn SIn;
while (HashBBs->FNextBlobPt(TrvBlobPt, KeyId, SIn)){
TFHashBlobType Type=TFHashBlobType(int(TInt(*SIn)));
if (Type==fhbtKey){return true;}
}
return false;
}