Drizzled Public API Documentation

alias_ms.h
00001 /* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase Media Stream for MySQL
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  * Barry Leslie
00020  *
00021  * 2008-12-30
00022  *
00023  * H&G2JCtL
00024  *
00025  * BLOB alias index.
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;             /* Table magic number. */
00056   CSDiskValue2      ah_version_2;           /* The header version. */
00057   CSDiskValue2      ah_head_size_2;           /* The size of the header. */
00058   CSDiskValue8      ah_file_size_8;           /* The size of the file. */ 
00059   
00060   CSDiskValue8      ah_free_list_8;           /* The offset of the first bucket in the free list. */
00061   
00062   CSDiskValue2      ah_num_buckets_2;         /* The number of bucket chains in the index. (BUCKET_LIST_SIZE when created)*/  
00063   CSDiskValue4      ah_bucket_size_4;         /* The size of each bucket. (NUM_RECORDS_PER_BUCKET when created)*/
00064 
00065 } MSAliasHeadRec, *MSAliasHeadPtr;
00066 
00067 /*
00068  * When a record is freed  ba_repo_id_4 is set to zero 
00069 */
00070 typedef struct MSDiskAliasRec {
00071   CSDiskValue4      ar_repo_id_4;           /* File ID. Not zero when allocated. */
00072   CSDiskValue8      ar_offset_8;            /* Offset into the file of the BLOB. */
00073   CSDiskValue4      ar_hash_4;              /* The hash value of the alias string. (Is assumed to be at the end of the structure.*/
00074 } MSDiskAliasRec, *MSDiskAliasPtr;
00075 
00076 typedef struct MSADiskBucketHead {
00077   CSDiskValue8      ab_prev_bucket_8;         /* The file offset of the previouse bucket in the chain. */
00078   CSDiskValue8      ab_next_bucket_8;         /* The file offset of the next bucket in the chain. */
00079   CSDiskValue4      ab_num_recs_4;            /* The number of used record in the bucket. */
00080   CSDiskValue4      ab_eor_rec_4;           /* (End Of Records) The position of the first free record after all the records in the bucket. */
00081 } MSADiskBucketHeadRec, *MSADiskBucketHeadPtr;
00082 
00083 typedef struct MSADiskBucket {
00084   MSADiskBucketHeadRec  ab_heaher;
00085   MSDiskAliasRec      ab_records[NUM_RECORDS_PER_BUCKET]; /* The start of the records in the bucket. */
00086 } MSADiskBucketRec, *MSADiskBucketPtr;
00087 
00088 /*
00089  * MSABucketInfo stores bucket information in RAM.
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; /* The file offset of the bucket. */
00104 
00105   uint64_t      bi_records_offset;  /* The file offset of the first record in the bucket. */
00106   
00107   // Required method for item in a CSLinkedList.
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   // (bi_end_of_records -1) is the index of the last valid record in the bucket.
00132   // free records can actually appear any where in the bucket unless it has
00133   // just been compressed.
00134   uint32_t      bi_num_recs;    /* The number of records in the bucket. */
00135   uint32_t      bi_end_of_records;  /* The index of the start of the free records in the bucket. */
00136 
00137   MSABucketInfo *bi_NextLink;
00138   MSABucketInfo *bi_PrevLink;
00139 };
00140 
00141 class MSABucketLinkedList: public CSLinkedList {
00142 public:
00143 
00144   /* Value is returned referenced. */
00145   MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();}
00146 
00147   /* Value is returned NOT referenced. */
00148   MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();}
00149 
00150   /* Value is returned NOT referenced. */
00151   MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();}
00152 
00153   /* Value is returned referenced. */
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;                 /* Next file available in the pool */
00168 
00169   MSAliasFile(MSAliasFileShare *share);
00170   virtual ~MSAliasFile();
00171 
00172   // Required method for CSPool item.
00173   virtual void returnToPool();
00174 
00175   
00176   // Required method for item in a CSLinkedList.
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   // Index file operations.
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   /* When a load is inprogress locks are not required and writes are batched. */
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;     // The index file.
00210   
00211   bool        iLoading;
00212   MSADiskBucketRec  *iBucketCache; // The bucket cache is used during index loading in single thread mode.
00213   MSDiskAliasRec    iBucket[NUM_RECORDS_PER_BUCKET];// The current bucket loaded from disk.
00214   MSABucketLinkedList *iBucketChain;  // The bucket list for the current hash value.
00215   MSABucketInfo   *iStartBucket;  // The file offset of the bucket the search started at.
00216   MSABucketInfo   *iCurrentBucket;// The currnet bucket, NULL if no bucket is loaded.
00217   
00218   CSDiskValue4    iDiskHash_4;  // The current hash value we are looking for in disk byte order.
00219   uint32_t        iCurrentRec;  // The current record position in the current bucket.
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;    /* A list of all files in this pool */
00258   uint64_t      msa_fileSize;
00259   CSPath      *msa_filePath;
00260   CSLock      msa_writeLock;  
00261   MSAliasFile   *msa_pool;      /* A list of files currently not in use. */
00262   
00263   CSLock      msa_poolLock; 
00264   bool      msa_closing;
00265   MSABucketLinkedList msa_empty_buckets;    /* A list of unused buckets. */
00266   
00267   MSABucketLinkedList msa_buckets[BUCKET_LIST_SIZE];  /* An array of bucket chains. */
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;                 /* Next file available in the pool */
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; // This is a back reference so this reference is not counted. 
00329   CSPath      *iFilePath;
00330   
00331   bool      iClosing;
00332   bool      iDelete;      // true when the alias index file should be deleted.
00333   
00334   MSAliasFileShare *iFileShare; // File information shared between all files in the pool.
00335   
00336   CSLock      iSysTablePoolLock;
00337   MSSysMeta   *iSysTablePool;                 /* A list of files currently not in use. */
00338   CSLinkedList  iPoolSysTables;                 /* A list of all files in this pool */
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__