1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31
#ifndef __ALIAS_MS_H__
32
#define __ALIAS_MS_H__
36
#include "cslib/CSStorage.h"
38
#define MS_ALIAS_FILE_MAGIC 0x5954228A
39
#define MS_ALIAS_FILE_VERSION 1
40
#define BLOB_ALIAS_LENGTH 1024
41
#define INVALID_ALIAS_HASH ((uint32_t)-1)
43
#ifdef HAVE_ALIAS_SUPPORT
46
class CSHTTPOutputStream;
47
class MSMetaDataTable;
49
#define ACTIVE_ALIAS_INDEX "ms_blob_alias.idx"
51
#define NUM_RECORDS_PER_BUCKET 254 // 254 = bucket size of 4 K
52
#define BUCKET_LIST_SIZE 1024
54
typedef struct MSAliasHead {
55
CSDiskValue4 ah_magic_4; /* Table magic number. */
56
CSDiskValue2 ah_version_2; /* The header version. */
57
CSDiskValue2 ah_head_size_2; /* The size of the header. */
58
CSDiskValue8 ah_file_size_8; /* The size of the file. */
60
CSDiskValue8 ah_free_list_8; /* The offset of the first bucket in the free list. */
62
CSDiskValue2 ah_num_buckets_2; /* The number of bucket chains in the index. (BUCKET_LIST_SIZE when created)*/
63
CSDiskValue4 ah_bucket_size_4; /* The size of each bucket. (NUM_RECORDS_PER_BUCKET when created)*/
65
} MSAliasHeadRec, *MSAliasHeadPtr;
68
* When a record is freed ba_repo_id_4 is set to zero
70
typedef struct MSDiskAliasRec {
71
CSDiskValue4 ar_repo_id_4; /* File ID. Not zero when allocated. */
72
CSDiskValue8 ar_offset_8; /* Offset into the file of the BLOB. */
73
CSDiskValue4 ar_hash_4; /* The hash value of the alias string. (Is assumed to be at the end of the structure.*/
74
} MSDiskAliasRec, *MSDiskAliasPtr;
76
typedef struct MSADiskBucketHead {
77
CSDiskValue8 ab_prev_bucket_8; /* The file offset of the previouse bucket in the chain. */
78
CSDiskValue8 ab_next_bucket_8; /* The file offset of the next bucket in the chain. */
79
CSDiskValue4 ab_num_recs_4; /* The number of used record in the bucket. */
80
CSDiskValue4 ab_eor_rec_4; /* (End Of Records) The position of the first free record after all the records in the bucket. */
81
} MSADiskBucketHeadRec, *MSADiskBucketHeadPtr;
83
typedef struct MSADiskBucket {
84
MSADiskBucketHeadRec ab_heaher;
85
MSDiskAliasRec ab_records[NUM_RECORDS_PER_BUCKET]; /* The start of the records in the bucket. */
86
} MSADiskBucketRec, *MSADiskBucketPtr;
89
* MSABucketInfo stores bucket information in RAM.
91
class MSABucketInfo: public CSOrderKey {
94
MSABucketInfo(uint64_t offset, uint32_t num, uint32_t end_of_records):
95
bi_bucket_offset(offset),
96
bi_records_offset(offset + offsetof(MSADiskBucketRec, ab_records)),
98
bi_end_of_records(end_of_records),
103
uint64_t bi_bucket_offset; /* The file offset of the bucket. */
105
uint64_t bi_records_offset; /* The file offset of the first record in the bucket. */
107
// Required method for item in a CSLinkedList.
108
virtual MSABucketInfo *getNextLink() { return bi_NextLink; }
109
virtual MSABucketInfo *getPrevLink() { return bi_PrevLink; }
110
virtual void setNextLink(CSObject *link) { bi_NextLink = (MSABucketInfo*)link; }
111
virtual void setPrevLink(CSObject *link) { bi_PrevLink = (MSABucketInfo*)link; }
113
virtual CSObject *getKey() { return this;}
114
virtual int compareKey(CSOrderKey *x) {
115
MSABucketInfo *key = (MSABucketInfo *) x;
117
if (bi_bucket_offset != key->bi_bucket_offset)
120
return (bi_bucket_offset < key->bi_bucket_offset)? -1: 1;
123
static MSABucketInfo *newMSABucketInfo(uint64_t offset, uint32_t num = 0, uint32_t last = 0);
125
uint32_t getSize() { return bi_num_recs;}
126
uint32_t getEndOfRecords() { return bi_end_of_records;}
127
void recAdded(CSFile *iFile, uint32_t idx);
128
void recRemoved(CSFile *iFile, uint32_t idx, MSDiskAliasRec bucket[]);
131
// (bi_end_of_records -1) is the index of the last valid record in the bucket.
132
// free records can actually appear any where in the bucket unless it has
133
// just been compressed.
134
uint32_t bi_num_recs; /* The number of records in the bucket. */
135
uint32_t bi_end_of_records; /* The index of the start of the free records in the bucket. */
137
MSABucketInfo *bi_NextLink;
138
MSABucketInfo *bi_PrevLink;
141
class MSABucketLinkedList: public CSLinkedList {
144
/* Value is returned referenced. */
145
MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();}
147
/* Value is returned NOT referenced. */
148
MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();}
150
/* Value is returned NOT referenced. */
151
MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();}
153
/* Value is returned referenced. */
154
MSABucketInfo *removeFront(){ return (MSABucketInfo*) CSLinkedList::removeFront();}
157
typedef struct MSAliasRec {
159
uint64_t repo_offset;
161
} MSAliasRec, *MSAliasPtr;
163
class MSAliasFile : public CSPooled, public CSRefObject {
165
class MSAliasFileShare *ba_share;
167
MSAliasFile *ba_nextFile; /* Next file available in the pool */
169
MSAliasFile(MSAliasFileShare *share);
170
virtual ~MSAliasFile();
172
// Required method for CSPool item.
173
virtual void returnToPool();
176
// Required method for item in a CSLinkedList.
177
virtual CSObject *getNextLink() { return ba_NextLink; }
178
virtual CSObject *getPrevLink() { return ba_PrevLink; }
179
virtual void setNextLink(CSObject *link) { ba_NextLink = link; }
180
virtual void setPrevLink(CSObject *link) { ba_PrevLink = link; }
182
// Index file operations.
183
MSDiskAliasPtr findRec(uint32_t hash);
184
MSDiskAliasPtr nextRec();
185
void addRec(MSDiskAliasPtr rec);
186
void deleteCurrentRec();
187
void updateCurrentRec(MSDiskAliasPtr rec);
188
bool findRec(MSDiskAliasPtr rec);
190
/* When a load is inprogress locks are not required and writes are batched. */
196
bool nextBucket(bool with_space);
200
while (iCurrentRec) {
202
if ( CS_EQ_DISK_4(iDiskHash_4, iBucket[iCurrentRec].ar_hash_4)
203
&& !CS_IS_NULL_DISK_4(iBucket[iCurrentRec].ar_repo_id_4))
209
CSFile *iFile; // The index file.
212
MSADiskBucketRec *iBucketCache; // The bucket cache is used during index loading in single thread mode.
213
MSDiskAliasRec iBucket[NUM_RECORDS_PER_BUCKET];// The current bucket loaded from disk.
214
MSABucketLinkedList *iBucketChain; // The bucket list for the current hash value.
215
MSABucketInfo *iStartBucket; // The file offset of the bucket the search started at.
216
MSABucketInfo *iCurrentBucket;// The currnet bucket, NULL if no bucket is loaded.
218
CSDiskValue4 iDiskHash_4; // The current hash value we are looking for in disk byte order.
219
uint32_t iCurrentRec; // The current record position in the current bucket.
221
CSObject *ba_NextLink;
222
CSObject *ba_PrevLink;
226
//===========================================
227
class MSAliasFileShare: public CSObject {
229
MSAliasFileShare(CSPath *path):
236
if (path->exists(&isdir))
237
msa_fileSize = path->getSize();
242
msa_poolFiles.clear();
244
msa_filePath->release();
246
for (uint32_t i =0; i < BUCKET_LIST_SIZE; i++)
247
msa_buckets[i].clear();
249
msa_empty_buckets.clear();
252
void close() { msa_poolFiles.clear();}
254
MSABucketLinkedList *getBucketChain(uint32_t hash) { return msa_buckets + (hash % BUCKET_LIST_SIZE); }
255
MSAliasFile *getPoolFile();
257
CSLinkedList msa_poolFiles; /* A list of all files in this pool */
258
uint64_t msa_fileSize;
259
CSPath *msa_filePath;
260
CSLock msa_writeLock;
261
MSAliasFile *msa_pool; /* A list of files currently not in use. */
265
MSABucketLinkedList msa_empty_buckets; /* A list of unused buckets. */
267
MSABucketLinkedList msa_buckets[BUCKET_LIST_SIZE]; /* An array of bucket chains. */
270
//===========================================
271
class MSSysMeta : public CSRefObject, public CSPooled {
273
class MSAlias *md_myMSAlias;
275
MSSysMeta *md_nextFile; /* Next file available in the pool */
277
MSSysMeta(MSAlias *msa);
278
virtual ~MSSysMeta();
280
virtual void returnToPool();
282
virtual CSObject *getNextLink() { return md_NextLink; }
283
virtual CSObject *getPrevLink() { return md_PrevLink; }
284
virtual void setNextLink(CSObject *link) { md_NextLink = link; }
285
virtual void setPrevLink(CSObject *link) { md_PrevLink = link; }
287
bool matchAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
290
MSMetaDataTable *mtab;
291
CSObject *md_NextLink;
292
CSObject *md_PrevLink;
296
//===========================================
297
class MSAlias : public CSSharedRefObject {
300
MSAlias(MSDatabase *db_noref);
303
void ma_open(const char *file_name = ACTIVE_ALIAS_INDEX);
305
void ma_delete() {iDelete = true;}
307
uint32_t addAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
309
void addAlias(MSAliasFile *af, MSAliasRec *rec);
311
void deleteAlias(MSDiskAliasPtr diskRec);
312
void deleteAlias(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
313
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);
315
bool findBlobByAlias(const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
316
bool blobAliasExists(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
318
bool findBlobByAlias(MSAliasFile *af, const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
320
static uint32_t hashAlias(const char *ptr);
324
friend class MSAliasFile;
325
friend class MSSysMeta;
328
MSDatabase *iDatabase_br; // This is a back reference so this reference is not counted.
332
bool iDelete; // true when the alias index file should be deleted.
334
MSAliasFileShare *iFileShare; // File information shared between all files in the pool.
336
CSLock iSysTablePoolLock;
337
MSSysMeta *iSysTablePool; /* A list of files currently not in use. */
338
CSLinkedList iPoolSysTables; /* A list of all files in this pool */
340
MSAliasFile *getAliasFile() { return iFileShare->getPoolFile();}
341
void buildAliasIndex();
342
void MSAliasCompress(CSFile *fa, CSSortedList *freeList, MSABucketLinkedList *bucketChain);
344
bool hasBlobAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias, bool *referenced);
348
#endif //HAVE_ALIAS_SUPPORT
350
#endif // __ALIAS_MS_H__