00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #pragma once
00031 #ifndef __ALIAS_MS_H__
00032 #define __ALIAS_MS_H__
00033 #include <stddef.h>
00034
00035 #include "defs_ms.h"
00036 #include "cslib/CSStorage.h"
00037
00038 #define MS_ALIAS_FILE_MAGIC 0x5954228A
00039 #define MS_ALIAS_FILE_VERSION 1
00040 #define BLOB_ALIAS_LENGTH 1024
00041 #define INVALID_ALIAS_HASH ((uint32_t)-1)
00042
00043 #ifdef HAVE_ALIAS_SUPPORT
00044 class MSOpenTable;
00045 class MSDatabase;
00046 class CSHTTPOutputStream;
00047 class MSMetaDataTable;
00048
00049 #define ACTIVE_ALIAS_INDEX "ms_blob_alias.idx"
00050
00051 #define NUM_RECORDS_PER_BUCKET 254 // 254 = bucket size of 4 K
00052 #define BUCKET_LIST_SIZE 1024
00053
00054 typedef struct MSAliasHead {
00055 CSDiskValue4 ah_magic_4;
00056 CSDiskValue2 ah_version_2;
00057 CSDiskValue2 ah_head_size_2;
00058 CSDiskValue8 ah_file_size_8;
00059
00060 CSDiskValue8 ah_free_list_8;
00061
00062 CSDiskValue2 ah_num_buckets_2;
00063 CSDiskValue4 ah_bucket_size_4;
00064
00065 } MSAliasHeadRec, *MSAliasHeadPtr;
00066
00067
00068
00069
00070 typedef struct MSDiskAliasRec {
00071 CSDiskValue4 ar_repo_id_4;
00072 CSDiskValue8 ar_offset_8;
00073 CSDiskValue4 ar_hash_4;
00074 } MSDiskAliasRec, *MSDiskAliasPtr;
00075
00076 typedef struct MSADiskBucketHead {
00077 CSDiskValue8 ab_prev_bucket_8;
00078 CSDiskValue8 ab_next_bucket_8;
00079 CSDiskValue4 ab_num_recs_4;
00080 CSDiskValue4 ab_eor_rec_4;
00081 } MSADiskBucketHeadRec, *MSADiskBucketHeadPtr;
00082
00083 typedef struct MSADiskBucket {
00084 MSADiskBucketHeadRec ab_heaher;
00085 MSDiskAliasRec ab_records[NUM_RECORDS_PER_BUCKET];
00086 } MSADiskBucketRec, *MSADiskBucketPtr;
00087
00088
00089
00090
00091 class MSABucketInfo: public CSOrderKey {
00092 public:
00093
00094 MSABucketInfo(uint64_t offset, uint32_t num, uint32_t end_of_records):
00095 bi_bucket_offset(offset),
00096 bi_records_offset(offset + offsetof(MSADiskBucketRec, ab_records)),
00097 bi_num_recs(num),
00098 bi_end_of_records(end_of_records),
00099 bi_NextLink(NULL),
00100 bi_PrevLink(NULL)
00101 {}
00102
00103 uint64_t bi_bucket_offset;
00104
00105 uint64_t bi_records_offset;
00106
00107
00108 virtual MSABucketInfo *getNextLink() { return bi_NextLink; }
00109 virtual MSABucketInfo *getPrevLink() { return bi_PrevLink; }
00110 virtual void setNextLink(CSObject *link) { bi_NextLink = (MSABucketInfo*)link; }
00111 virtual void setPrevLink(CSObject *link) { bi_PrevLink = (MSABucketInfo*)link; }
00112
00113 virtual CSObject *getKey() { return this;}
00114 virtual int compareKey(CSOrderKey *x) {
00115 MSABucketInfo *key = (MSABucketInfo *) x;
00116
00117 if (bi_bucket_offset != key->bi_bucket_offset)
00118 return 0;
00119
00120 return (bi_bucket_offset < key->bi_bucket_offset)? -1: 1;
00121 }
00122
00123 static MSABucketInfo *newMSABucketInfo(uint64_t offset, uint32_t num = 0, uint32_t last = 0);
00124
00125 uint32_t getSize() { return bi_num_recs;}
00126 uint32_t getEndOfRecords() { return bi_end_of_records;}
00127 void recAdded(CSFile *iFile, uint32_t idx);
00128 void recRemoved(CSFile *iFile, uint32_t idx, MSDiskAliasRec bucket[]);
00129
00130 private:
00131
00132
00133
00134 uint32_t bi_num_recs;
00135 uint32_t bi_end_of_records;
00136
00137 MSABucketInfo *bi_NextLink;
00138 MSABucketInfo *bi_PrevLink;
00139 };
00140
00141 class MSABucketLinkedList: public CSLinkedList {
00142 public:
00143
00144
00145 MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();}
00146
00147
00148 MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();}
00149
00150
00151 MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();}
00152
00153
00154 MSABucketInfo *removeFront(){ return (MSABucketInfo*) CSLinkedList::removeFront();}
00155 };
00156
00157 typedef struct MSAliasRec {
00158 uint32_t repo_id;
00159 uint64_t repo_offset;
00160 uint32_t alias_hash;
00161 } MSAliasRec, *MSAliasPtr;
00162
00163 class MSAliasFile : public CSPooled, public CSRefObject {
00164 public:
00165 class MSAliasFileShare *ba_share;
00166 bool ba_isFileInUse;
00167 MSAliasFile *ba_nextFile;
00168
00169 MSAliasFile(MSAliasFileShare *share);
00170 virtual ~MSAliasFile();
00171
00172
00173 virtual void returnToPool();
00174
00175
00176
00177 virtual CSObject *getNextLink() { return ba_NextLink; }
00178 virtual CSObject *getPrevLink() { return ba_PrevLink; }
00179 virtual void setNextLink(CSObject *link) { ba_NextLink = link; }
00180 virtual void setPrevLink(CSObject *link) { ba_PrevLink = link; }
00181
00182
00183 MSDiskAliasPtr findRec(uint32_t hash);
00184 MSDiskAliasPtr nextRec();
00185 void addRec(MSDiskAliasPtr rec);
00186 void deleteCurrentRec();
00187 void updateCurrentRec(MSDiskAliasPtr rec);
00188 bool findRec(MSDiskAliasPtr rec);
00189
00190
00191 void startLoad();
00192 void finishLoad();
00193
00194
00195 private:
00196 bool nextBucket(bool with_space);
00197
00198 bool scanBucket()
00199 {
00200 while (iCurrentRec) {
00201 iCurrentRec--;
00202 if ( CS_EQ_DISK_4(iDiskHash_4, iBucket[iCurrentRec].ar_hash_4)
00203 && !CS_IS_NULL_DISK_4(iBucket[iCurrentRec].ar_repo_id_4))
00204 return true;
00205 }
00206 return false;
00207 }
00208
00209 CSFile *iFile;
00210
00211 bool iLoading;
00212 MSADiskBucketRec *iBucketCache;
00213 MSDiskAliasRec iBucket[NUM_RECORDS_PER_BUCKET];
00214 MSABucketLinkedList *iBucketChain;
00215 MSABucketInfo *iStartBucket;
00216 MSABucketInfo *iCurrentBucket;
00217
00218 CSDiskValue4 iDiskHash_4;
00219 uint32_t iCurrentRec;
00220
00221 CSObject *ba_NextLink;
00222 CSObject *ba_PrevLink;
00223
00224 };
00225
00226
00227 class MSAliasFileShare: public CSObject {
00228 public:
00229 MSAliasFileShare(CSPath *path):
00230 msa_filePath(path),
00231 msa_fileSize(0),
00232 msa_pool(NULL),
00233 msa_closing(false)
00234 {
00235 bool isdir = false;
00236 if (path->exists(&isdir))
00237 msa_fileSize = path->getSize();
00238 }
00239
00240 ~MSAliasFileShare()
00241 {
00242 msa_poolFiles.clear();
00243 if (msa_filePath)
00244 msa_filePath->release();
00245
00246 for (uint32_t i =0; i < BUCKET_LIST_SIZE; i++)
00247 msa_buckets[i].clear();
00248
00249 msa_empty_buckets.clear();
00250 }
00251
00252 void close() { msa_poolFiles.clear();}
00253
00254 MSABucketLinkedList *getBucketChain(uint32_t hash) { return msa_buckets + (hash % BUCKET_LIST_SIZE); }
00255 MSAliasFile *getPoolFile();
00256
00257 CSLinkedList msa_poolFiles;
00258 uint64_t msa_fileSize;
00259 CSPath *msa_filePath;
00260 CSLock msa_writeLock;
00261 MSAliasFile *msa_pool;
00262
00263 CSLock msa_poolLock;
00264 bool msa_closing;
00265 MSABucketLinkedList msa_empty_buckets;
00266
00267 MSABucketLinkedList msa_buckets[BUCKET_LIST_SIZE];
00268 };
00269
00270
00271 class MSSysMeta : public CSRefObject, public CSPooled {
00272 public:
00273 class MSAlias *md_myMSAlias;
00274 bool md_isFileInUse;
00275 MSSysMeta *md_nextFile;
00276
00277 MSSysMeta(MSAlias *msa);
00278 virtual ~MSSysMeta();
00279
00280 virtual void returnToPool();
00281
00282 virtual CSObject *getNextLink() { return md_NextLink; }
00283 virtual CSObject *getPrevLink() { return md_PrevLink; }
00284 virtual void setNextLink(CSObject *link) { md_NextLink = link; }
00285 virtual void setPrevLink(CSObject *link) { md_PrevLink = link; }
00286
00287 bool matchAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
00288
00289 private:
00290 MSMetaDataTable *mtab;
00291 CSObject *md_NextLink;
00292 CSObject *md_PrevLink;
00293
00294 };
00295
00296
00297 class MSAlias : public CSSharedRefObject {
00298 public:
00299
00300 MSAlias(MSDatabase *db_noref);
00301 ~MSAlias();
00302
00303 void ma_open(const char *file_name = ACTIVE_ALIAS_INDEX);
00304 void ma_close();
00305 void ma_delete() {iDelete = true;}
00306
00307 uint32_t addAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
00308 private:
00309 void addAlias(MSAliasFile *af, MSAliasRec *rec);
00310 public:
00311 void deleteAlias(MSDiskAliasPtr diskRec);
00312 void deleteAlias(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
00313 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);
00314
00315 bool findBlobByAlias(const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
00316 bool blobAliasExists(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
00317 private:
00318 bool findBlobByAlias(MSAliasFile *af, const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
00319 public:
00320 static uint32_t hashAlias(const char *ptr);
00321
00322 void MSAliasBuild();
00323
00324 friend class MSAliasFile;
00325 friend class MSSysMeta;
00326
00327 private:
00328 MSDatabase *iDatabase_br;
00329 CSPath *iFilePath;
00330
00331 bool iClosing;
00332 bool iDelete;
00333
00334 MSAliasFileShare *iFileShare;
00335
00336 CSLock iSysTablePoolLock;
00337 MSSysMeta *iSysTablePool;
00338 CSLinkedList iPoolSysTables;
00339
00340 MSAliasFile *getAliasFile() { return iFileShare->getPoolFile();}
00341 void buildAliasIndex();
00342 void MSAliasCompress(CSFile *fa, CSSortedList *freeList, MSABucketLinkedList *bucketChain);
00343 void MSAliasLoad();
00344 bool hasBlobAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias, bool *referenced);
00345 };
00346
00347
00348 #endif //HAVE_ALIAS_SUPPORT
00349
00350 #endif // __ALIAS_MS_H__