Реализация высокоуровнего интерфейса вокруг базы данных Berclee DB
p align="left"> 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); } }; Этот параметризированный класс на самом деле только переопределил сигнатуры методов более удобными и работающими с пользовательскими типами данных. База данных или объект окружения Этот объект фактически представляет собой абстракцию базы данных: является контейнером для индексируемых таблиц, отвечает за их открытие, доступ, а также проводит над ними служебные операции экспорта и т.п. На диаграмме это выглядит так: 57 Описание класса приведено ниже: class hbEnv { DbEnv *env; bool is_native_log; Log* LogObj; //! Путь к файлам char* path; //! Количество баз - ломает вектором писать - тогда дольше компилится int sz; //! Инишиалайзеры (в количестве равном sz) hbInit *dbinits; hbInit *idxinits; int idxsz; char* schemaid; // уже проверяется, при открытии из словаря чит. оригин. и сравнивается //! Мутекс для транзакций pthread_mutex_t mx; uint dltype; //! in secs interval for checkpoints and logarchs ulong dldelay,bdbchkpoint,bdblogrem; static void* thf_deadrs(void*); static void* thf_chkpnt(void*); static void* thf_logarc(void*); pthread_t pth_deadrs,pth_chkpnt,pth_logarc; ushort stflags; ushort stflags; bool IsOpenflag; ushort state; TDictionary dict; //char* ConfFile; //имя конф. файла может переопределятся в потомках/ но зачем FILE* OpenOutputStream(const char* fn,const char* mode); void CloseOutputStream(FILE* f); // удаляет все __db.00x файлы т.к там хранится хэш, из-за которого может неверно сработать проверка индексов protected: //! Сами тейблы, индексов здесь нет, они в самих тейблах hbPTable **dbs; void SetSchemaid(const char* File) {if(schemaid)free(schemaid);schemaid = strdup(File);} // тэйблы будут создаваться в конструкторе потомка ,и вноситься в dbs int Close(int); virtual void UsrClose(); public: Log* GetLog() {return LogObj;} operator DbEnv*() {return env;}; DbEnv* operator ->() {return env;} //DbEnv& GetDbEnv(){ return env;} const char* GetSchemaId()const {return schemaid;} const char* GetUuid(const bexcp&, hbTxn *tx); const char* GetPath()const {return path;} bool IsOpen() {return state;} hbEnv(const char *p,envInit& e,ushort flt = LL_DEBUG, Log* LogObj1 = 0); virtual ~hbEnv(); //st_flags помещ. в DbEnv::set_flags (DB_TXN_NOSYNC) //op_flags помещ. в Db::open (DB_PRIVATE/DB_THREAD - by default) // если режим CDS то эти флаги игнорируются за исключением op_flags = DB_PRIVATE!! void OpenTDSMode(const bexcp& excp, u_int32_t st_flags = 0, u_int32_t op_flags = (DB_THREAD | DB_RECOVER) ) //DB_THREAD | DB_RECOVER_FATAL {DBOpen(excp, OPEN_TDS,true,st_flags, op_flags);} void OpenCDSMode(const bexcp& excp, bool opentables = true,u_int32_t op_flags = 0/*только для DB_PRIVATE*/) {DBOpen(excp, OPEN_CDS,opentables,0,op_flags);} void Close(const bexcp& excp); void Close(); // полная инициализация&создание базы с нуля (предварительное удаление БД) void Init(const bexcp& excp, u_int32_t op_flags=DB_THREAD); // Проверка индексов и если надо их корректировка база должна быть в offline void CheckForIdx(const bexcp& excp, uint bulk_ret_buffer_size = (5 * 1024 * 1024),bool fix = false); void CheckForRef(const bexcp& excp, uint bulk_ret_buffer_size = (5 * 1024 * 1024)); //! экспорт базы даных void ExportDB(const bexcp& excp, const char* fn,uint bulk_ret_buffer_size = (5 * 1024 * 1024)); //! импорт базы даных void ImportDB(const bexcp& excp, const char* fn); void printf(ushort level,const char* fmt,...); // обвертка под Log::printf }; Этот класс инкапсулирует работу со словарем, где может храниться информация, полезная для программиста. Транзакции Класс транзакций имеет следующий вид: class hbTxn{ hbEnv& Env; bexcp excp1; hbTxn* parent; DbTxn* Txn; void SetFlags(){} hbTxn(const hbTxn& Txn1):Env(Txn1.Env){} //copy constr hbTxn& operator=(const hbTxn&){return *this;} // := public: operator DbTxn*() {return Txn;}; hbTxn(const bexcp& excp, hbEnv& env1,ullong flags = 0,hbTxn* parent1 = 0); // младшие 32 бита это //обычн. беркл. флаги 33 бит отвечает за немедленный старт транзакции сразу же после создания hbTxn(const bexcp& excp, hbTxn* parent1,ullong flags = 0); // --- " --- ~hbTxn(); bool HaveParentTxn() {return parent!=0;} void Start(const bexcp& excp, ulong flags = 0); void Commit(const bexcp& excp, ulong flags = 0); void RollBack(const bexcp& excp); //void RollBack(); }; Его особенностью является то, что созданный объект транзакции нельзя копировать или создавать копированием. А также такой объект должен создаваться автоматически, то есть как стековая переменная: try { hbTxn tx(excp, parent_tx); // операции с базой tx.Commit(); } catch(…){} Как видим, первое - не надо заботиться об удалении объекта транзакции (при любой ситуации), второе - в случае исключения Rollback() вызовется автоматически в деструкторе этого объекта. Транслятор Как уже говорилось, задача транслятора состоит в том, чтобы создать по желанию пользователя максимально удобную оболочку для библиотеки в соответствии с его определениями основных элементов базы. Файл грамматики приведен ниже: %% #------------------------------------------------------- #------ COMMENTS -------------------------------------- #------------------------------------------------------- #id идентификатор #string строковый литерал или идентификатор #num чиловой литерал #float литерал числа с плавающей точкой #char символьный литерал #rawcode ::= любая последователность кода между '{*' и '*}' file: 'end' {tblproc::Finish();} | filetext 'end' {tblproc::Finish();} ; filetext: item | item filetext ; item: optionblock | idxblock | structblock | enumblock | codeblock | tableblock ; literal: string {[$_[1],0]} | num {[$_[1],1]} | float {[$_[1],2]} | char {[$_[1],3]} ; #--------------------------------------------------------- optionblock: 'option' '{' oplist '}' ';' {tblproc::OptBlockPrint('',$_[3]);} | 'option' opitem ';' {tblproc::OptBlockPrint('',[$_[2]]);} | 'option' id '{' oplist '}' ';' {tblproc::OptBlockPrint($_[2],$_[4]);} | 'option' id opitem ';' {tblproc::OptBlockPrint($_[2],[$_[3]]);} ; oplist: opitem ';' {[$_[1]]} | opitem ';' oplist {push @{$_[3]}, $_[1]; $_[3]} ; opitem: id '=' literal {[$_[1],@{$_[3]}[0],0,@{$_[3]}[1]]} | id '=' id {[$_[1],$_[3] ,1,'']} ; #--------------------------------------------------------- idxblock: 'idx' id idxitem ';' {tblproc::IdxBlockPrint($_[2],[$_[3]]);} | 'idx' id '{' idxitemlist '}' ';' {tblproc::IdxBlockPrint($_[2],$_[4]);} ; idxitemlist: idxitem ';' {[$_[1]]} | idxitem ';' idxitemlist {unshift @{$_[3]},$_[1]; $_[3]} ; idxitem: idxmod1 id '(' flist1 ')' {[0,$_[1],$_[2],$_[4],'']} | idxmod1 id '(' flist1 ')' '{*' rawcode '*}' {[0,$_[1],$_[2],$_[4],$_[7]]} | idxmod2 id '(' flist2 ')' {[1,$_[1],$_[2],$_[4],'']} | idxmod2 id '(' flist2 ')' '{*' rawcode '*}' {[1,$_[1],$_[2],$_[4],$_[7]]} ; idxmod1: '.!' | ':!' | '%!' ; idxmod2: '.' | ':' | '%' ; flist1: id {[[$_[1],'']]} | id ',' flist1 {unshift @{$_[3]},[$_[1],''];$_[3]} ; flist2: idxmod3 id {[[$_[2],$_[1]]]} | idxmod3 id ',' flist2 {unshift @{$_[4]},[$_[2],$_[1]];$_[4]} ; idxmod3: '+' | '-' | '^' ; #--------------------------------------------------------- codeblock: code 'decl' '{*' rawcode '*}' {tblproc::CodeBlockPrint('hh', \$_[4],0);} | code 'tab' '{*' rawcode '*}' {tblproc::CodeBlockPrint('tab', \$_[4],0);} | code 'def' '{*' rawcode '*}' {tblproc::CodeBlockPrint('cc', \$_[4],0);} | code 'def' 'top' '{*' rawcode '*}' {tblproc::CodeBlockPrint('cc', \$_[5],1);} | code '{*' rawcode '*}' {tblproc::CodeBlockPrint('all', \$_[3],0);} ; #--------------------------------------------------------- enumblock: 'enum' id '{' enumlist '}' ';' {tblproc::EnumBlockPrint($_[2],$_[4]);} | 'enum' id ';' {tblproc::EnumBlockPrint($_[2],[]);} ; enumlist: enumitem {[$_[1]]} | enumitem ',' enumlist {unshift @{$_[3]}, $_[1]; $_[3]} ; enumitem: id {[$_[1],'']} | id '=' num {[$_[1],$_[3]]} ; #--------------------------------------------------------- structblock: 'struct' id '{' structlist '}' ';' {tblproc::StructBlockPrint($_[2],$_[4]);} ; structlist: structitem {[$_[1]]} | structitem structlist {unshift @{$_[2]}, $_[1]; $_[2]} ; structitem: id pnlistid ';' {[$_[1],@{$_[2]}[0],@{$_[2]}[1]]} ; #--------------------------------------------------------- tableblock: tableforward {tblproc::TableBlockPrint(@{$_[1]}[0],'',[],[]);} | tablehead ';' {tblproc::TableBlockPrint(@{$_[1]}[0],@{$_[1]}[1],@{$_[1]}[2], []);} | tablehead tail ';' {tblproc::TableBlockPrint(@{$_[1]}[0],@{$_[1]}[1],@{$_[1]}[2], $_[2]);} ; tail: idxtailitem {$_[1]} | idxtailitem tail {unshift @{$_[2]},$_[1];$_[2]} | optiontailitem | optiontailitem tail ; tableforward: 'table' id ';' {[$_[2]]} ; tablehead: 'table' memmodifid '{' memberlist '}' {[@{$_[2]}[0],@{$_[2]}[1],$_[4]]} ; memmodifid: id {[$_[1],'']} | memmodificator id {[$_[2],'$']} ; memberlist: memberitem {[$_[1]]} | memberitem memberlist {unshift @{$_[2]}, $_[1]; $_[2]} ; memberitem: id pnlistid ';' {[$_[1],@{$_[2]}[0],@{$_[2]}[1],[]]} | id pnlistid modificator1 ';' {[$_[1],@{$_[2]}[0],@{$_[2]}[1],$_[3]]} ; modificator1: idxmodificator {[$_[1], '']} # | idxmodificator memmodificator {[$_[1], '$','']} | idxmodificator '{*' rawcode '*}' {[$_[1], $_[3]]} # | idxmodificator memmodificator '{*' rawcode '*}' {[$_[1], '$', $_[4]]} ; pnlistid: pnlist id {[$_[1], $_[2]]} | id {[[], $_[1]]} ; pnlist: pointer {[$_[1],'']} | pointer array {[$_[1],$_[2]]} | array {['',$_[1]]} ; pointer: '+' | '-' | '*' ; array: '[' id ']' {$_[2]} | '[' num ']' {$_[2]} ; idxmodificator: '.!' | ':!' | '%!' | '.+' | ':+' | '%+' | '.-' | ':-' | '%-' | '.^' | ':^' | '%^' ; memmodificator: '$' ; idxtailitem: 'idx' idxitem {[$_[2]]} | 'idx' '{' idxitemlist '}' {$_[3]} ; optiontailitem: 'option' '{' oplist '}' | 'option' opitem ; #--------------------------------------------------------- %% use tblproc; Основными компонентами этой грамматики являются: · option - элемент языка, определяющий настройки к конкретной таблице. · Idx блок - это блок, определяющий параметры индексной таблицы. · Table блок - блок, определяющий таблицу, ее записи и индексы. · Struct блок - блок, аналогичен table, с той разницей, генерирует только определения структур записей без определения самой таблицы. · Enum блок - определение С++ енумераторов, используемых в определении таблицы. · Code блок - блок сырого С++ кода встраимого непосредственного в результирующий файл. Транслятор состоит из 3 основных частей лексики, семантики и пускового модуля, написанных на языке Perl. Лексический анализатор создан с учетом этой грамматики и имеет следующий интерфейс. Prepare(array of lines); // normal result ==0 token Next(); Он поддерживает также препроцессирование на уровне вложений include. Семантический анализатор состоит из API, вызываемых как обработчики событий (для интерфейса yapp указываются в определении грамматики). Пусковой модуль является оболочкой для запуска синтаксического анализатора, с разбором входных параметров Формат: 1)HibaseCompiler.pl [-f имя файла] [-p путь к hibase] [-d каталог, куда помещ. сген стаб] 2)program | HibaseCompiler.pl [-p путь к hibase] [-d каталог,куда помещ. сген стаб]. 6.Пример работы программы В качестве примера расмотрим следующее определение базы данных Tables.def code def top {* #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <db_cxx.h> #include "../hblib/consts.hh" #include "../hblib/ll.hh" #include "../hblib/utils.hh" #include "../hblib/hdb.hh" #include "tbmain.hh" #include "dbmain.hh" *} option { file = "main"; namespace = "hb"; }; table supplier { char [12]name .!; // key uh; //unq,hash char [40]desc; }; table thing { supplier+ tsupplier; // внешняя ссылка char [12]name .!; // key uh; //unq,hash char [40]desc; }; end В результате работы транслятора получаем 3 файла: файл описания структур записей таблиц, файл определения самих таблиц и базы и файл ее реализации: hbmain.hh namespace hb{ using namespace hb; class mainEnv; struct supplierKey { db_recno_t key; inline void Export(FILE* f); inline void Import(char*,uint); supplierKey(const db_recno_t& key_temp); supplierKey(){} }__attribute__ ((packed)); struct supplierVal { char name[12]; char desc[40]; inline void Export(FILE* f); inline void Import(char*,uint); supplierVal(char* name_temp,char* desc_temp); supplierVal(){} }__attribute__ ((packed)); class qsupplier: public hbTable<supplierKey,supplierVal>{ mainEnv& menv; public: qsupplier(mainEnv&); inline void RefInit(); static void GetRef_supplier(uint, char* ,char* , db_recno_t*&, uint&); static int qsupplier::idx_name(Db *db,const Dbt* pk,const Dbt* pv,Dbt* fv); }; struct isupplier_name { char name[12]; char* Getname(){return name;} isupplier_name(char* name_temp); }__attribute__ ((packed)); //------------------------------------------------------------------------------ struct thingKey { db_recno_t key; inline void Export(FILE* f); inline void Import(char*,uint); thingKey(const db_recno_t& key_temp); thingKey(){} }__attribute__ ((packed)); struct thingVal { db_recno_t tsupplier; char name[12]; char desc[40]; inline void Export(FILE* f); inline void Import(char*,uint); thingVal(const db_recno_t& tsupplier_temp,char* name_temp,char* desc_temp); thingVal(){} }__attribute__ ((packed)); class qthing: public hbTable<thingKey,thingVal>{ mainEnv& menv; public: qthing(mainEnv&); inline void RefInit(); static void GetRef_thing(uint, char* ,char* , db_recno_t*&, uint&); static int qthing::idx_name(Db *db,const Dbt* pk,const Dbt* pv,Dbt* fv); }; struct ithing_name { char name[12]; char* Getname(){return name;} ithing_name(char* name_temp); }__attribute__ ((packed)); //------------------------------------------------------------------------------ }; dbmain.hh namespace hb{ using namespace hb; enum idxNames{ dbn_supplier_name = 0, dbn_thing_name = 0}; class mainEnv; class mainEnv:public hbEnv{ public: mainEnv(const char*,ushort flt = LL_DEBUG, Log* LogObj1 = 0); qsupplier& tsupplier; qthing& tthing; }; }; dbmain.cc #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <db_cxx.h> #include "../hblib/consts.hh" #include "../hblib/ll.hh" #include "../hblib/utils.hh" #include "../hblib/hdb.hh" #include "tbmain.hh" #include "dbmain.hh" //#include <stdio.h> //#include <stdlib.h> //#include <time.h> //#include <string.h> //#include <stdarg.h> //#include <pthread.h> //#include <unistd.h> //#include <dirent.h> //#include <ctype.h> //#include <sys/types.h> //#include "../hibase/consts.hh" //#include "../hibase/ll.hh" //#include "../hibase/hdb.hh" //#include "myconst.hh" //#include "dbmain.hh" namespace hb{}; using namespace hb; namespace hb{}; using namespace hb; #define NUMDB 2 enum maindbNames{ dbnsupplier = 0,dbnthing}; static hbInit tblIndexes[]={ { "supplier::name","supplier.i","name",DB_HASH,0,0,0,&qsupplier::idx_name, 0, 0 }, { "thing::name","thing.i","name",DB_HASH,0,0,0,&qthing::idx_name, 0, 0 } }; static hbInit tblInits[]={ {"supplier","supplier.q",0,DB_QUEUE,0,1, tblIndexes + 0 , 0, &qsupplier::GetRef_supplier, 0}, {"thing","thing.q",0,DB_QUEUE,0,1, tblIndexes + 1 , 0, &qthing::GetRef_thing, 1} }; envInit mainEnvInit={ NUMDB, "$Id: tblproc.pm,v 1.35 2004/01/10 23:57:48 bora Exp $" }; qsupplier::qsupplier(mainEnv& env): hbTable<supplierKey,supplierVal>(env,tblInits[dbnsupplier]), menv(env) {} void qsupplier::RefInit() { } void qsupplier::GetRef_supplier(uint num, char* key,char* val, db_recno_t*& refs, uint& ref_count) { supplierKey *key1 = (supplierKey*)key; supplierVal *val1 = (supplierVal*)val; } void supplierKey::Export(FILE* f) { fprintf(f,"%d",key); } void supplierKey::Import(char* buf, uint len) { int j,num, i = 0; char temp; buf[i]=='')break;} temp = buf[i];buf[i] = '\0';sscanf(buf+j,"%d",&key); buf[i] = temp; i++; } supplierKey::supplierKey(const db_recno_t& key_temp) { memset(this,0,sizeof(*this)); key = key_temp; } void supplierVal::Export(FILE* f) { fprintf(f,"{"); CharArrInToStr(f,name,12); fprintf(f,"}"); fprintf(f,","); fprintf(f,"{"); CharArrInToStr(f,desc,40); fprintf(f,"}"); } void supplierVal::Import(char* buf, uint len) { int j,num, i = 0; char temp; if(buf[i++] !='{') throw hbExcp(3,LL_CRITICAL,0,"Ошибка импорта: +указатель на таблицу = 0."); j = i; for(;i<len;i++) { if (buf[i] == '}' && buf[i-1]!='\\') break; } StrToCharArr(buf+j,i-j,name,12); i+= 2; if(buf[i++] !='{') throw hbExcp(3,LL_CRITICAL,0,"Ошибка импорта: +указатель на таблицу = 0."); j = i; for(;i<len;i++) { if (buf[i] == '}' && buf[i-1]!='\\') break; } StrToCharArr(buf+j,i-j,desc,40); i+= 2; } supplierVal::supplierVal(char* name_temp,char* desc_temp) { memset(this,0,sizeof(*this)); strncpy(name,name_temp, sizeof(name)); strncpy(desc,desc_temp, sizeof(desc)); } isupplier_name::isupplier_name(char* name_temp) { memcpy(name,name_temp,sizeof(name)); } int qsupplier::idx_name(Db *db,const Dbt* pk,const Dbt* pv,Dbt* fv) { supplierVal *v= (supplierVal*)(pv->get_data()); fv->set_data(v->name); fv->set_size(sizeof(isupplier_name)); return 0; } //------------------------------------------------------------------------------ qthing::qthing(mainEnv& env): hbTable<thingKey,thingVal>(env,tblInits[dbnthing]), menv(env) {} void qthing::RefInit() { ref.reftables[0].type = '+'; ref.reftables[0].reftable = &menv.tsupplier; } void qthing::GetRef_thing(uint num, char* key,char* val, db_recno_t*& refs, uint& ref_count) { thingKey *key1 = (thingKey*)key; thingVal *val1 = (thingVal*)val; if(num==0) { refs = &val1->tsupplier; ref_count = 1; } } void thingKey::Export(FILE* f) { fprintf(f,"%d",key); } void thingKey::Import(char* buf, uint len) { int j,num, i = 0; char temp; ')break;} temp = buf[i];buf[i] = '\0';sscanf(buf+j,"%d",&key); buf[i] = temp; i++; } thingKey::thingKey(const db_recno_t& key_temp) { memset(this,0,sizeof(*this)); key = key_temp; } void thingVal::Export(FILE* f) { fprintf(f,"%d",tsupplier); fprintf(f,","); fprintf(f,"{"); CharArrInToStr(f,name,12); fprintf(f,"}"); fprintf(f,","); fprintf(f,"{"); CharArrInToStr(f,desc,40); fprintf(f,"}"); } void thingVal::Import(char* buf, uint len) { int j,num, i = 0; char temp; buf[i]=='')break;} temp = buf[i];buf[i] = '\0';sscanf(buf+j,"%d",&tsupplier); buf[i] = temp; if(tsupplier == 0) throw hbExcp(3,LL_CRITICAL,0," Ошибка импорта: +указатель на таблицу = 0. "); i++; if(buf[i++] !='{') throw hbExcp(3,LL_CRITICAL,0," Ошибка импорта: не могу распарсить строку."); j = i; for(;i<len;i++) { if (buf[i] == '}' && buf[i-1]!='\\') break; } StrToCharArr(buf+j,i-j,name,12); i+= 2; if(buf[i++] !='{') throw hbExcp(3,LL_CRITICAL,0," Ошибка импорта: не могу распарсить строку. "); j = i; for(;i<len;i++) { if (buf[i] == '}' && buf[i-1]!='\\') break; } StrToCharArr(buf+j,i-j,desc,40); i+= 2; } thingVal::thingVal(const db_recno_t& tsupplier_temp,char* name_temp,char* desc_temp) { memset(this,0,sizeof(*this)); tsupplier = tsupplier_temp; strncpy(name,name_temp, sizeof(name)); strncpy(desc,desc_temp, sizeof(desc)); } ithing_name::ithing_name(char* name_temp) { memcpy(name,name_temp,sizeof(name)); } int qthing::idx_name(Db *db,const Dbt* pk,const Dbt* pv,Dbt* fv) { thingVal *v= (thingVal*)(pv->get_data()); fv->set_data(v->name); fv->set_size(sizeof(ithing_name)); return 0; } //------------------------------------------------------------------------------ mainEnv::mainEnv(const char *path,ushort flt, Log* LogObj1):hbEnv(path,mainEnvInit,flt,LogObj1), tsupplier(* (new qsupplier(*this))), tthing(* (new qthing(*this))) { dbs[dbnsupplier] = &tsupplier;tsupplier.RefInit(); dbs[dbnthing] = &tthing;tthing.RefInit(); } Файл пример описан так int main(void) { mainEnv env ("./DataBase/"); //создаем базу, то есть формируем необходимые файлы для всех таблиц env.Init(bexcp(16,"main","example.cc",3,LL_DEBUG)); env.Close(bexcp(16,"main","example.cc",3,LL_DEBUG)); env.ImportDB(bexcp(16,"main","example.cc",3,LL_DEBUG),"./Export1.ex"); env.ExportDB(bexcp(16,"main","example.cc",3,LL_DEBUG),"./Export.ex"); // проверяем на индексную целостность env.CheckForIdx(bexcp(16,"main","example.cc",3,LL_DEBUG)); // проверяем на ссылочную целостность env.CheckForRef(bexcp(16,"main","example.cc",3,LL_DEBUG)); env.OpenTDSMode(); //открываем ее в нормальном транзакционном режиме try { hbTxn tx(env); tx.Start(); supplierKey key = {1} ; supplierVal val = {"Boris","Boss"}; env.tsupplier.Put(&tx,&key,&val); thingKey key = {1} ; thingVal val = {1,"Computer","best"}; env.tthing.Put(&tx,&key,&val); tx.commit(); } catch(hbExcp& excp) { cout<<excp.what(); } env.Close(); return 0; } 7.Заключение На сегодняшний день навигационно-сетевые базы вновь приобрели свою актуальность. Это обуславливается, главным образом, их очень высокой скоростью работы, даже, несмотря на сложность понимания для неквалифицированного специалиста. Чтобы облегчить работу программисту с такой базой средствами BerkeleyDB к ней был введен генератор объектно-ориентированного интерфейса. Это позволило качественно улучшить скорость разработки на С++ и повысить уровень абстракции работы с ней. 8.Список используемой литературы: 1) http://www.sleepycat.com - официальный сайт компании -разработчика BerkeleyDB 2) The Object Data Standard ODMG 3.0. New York, MK, 2002. 3) Gamma E., Helm R., Johnson R., Vlissides J. Design Patterns: Elements of reusable object-oriented software, Reading, MA: Addison-Westley, 1995. 4) Герберт Шилдт. Полный справочник по С. М., Вильямс, 2002.
Страницы: 1, 2
|