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
30
#ifndef __ALIAS_MS_H__
31
#define __ALIAS_MS_H__
35
#include "cslib/CSStorage.h"
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)
42
#ifdef HAVE_ALIAS_SUPPORT
45
class CSHTTPOutputStream;
46
class MSMetaDataTable;
48
#define ACTIVE_ALIAS_INDEX "ms_blob_alias.idx"
50
#define NUM_RECORDS_PER_BUCKET 254 // 254 = bucket size of 4 K
51
#define BUCKET_LIST_SIZE 1024
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. */
59
CSDiskValue8 ah_free_list_8; /* The offset of the first bucket in the free list. */
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)*/
64
} MSAliasHeadRec, *MSAliasHeadPtr;
67
* When a record is freed ba_repo_id_4 is set to zero
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;
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;
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;
88
* MSABucketInfo stores bucket information in RAM.
90
class MSABucketInfo: public CSOrderKey {
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)),
97
bi_end_of_records(end_of_records),
102
uint64_t bi_bucket_offset; /* The file offset of the bucket. */
104
uint64_t bi_records_offset; /* The file offset of the first record in the bucket. */
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; }
112
virtual CSObject *getKey() { return this;}
113
virtual int compareKey(CSOrderKey *x) {
114
MSABucketInfo *key = (MSABucketInfo *) x;
116
if (bi_bucket_offset != key->bi_bucket_offset)
119
return (bi_bucket_offset < key->bi_bucket_offset)? -1: 1;
122
static MSABucketInfo *newMSABucketInfo(uint64_t offset, uint32_t num = 0, uint32_t last = 0);
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[]);
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. */
136
MSABucketInfo *bi_NextLink;
137
MSABucketInfo *bi_PrevLink;
140
class MSABucketLinkedList: public CSLinkedList {
143
/* Value is returned referenced. */
144
MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();}
146
/* Value is returned NOT referenced. */
147
MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();}
149
/* Value is returned NOT referenced. */
150
MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();}
152
/* Value is returned referenced. */
153
MSABucketInfo *removeFront(){ return (MSABucketInfo*) CSLinkedList::removeFront();}
156
typedef struct MSAliasRec {
158
uint64_t repo_offset;
160
} MSAliasRec, *MSAliasPtr;
162
class MSAliasFile : public CSPooled, public CSRefObject {
164
class MSAliasFileShare *ba_share;
166
MSAliasFile *ba_nextFile; /* Next file available in the pool */
168
MSAliasFile(MSAliasFileShare *share);
169
virtual ~MSAliasFile();
171
// Required method for CSPool item.
172
virtual void returnToPool();
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; }
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);
189
/* When a load is inprogress locks are not required and writes are batched. */
195
bool nextBucket(bool with_space);
199
while (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))
208
CSFile *iFile; // The index file.
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.
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.
220
CSObject *ba_NextLink;
221
CSObject *ba_PrevLink;
225
//===========================================
226
class MSAliasFileShare: public CSObject {
228
MSAliasFileShare(CSPath *path):
235
if (path->exists(&isdir))
236
msa_fileSize = path->getSize();
241
msa_poolFiles.clear();
243
msa_filePath->release();
245
for (uint32_t i =0; i < BUCKET_LIST_SIZE; i++)
246
msa_buckets[i].clear();
248
msa_empty_buckets.clear();
251
void close() { msa_poolFiles.clear();}
253
MSABucketLinkedList *getBucketChain(uint32_t hash) { return msa_buckets + (hash % BUCKET_LIST_SIZE); }
254
MSAliasFile *getPoolFile();
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. */
264
MSABucketLinkedList msa_empty_buckets; /* A list of unused buckets. */
266
MSABucketLinkedList msa_buckets[BUCKET_LIST_SIZE]; /* An array of bucket chains. */
269
//===========================================
270
class MSSysMeta : public CSRefObject, public CSPooled {
272
class MSAlias *md_myMSAlias;
274
MSSysMeta *md_nextFile; /* Next file available in the pool */
276
MSSysMeta(MSAlias *msa);
277
virtual ~MSSysMeta();
279
virtual void returnToPool();
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; }
286
bool matchAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
289
MSMetaDataTable *mtab;
290
CSObject *md_NextLink;
291
CSObject *md_PrevLink;
295
//===========================================
296
class MSAlias : public CSSharedRefObject {
299
MSAlias(MSDatabase *db_noref);
302
void ma_open(const char *file_name = ACTIVE_ALIAS_INDEX);
304
void ma_delete() {iDelete = true;}
306
uint32_t addAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
308
void addAlias(MSAliasFile *af, MSAliasRec *rec);
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);
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);
317
bool findBlobByAlias(MSAliasFile *af, const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
319
static uint32_t hashAlias(const char *ptr);
323
friend class MSAliasFile;
324
friend class MSSysMeta;
327
MSDatabase *iDatabase_br; // This is a back reference so this reference is not counted.
331
bool iDelete; // true when the alias index file should be deleted.
333
MSAliasFileShare *iFileShare; // File information shared between all files in the pool.
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 */
339
MSAliasFile *getAliasFile() { return iFileShare->getPoolFile();}
340
void buildAliasIndex();
341
void MSAliasCompress(CSFile *fa, CSSortedList *freeList, MSABucketLinkedList *bucketChain);
343
bool hasBlobAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias, bool *referenced);
347
#endif //HAVE_ALIAS_SUPPORT
349
#endif // __ALIAS_MS_H__