1548.2.1
by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin. |
1 |
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
|
2 |
*
|
|
3 |
* PrimeBase Media Stream for MySQL
|
|
4 |
*
|
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
6 |
* it under the terms of the GNU General Public License as published by
|
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
8 |
* (at your option) any later version.
|
|
9 |
*
|
|
10 |
* This program is distributed in the hope that it will be useful,
|
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
* GNU General Public License for more details.
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License
|
|
16 |
* along with this program; if not, write to the Free Software
|
|
17 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18 |
*
|
|
19 |
* Barry Leslie
|
|
20 |
*
|
|
21 |
* 2008-12-30
|
|
22 |
*
|
|
23 |
* H&G2JCtL
|
|
24 |
*
|
|
25 |
* BLOB alias index.
|
|
26 |
*
|
|
27 |
*/
|
|
28 |
||
29 |
||
30 |
#ifndef __ALIAS_MS_H__
|
|
31 |
#define __ALIAS_MS_H__
|
|
32 |
#include <stddef.h> |
|
33 |
||
1548.2.10
by Barry.Leslie at PrimeBase
Merge from trunk. |
34 |
#include "defs_ms.h" |
1548.2.2
by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle. |
35 |
#include "cslib/CSStorage.h" |
1548.2.1
by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin. |
36 |
|
37 |
#define MS_ALIAS_FILE_MAGIC 0x5954228A
|
|
38 |
#define MS_ALIAS_FILE_VERSION 1
|
|
39 |
#define BLOB_ALIAS_LENGTH 1024
|
|
40 |
#define INVALID_ALIAS_HASH ((uint32_t)-1)
|
|
41 |
||
42 |
#ifdef HAVE_ALIAS_SUPPORT
|
|
43 |
class MSOpenTable; |
|
44 |
class MSDatabase; |
|
45 |
class CSHTTPOutputStream; |
|
46 |
class MSMetaDataTable; |
|
47 |
||
48 |
#define ACTIVE_ALIAS_INDEX "ms_blob_alias.idx"
|
|
49 |
||
50 |
#define NUM_RECORDS_PER_BUCKET 254 // 254 = bucket size of 4 K |
|
51 |
#define BUCKET_LIST_SIZE 1024
|
|
52 |
||
53 |
typedef struct MSAliasHead { |
|
54 |
CSDiskValue4 ah_magic_4; /* Table magic number. */ |
|
55 |
CSDiskValue2 ah_version_2; /* The header version. */ |
|
56 |
CSDiskValue2 ah_head_size_2; /* The size of the header. */ |
|
57 |
CSDiskValue8 ah_file_size_8; /* The size of the file. */ |
|
58 |
||
59 |
CSDiskValue8 ah_free_list_8; /* The offset of the first bucket in the free list. */ |
|
60 |
||
61 |
CSDiskValue2 ah_num_buckets_2; /* The number of bucket chains in the index. (BUCKET_LIST_SIZE when created)*/ |
|
62 |
CSDiskValue4 ah_bucket_size_4; /* The size of each bucket. (NUM_RECORDS_PER_BUCKET when created)*/ |
|
63 |
||
64 |
} MSAliasHeadRec, *MSAliasHeadPtr; |
|
65 |
||
66 |
/*
|
|
67 |
* When a record is freed ba_repo_id_4 is set to zero
|
|
68 |
*/
|
|
69 |
typedef struct MSDiskAliasRec { |
|
70 |
CSDiskValue4 ar_repo_id_4; /* File ID. Not zero when allocated. */ |
|
71 |
CSDiskValue8 ar_offset_8; /* Offset into the file of the BLOB. */ |
|
72 |
CSDiskValue4 ar_hash_4; /* The hash value of the alias string. (Is assumed to be at the end of the structure.*/ |
|
73 |
} MSDiskAliasRec, *MSDiskAliasPtr; |
|
74 |
||
75 |
typedef struct MSADiskBucketHead { |
|
76 |
CSDiskValue8 ab_prev_bucket_8; /* The file offset of the previouse bucket in the chain. */ |
|
77 |
CSDiskValue8 ab_next_bucket_8; /* The file offset of the next bucket in the chain. */ |
|
78 |
CSDiskValue4 ab_num_recs_4; /* The number of used record in the bucket. */ |
|
79 |
CSDiskValue4 ab_eor_rec_4; /* (End Of Records) The position of the first free record after all the records in the bucket. */ |
|
80 |
} MSADiskBucketHeadRec, *MSADiskBucketHeadPtr; |
|
81 |
||
82 |
typedef struct MSADiskBucket { |
|
83 |
MSADiskBucketHeadRec ab_heaher; |
|
84 |
MSDiskAliasRec ab_records[NUM_RECORDS_PER_BUCKET]; /* The start of the records in the bucket. */ |
|
85 |
} MSADiskBucketRec, *MSADiskBucketPtr; |
|
86 |
||
87 |
/*
|
|
88 |
* MSABucketInfo stores bucket information in RAM.
|
|
89 |
*/
|
|
90 |
class MSABucketInfo: public CSOrderKey { |
|
91 |
public: |
|
92 |
||
93 |
MSABucketInfo(uint64_t offset, uint32_t num, uint32_t end_of_records): |
|
94 |
bi_bucket_offset(offset), |
|
95 |
bi_records_offset(offset + offsetof(MSADiskBucketRec, ab_records)), |
|
96 |
bi_num_recs(num), |
|
97 |
bi_end_of_records(end_of_records), |
|
98 |
bi_NextLink(NULL), |
|
99 |
bi_PrevLink(NULL) |
|
100 |
{}
|
|
101 |
||
102 |
uint64_t bi_bucket_offset; /* The file offset of the bucket. */ |
|
103 |
||
104 |
uint64_t bi_records_offset; /* The file offset of the first record in the bucket. */ |
|
105 |
||
106 |
// Required method for item in a CSLinkedList.
|
|
107 |
virtual MSABucketInfo *getNextLink() { return bi_NextLink; } |
|
108 |
virtual MSABucketInfo *getPrevLink() { return bi_PrevLink; } |
|
109 |
virtual void setNextLink(CSObject *link) { bi_NextLink = (MSABucketInfo*)link; } |
|
110 |
virtual void setPrevLink(CSObject *link) { bi_PrevLink = (MSABucketInfo*)link; } |
|
111 |
||
112 |
virtual CSObject *getKey() { return this;} |
|
113 |
virtual int compareKey(CSOrderKey *x) { |
|
114 |
MSABucketInfo *key = (MSABucketInfo *) x; |
|
115 |
||
116 |
if (bi_bucket_offset != key->bi_bucket_offset) |
|
117 |
return 0; |
|
118 |
||
119 |
return (bi_bucket_offset < key->bi_bucket_offset)? -1: 1; |
|
120 |
}
|
|
121 |
||
122 |
static MSABucketInfo *newMSABucketInfo(uint64_t offset, uint32_t num = 0, uint32_t last = 0); |
|
123 |
||
124 |
uint32_t getSize() { return bi_num_recs;} |
|
125 |
uint32_t getEndOfRecords() { return bi_end_of_records;} |
|
126 |
void recAdded(CSFile *iFile, uint32_t idx); |
|
127 |
void recRemoved(CSFile *iFile, uint32_t idx, MSDiskAliasRec bucket[]); |
|
128 |
||
129 |
private: |
|
130 |
// (bi_end_of_records -1) is the index of the last valid record in the bucket.
|
|
131 |
// free records can actually appear any where in the bucket unless it has
|
|
132 |
// just been compressed.
|
|
133 |
uint32_t bi_num_recs; /* The number of records in the bucket. */ |
|
134 |
uint32_t bi_end_of_records; /* The index of the start of the free records in the bucket. */ |
|
135 |
||
136 |
MSABucketInfo *bi_NextLink; |
|
137 |
MSABucketInfo *bi_PrevLink; |
|
138 |
};
|
|
139 |
||
140 |
class MSABucketLinkedList: public CSLinkedList { |
|
141 |
public: |
|
142 |
||
143 |
/* Value is returned referenced. */
|
|
144 |
MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();} |
|
145 |
||
146 |
/* Value is returned NOT referenced. */
|
|
147 |
MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();} |
|
148 |
||
149 |
/* Value is returned NOT referenced. */
|
|
150 |
MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();} |
|
151 |
||
152 |
/* Value is returned referenced. */
|
|
153 |
MSABucketInfo *removeFront(){ return (MSABucketInfo*) CSLinkedList::removeFront();} |
|
154 |
};
|
|
155 |
||
156 |
typedef struct MSAliasRec { |
|
157 |
uint32_t repo_id; |
|
158 |
uint64_t repo_offset; |
|
159 |
uint32_t alias_hash; |
|
160 |
} MSAliasRec, *MSAliasPtr; |
|
161 |
||
162 |
class MSAliasFile : public CSPooled, public CSRefObject { |
|
163 |
public: |
|
164 |
class MSAliasFileShare *ba_share; |
|
165 |
bool ba_isFileInUse; |
|
166 |
MSAliasFile *ba_nextFile; /* Next file available in the pool */ |
|
167 |
||
168 |
MSAliasFile(MSAliasFileShare *share); |
|
169 |
virtual ~MSAliasFile(); |
|
170 |
||
171 |
// Required method for CSPool item.
|
|
172 |
virtual void returnToPool(); |
|
173 |
||
174 |
||
175 |
// Required method for item in a CSLinkedList.
|
|
176 |
virtual CSObject *getNextLink() { return ba_NextLink; } |
|
177 |
virtual CSObject *getPrevLink() { return ba_PrevLink; } |
|
178 |
virtual void setNextLink(CSObject *link) { ba_NextLink = link; } |
|
179 |
virtual void setPrevLink(CSObject *link) { ba_PrevLink = link; } |
|
180 |
||
181 |
// Index file operations.
|
|
182 |
MSDiskAliasPtr findRec(uint32_t hash); |
|
183 |
MSDiskAliasPtr nextRec(); |
|
184 |
void addRec(MSDiskAliasPtr rec); |
|
185 |
void deleteCurrentRec(); |
|
186 |
void updateCurrentRec(MSDiskAliasPtr rec); |
|
187 |
bool findRec(MSDiskAliasPtr rec); |
|
188 |
||
189 |
/* When a load is inprogress locks are not required and writes are batched. */
|
|
190 |
void startLoad(); |
|
191 |
void finishLoad(); |
|
192 |
||
193 |
||
194 |
private: |
|
195 |
bool nextBucket(bool with_space); |
|
196 |
||
197 |
bool scanBucket() |
|
198 |
{
|
|
199 |
while (iCurrentRec) { |
|
200 |
iCurrentRec--; |
|
201 |
if ( CS_EQ_DISK_4(iDiskHash_4, iBucket[iCurrentRec].ar_hash_4) |
|
202 |
&& !CS_IS_NULL_DISK_4(iBucket[iCurrentRec].ar_repo_id_4)) |
|
203 |
return true; |
|
204 |
}
|
|
205 |
return false; |
|
206 |
}
|
|
207 |
||
208 |
CSFile *iFile; // The index file. |
|
209 |
||
210 |
bool iLoading; |
|
211 |
MSADiskBucketRec *iBucketCache; // The bucket cache is used during index loading in single thread mode. |
|
212 |
MSDiskAliasRec iBucket[NUM_RECORDS_PER_BUCKET];// The current bucket loaded from disk. |
|
213 |
MSABucketLinkedList *iBucketChain; // The bucket list for the current hash value. |
|
214 |
MSABucketInfo *iStartBucket; // The file offset of the bucket the search started at. |
|
215 |
MSABucketInfo *iCurrentBucket;// The currnet bucket, NULL if no bucket is loaded. |
|
216 |
||
217 |
CSDiskValue4 iDiskHash_4; // The current hash value we are looking for in disk byte order. |
|
218 |
uint32_t iCurrentRec; // The current record position in the current bucket. |
|
219 |
||
220 |
CSObject *ba_NextLink; |
|
221 |
CSObject *ba_PrevLink; |
|
222 |
||
223 |
};
|
|
224 |
||
225 |
//===========================================
|
|
226 |
class MSAliasFileShare: public CSObject { |
|
227 |
public: |
|
228 |
MSAliasFileShare(CSPath *path): |
|
229 |
msa_filePath(path), |
|
230 |
msa_fileSize(0), |
|
231 |
msa_pool(NULL), |
|
232 |
msa_closing(false) |
|
233 |
{
|
|
234 |
bool isdir = false; |
|
235 |
if (path->exists(&isdir)) |
|
236 |
msa_fileSize = path->getSize(); |
|
237 |
}
|
|
238 |
||
239 |
~MSAliasFileShare() |
|
240 |
{
|
|
241 |
msa_poolFiles.clear(); |
|
242 |
if (msa_filePath) |
|
243 |
msa_filePath->release(); |
|
244 |
||
1548.2.2
by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle. |
245 |
for (uint32_t i =0; i < BUCKET_LIST_SIZE; i++) |
1548.2.1
by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin. |
246 |
msa_buckets[i].clear(); |
247 |
||
248 |
msa_empty_buckets.clear(); |
|
249 |
}
|
|
250 |
||
251 |
void close() { msa_poolFiles.clear();} |
|
252 |
||
253 |
MSABucketLinkedList *getBucketChain(uint32_t hash) { return msa_buckets + (hash % BUCKET_LIST_SIZE); } |
|
254 |
MSAliasFile *getPoolFile(); |
|
255 |
||
256 |
CSLinkedList msa_poolFiles; /* A list of all files in this pool */ |
|
257 |
uint64_t msa_fileSize; |
|
258 |
CSPath *msa_filePath; |
|
259 |
CSLock msa_writeLock; |
|
260 |
MSAliasFile *msa_pool; /* A list of files currently not in use. */ |
|
261 |
||
262 |
CSLock msa_poolLock; |
|
263 |
bool msa_closing; |
|
264 |
MSABucketLinkedList msa_empty_buckets; /* A list of unused buckets. */ |
|
265 |
||
266 |
MSABucketLinkedList msa_buckets[BUCKET_LIST_SIZE]; /* An array of bucket chains. */ |
|
267 |
};
|
|
268 |
||
269 |
//===========================================
|
|
270 |
class MSSysMeta : public CSRefObject, public CSPooled { |
|
271 |
public: |
|
272 |
class MSAlias *md_myMSAlias; |
|
273 |
bool md_isFileInUse; |
|
274 |
MSSysMeta *md_nextFile; /* Next file available in the pool */ |
|
275 |
||
276 |
MSSysMeta(MSAlias *msa); |
|
277 |
virtual ~MSSysMeta(); |
|
278 |
||
279 |
virtual void returnToPool(); |
|
280 |
||
281 |
virtual CSObject *getNextLink() { return md_NextLink; } |
|
282 |
virtual CSObject *getPrevLink() { return md_PrevLink; } |
|
283 |
virtual void setNextLink(CSObject *link) { md_NextLink = link; } |
|
284 |
virtual void setPrevLink(CSObject *link) { md_PrevLink = link; } |
|
285 |
||
286 |
bool matchAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias); |
|
287 |
||
288 |
private: |
|
289 |
MSMetaDataTable *mtab; |
|
290 |
CSObject *md_NextLink; |
|
291 |
CSObject *md_PrevLink; |
|
292 |
||
293 |
};
|
|
294 |
||
295 |
//===========================================
|
|
296 |
class MSAlias : public CSSharedRefObject { |
|
297 |
public: |
|
298 |
||
299 |
MSAlias(MSDatabase *db_noref); |
|
300 |
~MSAlias(); |
|
301 |
||
302 |
void ma_open(const char *file_name = ACTIVE_ALIAS_INDEX); |
|
303 |
void ma_close(); |
|
304 |
void ma_delete() {iDelete = true;} |
|
305 |
||
306 |
uint32_t addAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias); |
|
307 |
private: |
|
308 |
void addAlias(MSAliasFile *af, MSAliasRec *rec); |
|
309 |
public: |
|
310 |
void deleteAlias(MSDiskAliasPtr diskRec); |
|
311 |
void deleteAlias(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash); |
|
312 |
void resetAlias(uint32_t old_repo_id, uint64_t old_repo_offset, uint32_t alias_hash, uint32_t new_repo_id, uint64_t new_repo_offset); |
|
313 |
||
314 |
bool findBlobByAlias(const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL); |
|
315 |
bool blobAliasExists(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash); |
|
316 |
private: |
|
317 |
bool findBlobByAlias(MSAliasFile *af, const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL); |
|
318 |
public: |
|
319 |
static uint32_t hashAlias(const char *ptr); |
|
320 |
||
321 |
void MSAliasBuild(); |
|
322 |
||
323 |
friend class MSAliasFile; |
|
324 |
friend class MSSysMeta; |
|
325 |
||
326 |
private: |
|
327 |
MSDatabase *iDatabase_br; // This is a back reference so this reference is not counted. |
|
328 |
CSPath *iFilePath; |
|
329 |
||
330 |
bool iClosing; |
|
331 |
bool iDelete; // true when the alias index file should be deleted. |
|
332 |
||
333 |
MSAliasFileShare *iFileShare; // File information shared between all files in the pool. |
|
334 |
||
335 |
CSLock iSysTablePoolLock; |
|
336 |
MSSysMeta *iSysTablePool; /* A list of files currently not in use. */ |
|
337 |
CSLinkedList iPoolSysTables; /* A list of all files in this pool */ |
|
338 |
||
339 |
MSAliasFile *getAliasFile() { return iFileShare->getPoolFile();} |
|
340 |
void buildAliasIndex(); |
|
341 |
void MSAliasCompress(CSFile *fa, CSSortedList *freeList, MSABucketLinkedList *bucketChain); |
|
342 |
void MSAliasLoad(); |
|
343 |
bool hasBlobAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias, bool *referenced); |
|
344 |
};
|
|
345 |
||
346 |
||
347 |
#endif //HAVE_ALIAS_SUPPORT |
|
348 |
||
349 |
#endif // __ALIAS_MS_H__ |