p align="left"> hbRec() { memset(&data,0,sizeof(A));dbtInit(sizeof(A),&data);} hbRec(const hbRec<A>& a):data(a.data) { dbtInit(sizeof(A),&data);} hbRec(const A& a) :data(a) { dbtInit(sizeof(A),&data);} void SetData(const A& a) { data = a;dbtInit(sizeof(A),&data);} virtual ~hbRec() {} }; Таблицы Диаграмма отношений существующих таблиц приведена ниже: 57 По аналогии с записями существует базовый класс таблиц hbBasetbl, который поддерживает работу со всеми стандартными типами таблиц (Hash, Btree, Queue). Фактически ее тип является ее состоянием и определяется в момент открытия. class hbBasetbl { // нужен для того чтобы set_flags вызывалась ровно один раз uint Set_flg_Counter; ushort state; // флаг, показывающ. открыта ли сама таблица, необходим для экстр. закрытия в случае некоректного // открытия bool tableopen; hbInit ini; protected: uint recsize; uint keysize; //только для DB_HASH Db *table; virtual void UsrOpen(hbTxn *tx,FileConf& conf,bool openidx,hbInitRt* irt = 0,u_int32_t op_flags = 0); virtual void UsrClose(); void SetRecSize(uint recsize1){recsize = recsize1;} void SetKeySize(uint keysize1){keysize = keysize1;} uint GetType() {return ini.type;} bool IsDup() return (ini.st_flags & DB_DUP public: hbEnv& env; operator Db*(){return table;} Db* operator ->(){return table;} const char* GetDbName(){return ini.dbname;} hbBasetbl(hbEnv& e,hbInit&); virtual ~hbBasetbl(){ if(state) Close();} void Open(hbTxn *tx,FileConf& conf,bool openidx,hbInitRt* irt = 0,u_int32_t op_flags = 0); void Close(); virtual void Create(hbTxn *tx,FileConf& conf,hbInitRt* irt = 0,u_int32_t op_flags = 0); virtual int Get(hbTxn *tx,hbObj *key,hbObj *val,u_int32_t flags=0); // в стиле С (без исключений) virtual int Pget(hbTxn *tx,hbObj *fkey,hbObj *pkey, // в стиле С (без исключений) hbObj *val, u_int32_t flags=0); virtual int Del(hbTxn *tx,hbObj *key,u_int32_t flags=0); // в стиле С (без исключений) virtual int tGet(hbTxn *tx,hbObj *key,hbObj *val,u_int32_t flags=0); // в стиле С++ virtual int tPget(hbTxn *tx,hbObj *fkey,hbObj *pkey, hbObj *val, u_int32_t flags=0); // в стиле С++ virtual int tDel(hbTxn *tx,hbObj *key,u_int32_t flags=0); // в стиле С++ virtual int Put(hbTxn *tx,hbObj *key,hbObj *val,u_int32_t flags=0); bool IsOpen(){return state;} }; Для ускорения доступа по какому-то критерию к данным в таблицах вводятся индексные таблицы. Ими могут быть любые из перечисленных, конечно в соответствии с их особенностями. Класс hbBasetbl является с одной стороны базовым классом, содержащим всю рутинную работу с флагами и основными операциями с таблицей, а с другой стороны -финальным классом для индексной таблицы. Этот класс является базовым, и совсем неудобен для работы, если эта таблица является индексированной (то есть имеет индексы - другие индексные таблицы). Необходим еще один класс, который будет обобщением понятия индексируемой таблицы и являться контейнером для таких индексных таблиц. Этот класс представлен ниже. class hbPTable:public hbBasetbl{ void ErrorClose(); void eee(); void FixIdx(uint bulk_ret_buffer_size,int i,FileConf& conf); void FixIdxForQueue(uint bulk_ret_buffer_size,int i,FileConf& conf); void FixIdxForHash(uint bulk_ret_buffer_size,int i,FileConf& conf); void CheckMainToIdx(uint bulk_ret_buffer_size,bool fix,FileConf& conf); void CheckMainToIdxForQueue(uint bulk_ret_buffer_size,bool fix,FileConf& conf); void CheckMainToIdxForHash(uint bulk_ret_buffer_size,bool fix,FileConf& conf); void CheckIdxToMain(uint bulk_ret_buffer_size,bool fix,FileConf& conf); void CheckIdxToMainForQueue(uint bulk_ret_buffer_size,bool fix,FileConf& conf); void CheckIdxToMainForHash(uint bulk_ret_buffer_size,bool fix,FileConf& conf); inline void ExportForQueue(uint bulk_ret_buffer_size,FILE* f, hbTxn* tx); inline void ExportForHash(uint bulk_ret_buffer_size,FILE* f, hbTxn* tx); inline void Import3(Dbt* key,Dbt* data); inline void Import2(char* buf); inline void Import1(FILE* f,char*& buf1,uint&); inline void CheckForRefForQueue(uint bulk_ret_buffer_size); inline void CheckForRefForHash(uint bulk_ret_buffer_size); inline uint GetMaxRefRecBuf(); protected: int sz; IdxItem *idx; RefItems ref; virtual void UsrOpen(hbTxn *tx,FileConf& conf,bool openidx,hbInitRt* irt = 0,u_int32_t flags = 0); virtual void UsrClose(); inline virtual void ExportDBTemplate(FILE*,const char*,const char*) = 0; inline virtual void ImportDBTemplate( char* buf1, uint buf1len, char* buf2, uint buf2len, hbObj*& Key, hbObj*& Val) = 0; public: //! конструктор принимает массив инициализаторов (в тч индексов) hbPTable(hbEnv& env,hbInit& ini1); virtual ~hbPTable(); // проверка индексной целостности void CheckIdx(uint bulk_ret_buffer_size,bool fix); // проверка ссылочной целостности void CheckForRef(uint bulk_ret_buffer_size); void Export(uint bulk_ret_buffer_size,FILE* f, hbTxn* tx); void Import(FILE* f,char*& buf,uint&); virtual int Pget(hbTxn *tx,int n,hbObj *fkey, hbObj* pkey, hbObj *val, u_int32_t flags=0) {return idx[n].table.Pget(tx,fkey,pkey,val,flags);} hbBasetbl& GetIdx(int n) {return idx[n].table;} inline uint GetIdxCount() {return sz;} inline uint GetRecSize() {return recsize;} }; Как видим, этот класс расширяет старый интерфейс путем введения утилитарных методов экспорта, импорта, различного рода проверок и операциями с индексными таблицами. Однако этот класс также не удобен в работе, так как не знает ничего о типах структур и ее характеристиках. Введение этих типов как параметров шаблона позволило бы очень упростить работу с интерфейсом индексируемой таблицы (но не расширить!). Результат приведен ниже: template<class Key,class Val> class hbTable:public hbPTable { public: //! конструктор принимает массив инициализаторов (в тч индексов) hbTable(hbEnv& e,hbInit& ini1):hbPTable(e,ini1) {SetRecSize(sizeof(Val));SetKeySize(sizeof(Key));} //SetRecSize use by QUEUE only virtual ~hbTable() {} // более продвинутые функции int Get(const bexcp& excp, hbTxn *tx,const Key &key,Val *val, u_int32_t flags=0) { Get(excp,tx,(Key*)&key,val,flags); } int Pget(const bexcp& excp, hbTxn *tx,int n,hbObj *fkey,Key *pkey, Val *val,u_int32_t flags=0) { MTRY hbRec<Key> k; hbRec<Val> v; int z=Pget(tx,n,fkey,&k,&v,flags); *pkey= *(k.getPnt()); *val= *(v.getPnt()); return z; CATCH_hbExcp } int Del(const bexcp& excp, hbTxn *tx, const Key &key,u_int32_t flags=0) { Del(excp,tx,(Key*)&key,flags); } int tGet(const bexcp& excp, hbTxn *tx, Key *key,Val *val, u_int32_t flags=0) { MTRY hbRec<Key> k(*key); hbRec<Val> v; int z = tGet(tx,&k,&v,flags); *val= *(v.getPnt()); return z; CATCH_hbExcp } int Put(const bexcp& excp, hbTxn *tx,const Key &key, const Val &val, u_int32_t flags=0) { Put(excp,tx,(Key*)&key,(Val*)&val,flags); } uint Append(const bexcp& excp, hbTxn *tx, Val *val) { MTRY if(GetType() != DB_QUEUE) return 0; hbRec<uint> k; hbRec<Val> v(*val); hbBasetbl::Put(tx,&k,&v,DB_APPEND); return (uint&)*(k.getPnt()); CATCH_hbExcp } uint Append(const bexcp& excp, hbTxn *tx,const Val &val) { return Append(excp,tx,(Val*)&val);
Страницы: 1, 2, 3, 4, 5, 6
|