Реализация высокоуровнего интерфейса вокруг базы данных Berclee DB
*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);
}
};
Этот параметризированный класс на самом деле только переопределил сигнатуры методов более удобными и работающими с пользовательскими типами данных.
База данных или объект окружения
Этот объект фактически представляет собой абстракцию базы данных: является контейнером для индексируемых таблиц, отвечает за их открытие, доступ, а также проводит над ними служебные операции экспорта и т.п. На диаграмме это выглядит так:
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.
Array
Страницы: 1, 2
|