bool FileRecord::Remove(const std::string& id, const std::string& owner) { if(!valid_) return false; Glib::Mutex::Lock lock(lock_); Dbt key; Dbt data; make_key(id,owner,key); void* pkey = key.get_data(); if(dberr("",db_locked_->get(NULL,&key,&data,0))) { ::free(pkey); error_str_ = "Record has active locks"; return false; // have locks }; if(!dberr("Failed to retrieve record from database",db_rec_->get(NULL,&key,&data,0))) { ::free(pkey); return false; // No such record? }; std::string uid; std::string id_tmp; std::string owner_tmp; std::list<std::string> meta; parse_record(uid,id_tmp,owner_tmp,meta,key,data); if(!uid.empty()) { ::unlink(uid_to_path(uid).c_str()); // TODO: handle error }; if(!dberr("Failed to delete record from database",db_rec_->del(NULL,&key,0))) { // TODO: handle error ::free(pkey); return false; }; db_rec_->sync(0); ::free(pkey); return true; }
bool FileRecord::RemoveLock(const std::string& lock_id, std::list<std::pair<std::string,std::string> >& ids) { if(!valid_) return false; Glib::Mutex::Lock lock(lock_); Dbc* cur = NULL; if(!dberr("removelock:cursor",db_lock_->cursor(NULL,&cur,DB_WRITECURSOR))) return false; Dbt key; Dbt data; make_string(lock_id,key); void* pkey = key.get_data(); if(!dberr("removelock:get1",cur->get(&key,&data,DB_SET))) { // TODO: handle errors ::free(pkey); cur->close(); return false; }; for(;;) { std::string id; std::string owner; uint32_t size = data.get_size(); void* buf = data.get_data(); buf = parse_string(id,buf,size); buf = parse_string(owner,buf,size); ids.push_back(std::pair<std::string,std::string>(id,owner)); if(!dberr("removelock:del",cur->del(0))) { ::free(pkey); cur->close(); return false; }; if(!dberr("removelock:get2",cur->get(&key,&data,DB_NEXT_DUP))) break; }; db_lock_->sync(0); ::free(pkey); cur->close(); return true; }
bool FileRecord::Modify(const std::string& id, const std::string& owner, const std::list<std::string>& meta) { if(!valid_) return false; Glib::Mutex::Lock lock(lock_); Dbt key; Dbt data; make_key(id,owner,key); void* pkey = key.get_data(); if(!dberr("Failed to retrieve record from database",db_rec_->get(NULL,&key,&data,0))) { ::free(pkey); return false; }; std::string uid; std::string id_tmp; std::string owner_tmp; std::list<std::string> meta_tmp; parse_record(uid,id_tmp,owner_tmp,meta_tmp,key,data); ::free(pkey); make_record(uid,id,owner,meta,key,data); if(!dberr("Failed to store record to database",db_rec_->put(NULL,&key,&data,0))) { ::free(key.get_data()); ::free(data.get_data()); return false; }; db_rec_->sync(0); ::free(key.get_data()); ::free(data.get_data()); return true; }
bool FileRecord::verify(void) { // Performing various kinds of verifications std::string dbpath = basepath_ + G_DIR_SEPARATOR_S + FR_DB_NAME; { Db db_test(NULL,DB_CXX_NO_EXCEPTIONS); if(!dberr("Error verifying databases", db_test.verify(dbpath.c_str(),NULL,NULL,DB_NOORDERCHK))) { if(error_num_ != ENOENT) return false; }; }; { Db db_test(NULL,DB_CXX_NO_EXCEPTIONS); if(!dberr("Error verifying database 'meta'", db_test.verify(dbpath.c_str(),"meta",NULL,DB_ORDERCHKONLY))) { if(error_num_ != ENOENT) return false; }; }; // Skip 'link' - it is not of btree kind // Skip 'lock' - for unknown reason it returns DB_NOTFOUND // Skip 'locked' - for unknown reason it returns DB_NOTFOUND return true; }
bool FileRecord::AddLock(const std::string& lock_id, const std::list<std::string>& ids, const std::string& owner) { if(!valid_) return false; Glib::Mutex::Lock lock(lock_); Dbt key; Dbt data; for(std::list<std::string>::const_iterator id = ids.begin(); id != ids.end(); ++id) { make_link(lock_id,*id,owner,data); void* pdata = data.get_data(); if(!dberr("addlock:put",db_link_->put(NULL,&key,&data,DB_APPEND))) { ::free(pdata); return false; }; ::free(pdata); }; db_link_->sync(0); return true; }
std::string FileRecord::Find(const std::string& id, const std::string& owner, std::list<std::string>& meta) { if(!valid_) return ""; Glib::Mutex::Lock lock(lock_); Dbt key; Dbt data; make_key(id,owner,key); void* pkey = key.get_data(); if(!dberr("Failed to retrieve record from database",db_rec_->get(NULL,&key,&data,0))) { ::free(pkey); return ""; }; std::string uid; std::string id_tmp; std::string owner_tmp; parse_record(uid,id_tmp,owner_tmp,meta,key,data); ::free(pkey); return uid_to_path(uid); }
std::string FileRecord::Add(std::string& id, const std::string& owner, const std::list<std::string>& meta) { if(!valid_) return ""; Glib::Mutex::Lock lock(lock_); Dbt key; Dbt data; std::string uid = rand_uid64().substr(4); make_record(uid,(id.empty())?uid:id,owner,meta,key,data); void* pkey = key.get_data(); void* pdata = data.get_data(); if(!dberr("Failed to add record to database",db_rec_->put(NULL,&key,&data,DB_NOOVERWRITE))) { ::free(pkey); ::free(pdata); return ""; }; db_rec_->sync(0); ::free(pkey); ::free(pdata); if(id.empty()) id = uid; return uid_to_path(uid); }
/* Initialize database tables */ int inittab() { register int dbt_lc; /* loop control */ register INT i, j; int key_offset = 0, key_count; char dbfile[DtSrFILENMLEN], dbd_ver[DBD_COMPAT_LEN + 1]; char dbname[FILENMLEN]; /* Temporary working space */ int dbf; FILE_ENTRY FAR *file_ptr; FIELD_ENTRY FAR *fld_ptr; #ifndef ONE_DB #define DB_ENABLE 1 #else #define DB_ENABLE 0 #endif #ifndef NO_TIMESTAMP #define TS_ENABLE 1 #else #define TS_ENABLE 0 #endif #if DB_ENABLE | TS_ENABLE RECORD_ENTRY FAR *rec_ptr; SET_ENTRY FAR *set_ptr; #endif #ifndef ONE_DB MEMBER_ENTRY FAR *mem_ptr; SORT_ENTRY FAR *srt_ptr; KEY_ENTRY FAR *key_ptr; #endif #ifndef NO_TIMESTAMP db_tsrecs = db_tssets = FALSE; #endif size_ft = size_rt = size_st = size_mt = size_srt = size_fd = size_kt = 0; /* compute individual dictionary sizes and offsets */ #ifndef ONE_DB for (dbt_lc = 0, curr_db_table = &db_table[old_no_of_dbs]; dbt_lc < no_of_dbs; ++dbt_lc, ++curr_db_table) { #endif /* form database dictionary name */ if ( DB_REF(db_path[0]) ) strcpy(dbname, DB_REF(db_path)); else dbname[0] = '\0'; #ifdef DEBUG_INITTAB if (debugging_inittab) { printf (__FILE__"100 inittab: path='%s' dbname='%s'\n", dbname, DB_REF(db_name)); fflush (stdout); } #endif if (strlen(dbname) + strlen(DB_REF(db_name)) >= FILENMLEN+4) return( dberr(S_NAMELEN) ); strcat(dbname, DB_REF(db_name)); if (con_dbd(dbfile, dbname, get_element(dbdpath, dbt_lc)) != S_OKAY) return( dberr(db_status) ); /*----------------- PASS 1 ------------------- * In this first pass, only opening to determine * required table sizes, so opening read-only is ok. */ if ( (dbf = open_b(dbfile, O_RDONLY)) < 0 ) return( dberr( S_INVDB ) ); /* Read in and verify the dictionary version */ DB_READ(dbf, dbd_ver, DBD_COMPAT_LEN); dbd_ver[DBD_COMPAT_LEN] = '\0'; for ( i=0; i<size_compat; i++ ) { if ( strcmp( dbd_ver, compat_dbd[i] ) == 0 ) goto goodver; } /* Incompatible dictionary file */ close( dbf ); return( dberr( S_INCOMPAT ) ); goodver: /* Read in database page size */ DB_READ(dbf, (char FAR *)&DB_REF(Page_size), sizeof(INT)); NTOHS (DB_REF(Page_size)); /* Read in table sizes */ DB_READ(dbf, (char FAR *)&DB_REF(Size_ft), sizeof(INT)); NTOHS (DB_REF(Size_ft)); DB_READ(dbf, (char FAR *)&DB_REF(Size_rt), sizeof(INT)); NTOHS (DB_REF(Size_rt)); DB_READ(dbf, (char FAR *)&DB_REF(Size_fd), sizeof(INT)); NTOHS (DB_REF(Size_fd)); DB_READ(dbf, (char FAR *)&DB_REF(Size_st), sizeof(INT)); NTOHS (DB_REF(Size_st)); DB_READ(dbf, (char FAR *)&DB_REF(Size_mt), sizeof(INT)); NTOHS (DB_REF(Size_mt)); DB_READ(dbf, (char FAR *)&DB_REF(Size_srt), sizeof(INT)); NTOHS (DB_REF(Size_srt)); DB_READ(dbf, (char FAR *)&DB_REF(Size_kt), sizeof(INT)); NTOHS (DB_REF(Size_kt)); close(dbf); /* end of PASS 1 */ #ifdef DEBUG_INITTAB if (debugging_inittab) { printf (__FILE__"152 sizes: pg=%d ft=%d rt=%d fd=%d\n" " st=%d mt=%d srt=%d kt=%d\n", (int) DB_REF(Page_size), (int) DB_REF(Size_ft), (int) DB_REF(Size_rt), (int) DB_REF(Size_fd), (int) DB_REF(Size_st), (int) DB_REF(Size_mt), (int) DB_REF(Size_srt), (int) DB_REF(Size_kt) ); fflush (stdout); } #endif DB_REF(sysdba) = NULL_DBA; #ifndef ONE_DB /* update merged dictionary offsets and sizes */ if ( curr_db_table->Page_size > page_size ) { page_size = curr_db_table->Page_size; #ifdef DEBUG_INITTAB if (debugging_inittab) { printf (__FILE__"191 db's page_size-->%d (largest = %d)\n", (int)page_size, (int)largest_page); fflush(stdout); } #endif } curr_db_table->ft_offset = size_ft; size_ft += curr_db_table->Size_ft; curr_db_table->rt_offset = size_rt; size_rt += curr_db_table->Size_rt; curr_db_table->fd_offset = size_fd; size_fd += curr_db_table->Size_fd; curr_db_table->st_offset = size_st; size_st += curr_db_table->Size_st; curr_db_table->mt_offset = size_mt; size_mt += curr_db_table->Size_mt; curr_db_table->srt_offset = size_srt; size_srt += curr_db_table->Size_srt; curr_db_table->kt_offset = size_kt; size_kt += curr_db_table->Size_kt; } #endif /* allocate dictionary space */ if ( alloc_dict() != S_OKAY ) return( db_status ); /* read in and adjust dictionary entries for each database */ #ifndef ONE_DB for (dbt_lc = 0, curr_db_table = &db_table[old_no_of_dbs]; dbt_lc < no_of_dbs; ++dbt_lc, ++curr_db_table) { #endif /* form database dictionary name */ if ( DB_REF(db_path[0]) ) strcpy(dbname, DB_REF(db_path)); else dbname[0] = '\0'; if (strlen(dbname) + strlen(DB_REF(db_name)) >= FILENMLEN+4) return( dberr(S_NAMELEN) ); strcat(dbname,DB_REF(db_name)); if (con_dbd(dbfile,dbname,get_element(dbdpath, dbt_lc)) != S_OKAY) return( dberr(db_status) ); #ifdef DEBUG_INITTAB if (dump_init_tables) { printf (__FILE__"247 Tables for database '%s':\n", dbfile); fflush (stdout); } #endif /*----------------- PASS 2 ------------------- * Second pass just loads allocated tables, * so opening .dbd file read-only is still ok. */ dbf = open_b (dbfile, O_RDONLY); DB_LSEEK(dbf, DBD_COMPAT_LEN + 8L*sizeof(INT), 0); /*----------------- FILE TABLE -------------------*/ DB_READ(dbf, (char FAR *)&file_table[ORIGIN(ft_offset)], (DB_REF(Size_ft)*sizeof(FILE_ENTRY))); /* Invalid if sizeof(xxxx_ENTRY) diff on each machine */ for ( i = 0, file_ptr = &file_table[ORIGIN(ft_offset)]; i < DB_REF(Size_ft); i++, file_ptr++) { /* Byte swap each INT on LITTLE_ENDIAN machines */ NTOHS (file_ptr->ft_slots); NTOHS (file_ptr->ft_slsize); NTOHS (file_ptr->ft_pgsize); NTOHS (file_ptr->ft_flags); #ifdef DEBUG_INITTAB if (dump_init_tables) { printf (" FILE#%d: ty=%c slts=%2d slsz=%3d pgsz=%d '%s'\n", (int)i, file_ptr->ft_type, (int)file_ptr->ft_slots, (int)file_ptr->ft_slsize, (int)file_ptr->ft_pgsize, file_ptr->ft_name); fflush (stdout); } #endif } /*----------------- RECORD TABLE -------------------*/ DB_READ(dbf, (char FAR *)&record_table[ORIGIN(rt_offset)], (DB_REF(Size_rt)*sizeof(RECORD_ENTRY))); for ( i = 0, rec_ptr = &record_table[ORIGIN(rt_offset)]; i < DB_REF(Size_rt); i++, rec_ptr++) { /* Byte swap each INT on LITTLE_ENDIAN machines */ NTOHS (rec_ptr->rt_file); NTOHS (rec_ptr->rt_len); NTOHS (rec_ptr->rt_data); NTOHS (rec_ptr->rt_fields); NTOHS (rec_ptr->rt_fdtot); NTOHS (rec_ptr->rt_flags); #ifdef DEBUG_INITTAB if (dump_init_tables) { printf ( " REC #%d: fil=%d len=%3d data=%2d fld1=%2d flds=%2d\n", (int)i, (int)rec_ptr->rt_file, (int)rec_ptr->rt_len, (int)rec_ptr->rt_data, (int)rec_ptr->rt_fields, (int)rec_ptr->rt_fdtot); fflush (stdout); } #endif } /*----------------- FIELD TABLE -------------------*/ DB_READ(dbf, (char FAR *)&field_table[ORIGIN(fd_offset)], (DB_REF(Size_fd)*sizeof(FIELD_ENTRY))); for ( i = 0, fld_ptr = &field_table[ORIGIN(fd_offset)]; i < DB_REF(Size_fd); i++, fld_ptr++) { /* Byte swap each INT on LITTLE_ENDIAN machines */ NTOHS (fld_ptr->fd_len); NTOHS (fld_ptr->fd_keyfile); NTOHS (fld_ptr->fd_keyno); NTOHS (fld_ptr->fd_ptr); NTOHS (fld_ptr->fd_rec); NTOHS (fld_ptr->fd_flags); for (j=0; j<MAXDIMS; j++) NTOHS (fld_ptr->fd_dim[j]); #ifdef DEBUG_INITTAB if (dump_init_tables) { if (i == 0) puts (" key typ len kfil key# ofs rec# flg dims"); printf ( " FLD#%2d %c %c %3d %d %d %3d %d %x", (int)i, fld_ptr->fd_key, fld_ptr->fd_type, (int)fld_ptr->fd_len, (int)fld_ptr->fd_keyfile, (int)fld_ptr->fd_keyno, (int)fld_ptr->fd_ptr, (int)fld_ptr->fd_rec, (int)fld_ptr->fd_flags); for (j=0; j<MAXDIMS; j++) if (fld_ptr->fd_dim[j]) printf (" %d:%d", j, (int)fld_ptr->fd_dim[j]); putchar ('\n'); fflush (stdout); } #endif } /*----------------- SET TABLE -------------------*/ DB_READ(dbf, (char FAR *)&set_table[ORIGIN(st_offset)], (DB_REF(Size_st)*sizeof(SET_ENTRY))); for ( i = 0, set_ptr = &set_table[ORIGIN(st_offset)]; i < DB_REF(Size_st); i++, set_ptr++) { /* Byte swap each INT on LITTLE_ENDIAN machines */ NTOHS (set_ptr->st_order); NTOHS (set_ptr->st_own_rt); NTOHS (set_ptr->st_own_ptr); NTOHS (set_ptr->st_members); NTOHS (set_ptr->st_memtot); NTOHS (set_ptr->st_flags); #ifdef DEBUG_INITTAB if (dump_init_tables) { printf ( " SET #%d: ord=%c owner=%d ownofs=%2d mem1=%d mems=%d\n", (int)i, (char)set_ptr->st_order, (int)set_ptr->st_own_rt, (int)set_ptr->st_own_ptr, (int)set_ptr->st_members, (int)set_ptr->st_memtot); fflush (stdout); } #endif } /*----------------- MEMBER TABLE -------------------*/ DB_READ(dbf, (char FAR *)&member_table[ORIGIN(mt_offset)], (DB_REF(Size_mt)*sizeof(MEMBER_ENTRY))); for ( i = 0, mem_ptr = &member_table[ORIGIN(mt_offset)]; i < DB_REF(Size_mt); i++, mem_ptr++) { /* Byte swap each INT on LITTLE_ENDIAN machines */ NTOHS (mem_ptr->mt_record); NTOHS (mem_ptr->mt_mem_ptr); NTOHS (mem_ptr->mt_sort_fld); NTOHS (mem_ptr->mt_totsf); #ifdef DEBUG_INITTAB if (dump_init_tables) { printf ( " MEM #%d: rec=%d ofs=%d sort1=%d sorts=%d\n", (int)i, (int)mem_ptr->mt_record, (int)mem_ptr->mt_mem_ptr, (int)mem_ptr->mt_sort_fld, (int)mem_ptr->mt_totsf); fflush (stdout); } #endif } DB_READ(dbf, (char FAR *)&sort_table[ORIGIN(srt_offset)], (DB_REF(Size_srt)*sizeof(SORT_ENTRY))); /* Member sort tables not used by DtSearch @@@ */ if (DB_REF(Size_srt)) { /* Byte swap each INT on LITTLE_ENDIAN machines */ srt_ptr = &sort_table[ORIGIN(srt_offset)]; NTOHS (srt_ptr->se_fld); NTOHS (srt_ptr->se_set); } DB_READ(dbf, (char FAR *)&key_table[ORIGIN(kt_offset)], (DB_REF(Size_kt)*sizeof(KEY_ENTRY))); /* Compound key tables not used by DtSearch @@@ */ if (DB_REF(Size_kt)) { /* Byte swap each INT on LITTLE_ENDIAN machines */ key_ptr = &key_table[ORIGIN(kt_offset)]; NTOHS (key_ptr->kt_key); NTOHS (key_ptr->kt_field); NTOHS (key_ptr->kt_ptr); NTOHS (key_ptr->kt_sort); } close(dbf); /* end of PASS 2 */ #ifdef DEBUG_INITTAB dump_init_tables = FALSE; #endif #ifndef ONE_DB curr_db_table->key_offset = key_offset; #endif /* update file table path entries */ if ( DB_REF(db_path[0]) || dbfpath[0] ) { for (i = 0, file_ptr = &file_table[ORIGIN(ft_offset)]; i < DB_REF(Size_ft); ++i, ++file_ptr) { /* Construct the data/key file name */ if ( DB_REF(db_path[0]) ) strcpy(dbname, DB_REF(db_path)); else dbname[0] = '\0'; if (strlen(dbname) + strlen(DB_REF(db_name)) >= FILENMLEN+4) return( dberr(S_NAMELEN) ); strcat(dbname, DB_REF(db_name)); if (con_dbf(dbfile, file_ptr->ft_name, dbname, get_element(dbfpath, dbt_lc)) != S_OKAY) return( dberr(db_status) ); /* Save new name in dictionary */ strcpy(file_ptr->ft_name, dbfile); } } #if DB_ENABLE | TS_ENABLE /* adjust record table entries */ for (i = ORIGIN(rt_offset), rec_ptr = &record_table[ORIGIN(rt_offset)]; i < ORIGIN(rt_offset) + DB_REF(Size_rt); ++i, ++rec_ptr) { #ifndef ONE_DB rec_ptr->rt_file += curr_db_table->ft_offset; rec_ptr->rt_fields += curr_db_table->fd_offset; #endif #ifndef NO_TIMESTAMP if ( rec_ptr->rt_flags & TIMESTAMPED ) { db_tsrecs = TRUE; #ifdef ONE_DB break; #endif } #endif } #endif /* adjust field table entries */ for (key_count = 0, i = ORIGIN(fd_offset), fld_ptr = &field_table[ORIGIN(fd_offset)]; i < ORIGIN(fd_offset) + DB_REF(Size_fd); ++i, ++fld_ptr) { #ifndef ONE_DB fld_ptr->fd_rec += curr_db_table->rt_offset; #endif if ( fld_ptr->fd_key != NOKEY ) { fld_ptr->fd_keyno += key_offset; ++key_count; #ifndef ONE_DB fld_ptr->fd_keyfile += curr_db_table->ft_offset; if ( fld_ptr->fd_type == 'k' ) fld_ptr->fd_ptr += curr_db_table->kt_offset; #endif } } key_offset += key_count; #if DB_ENABLE | TS_ENABLE /* adjust set table entries */ for (i = ORIGIN(st_offset), set_ptr = &set_table[ORIGIN(st_offset)]; i < ORIGIN(st_offset) + DB_REF(Size_st); ++i, ++set_ptr) { #ifndef ONE_DB set_ptr->st_own_rt += curr_db_table->rt_offset; set_ptr->st_members += curr_db_table->mt_offset; #endif #ifndef NO_TIMESTAMP if ( set_ptr->st_flags & TIMESTAMPED ) { db_tssets = TRUE; #ifdef ONE_DB break; #endif } #endif } #endif #ifndef ONE_DB /* adjust member table entries */ for (i = curr_db_table->mt_offset, mem_ptr = &member_table[curr_db_table->mt_offset]; i < curr_db_table->mt_offset + curr_db_table->Size_mt; ++i, ++mem_ptr) { mem_ptr->mt_record += curr_db_table->rt_offset; mem_ptr->mt_sort_fld += curr_db_table->srt_offset; } /* adjust sort table entries */ for (i = curr_db_table->srt_offset, srt_ptr = &sort_table[curr_db_table->srt_offset]; i < curr_db_table->srt_offset + curr_db_table->Size_srt; ++i, ++srt_ptr) { srt_ptr->se_fld += curr_db_table->fd_offset; srt_ptr->se_set += curr_db_table->st_offset; } /* adjust key table entries */ for (i = curr_db_table->kt_offset, key_ptr = &key_table[curr_db_table->kt_offset]; i < curr_db_table->kt_offset + curr_db_table->Size_kt; ++i, ++key_ptr) { key_ptr->kt_key += curr_db_table->fd_offset; key_ptr->kt_field += curr_db_table->fd_offset; } } /* end loop for each database */ #endif initcurr(); return( db_status ); }
bool FileRecord::open(bool create) { int oflags = 0; int eflags = DB_INIT_CDB | DB_INIT_MPOOL; if(create) { oflags |= DB_CREATE; eflags |= DB_CREATE; }; int mode = S_IRUSR|S_IWUSR; db_env_ = new DbEnv(DB_CXX_NO_EXCEPTIONS); if(!dberr("Error opening database environment", db_env_->open(basepath_.c_str(),eflags,mode))) { delete db_env_; db_env_ = NULL; db_env_clean(basepath_); db_env_ = new DbEnv(DB_CXX_NO_EXCEPTIONS); if(!dberr("Error opening database environment", db_env_->open(basepath_.c_str(),eflags,mode))) { return false; }; }; dberr("Error setting database environment flags", db_env_->set_flags(DB_CDB_ALLDB,1)); std::string dbpath = FR_DB_NAME; if(!verify()) return false; // db_link // |---db_lock // \---db_locked db_rec_ = new Db(db_env_,DB_CXX_NO_EXCEPTIONS); db_lock_ = new Db(db_env_,DB_CXX_NO_EXCEPTIONS); db_locked_ = new Db(db_env_,DB_CXX_NO_EXCEPTIONS); db_link_ = new Db(db_env_,DB_CXX_NO_EXCEPTIONS); if(!dberr("Error setting flag DB_DUPSORT",db_lock_->set_flags(DB_DUPSORT))) return false; if(!dberr("Error setting flag DB_DUPSORT",db_locked_->set_flags(DB_DUPSORT))) return false; if(!dberr("Error associating databases",db_link_->associate(NULL,db_lock_,&locked_callback,0))) return false; if(!dberr("Error associating databases",db_link_->associate(NULL,db_locked_,&lock_callback,0))) return false; if(!dberr("Error opening database 'meta'", db_rec_->open(NULL,dbpath.c_str(), "meta", DB_BTREE,oflags,mode))) return false; if(!dberr("Error opening database 'link'", db_link_->open(NULL,dbpath.c_str(), "link", DB_RECNO,oflags,mode))) return false; if(!dberr("Error opening database 'lock'", db_lock_->open(NULL,dbpath.c_str(), "lock", DB_BTREE,oflags,mode))) return false; if(!dberr("Error opening database 'locked'", db_locked_->open(NULL,dbpath.c_str(),"locked",DB_BTREE,oflags,mode))) return false; return true; }
int main(int argc, char *argv[]) { extern int optind; extern char *optarg; enum S command, state; DB *dbp; DBT data, key, keydata; size_t len; int ch, oflags, sflag; char *fname, *infoarg, *p, *t, buf[8 * 1024]; infoarg = NULL; fname = NULL; oflags = O_CREAT | O_RDWR; sflag = 0; while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1) switch (ch) { case 'f': fname = optarg; break; case 'i': infoarg = optarg; break; case 'l': oflags |= DB_LOCK; break; case 'o': if ((ofd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) dberr("%s: %s", optarg, strerror(errno)); break; case 's': sflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc != 2) usage(); /* Set the type. */ type = dbtype(*argv++); /* Open the descriptor file. */ if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) dberr("%s: %s", *argv, strerror(errno)); /* Set up the db structure as necessary. */ if (infoarg == NULL) infop = NULL; else for (p = strtok(infoarg, ",\t "); p != NULL; p = strtok(0, ",\t ")) if (*p != '\0') infop = setinfo(type, p); /* * Open the DB. Delete any preexisting copy, you almost never * want it around, and it often screws up tests. */ if (fname == NULL) { p = getenv("TMPDIR"); if (p == NULL) p = "/var/tmp"; (void)snprintf(buf, sizeof buf, "%s/__dbtest", p); fname = buf; (void)unlink(buf); } else if (!sflag) (void)unlink(fname); if ((dbp = dbopen(fname, oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) dberr("dbopen: %s", strerror(errno)); XXdbp = dbp; state = COMMAND; for (lineno = 1; (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { /* Delete the newline, displaying the key/data is easier. */ if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) *t = '\0'; if ((len = strlen(buf)) == 0 || isspace((unsigned char)*p) || *p == '#') continue; /* Convenient gdb break point. */ if (XXlineno == lineno) XXlineno = 1; switch (*p) { case 'c': /* compare */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); state = KEY; command = COMPARE; break; case 'e': /* echo */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); /* Don't display the newline, if CR at EOL. */ if (p[len - 2] == '\r') --len; if (write(ofd, p + 1, len - 1) != len - 1 || write(ofd, "\n", 1) != 1) dberr("write: %s", strerror(errno)); break; case 'g': /* get */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); state = KEY; command = GET; break; case 'p': /* put */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); state = KEY; command = PUT; break; case 'r': /* remove */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); if (flags == R_CURSOR) { rem(dbp, &key); state = COMMAND; } else { state = KEY; command = REMOVE; } break; case 'S': /* sync */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); synk(dbp); state = COMMAND; break; case 's': /* seq */ if (state != COMMAND) dberr("line %lu: not expecting command", lineno); if (flags == R_CURSOR) { state = KEY; command = SEQ; } else seq(dbp, &key); break; case 'f': flags = setflags(p + 1); break; case 'D': /* data file */ if (state != DATA) dberr("line %lu: not expecting data", lineno); data.data = rfile(p + 1, &data.size); goto ldata; case 'd': /* data */ if (state != DATA) dberr("line %lu: not expecting data", lineno); data.data = xmalloc(p + 1, len - 1); data.size = len - 1; ldata: switch (command) { case COMPARE: compare(&keydata, &data); break; case PUT: put(dbp, &key, &data); break; default: dberr("line %lu: command doesn't take data", lineno); } if (type != DB_RECNO) free(key.data); free(data.data); state = COMMAND; break; case 'K': /* key file */ if (state != KEY) dberr("line %lu: not expecting a key", lineno); if (type == DB_RECNO) dberr("line %lu: 'K' not available for recno", lineno); key.data = rfile(p + 1, &key.size); goto lkey; case 'k': /* key */ if (state != KEY) dberr("line %lu: not expecting a key", lineno); if (type == DB_RECNO) { static recno_t recno; recno = atoi(p + 1); key.data = &recno; key.size = sizeof(recno); } else { key.data = xmalloc(p + 1, len - 1); key.size = len - 1; } lkey: switch (command) { case COMPARE: getdata(dbp, &key, &keydata); state = DATA; break; case GET: get(dbp, &key); if (type != DB_RECNO) free(key.data); state = COMMAND; break; case PUT: state = DATA; break; case REMOVE: rem(dbp, &key); if ((type != DB_RECNO) && (flags != R_CURSOR)) free(key.data); state = COMMAND; break; case SEQ: seq(dbp, &key); if ((type != DB_RECNO) && (flags != R_CURSOR)) free(key.data); state = COMMAND; break; default: dberr("line %lu: command doesn't take a key", lineno); } break; case 'o': dump(dbp, p[1] == 'r'); break; default: dberr("line %lu: %s: unknown command character", lineno, p); } } #ifdef STATISTICS /* * -l must be used (DB_LOCK must be set) for this to be * used, otherwise a page will be locked and it will fail. */ if (type == DB_BTREE && oflags & DB_LOCK) __bt_stat(dbp); #endif if (dbp->close(dbp)) dberr("db->close: %s", strerror(errno)); (void)close(ofd); exit(0); }