12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031 |
- /*
- * $Id$
- *
- * recovery for berkeley_db module
- * Copyright (C) 2007 Cisco Systems
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * --------
- * 2007-09-19 genesis (wiquan)
- */
- #include <unistd.h>
- #include "kambdb_recover.h"
- tbl_cache_p tables;
- char* schema_dir = NULL;
- char* db_home = NULL;
- const char *progname;
- /**
- * main --
- */
- int main(int argc, char* argv[])
- {
- int ret, ch, i;
-
- ret = 0;
- progname = argv[0];
-
- while ((ch = getopt(argc, argv, "s:h:c:C:r:R:")) != EOF)
- switch (ch)
- {
- case 's':
- schema_dir = optarg;
- load_schema(optarg);
- break;
-
- case 'c': /*create <tablename> */
- ret = create(optarg);
- break;
-
- case 'C': /*Create all*/
- ret = create_all();
- break;
-
- case 'r': /*recover <filename> */
- ret = recover(optarg);
- break;
-
- case 'R': /*recover_all <MAXFILES> */
- ret = sscanf(optarg,"%i", &i);
- if(ret != 1) return -1;
- ret = recover_all(i);
- break;
-
- case 'h':
- db_home = optarg;
- break;
-
- case '?':
- default:
- return(usage());
-
- }
-
- argc -= optind;
- argv += optind;
-
- /*free mem; close open files.*/
- cleanup();
-
- return ret;
- }
- /**
- * usage --
- *
- */
- int usage(void)
- {
- fprintf(stderr, "usage: %s %s\n", progname,
- "-s schemadir [-h home] [-c tablename]");
-
- fprintf(stderr, "usage: %s %s\n", progname,
- "-s schemadir [-h home] [-C all]");
-
- fprintf(stderr, "usage: %s %s\n", progname,
- "-s schemadir [-h home] [-r journal-file]");
-
- fprintf(stderr, "usage: %s %s\n", progname,
- "-s schemadir [-h home] [-R lastN]");
-
- return (EXIT_FAILURE);
- }
- /**
- * create -- creates a Berkeley DB file with tablename (tn), along with
- * the needed metadata.
- * requires the schema data to be already parsed '-L' option.
- */
- int create(char* tn)
- {
- DB* db;
- int rc;
- tbl_cache_p tbc = NULL;
- table_p tp = NULL;
- rc = 0;
-
- tbc = get_table(tn);
- if(!tbc)
- { fprintf(stderr, "[create] Table %s is not supported.\n",tn);
- return 1;
- }
-
- tp = tbc->dtp;
- db = get_db(tp);
-
- if(db)
- {
- printf("Created table %s\n",tn);
- rc = 0;
- }
- else
- {
- fprintf(stderr, "[create] Failed to create table %s\n",tn);
- rc = 1;
- }
-
- return rc;
- }
- /**
- * create_all -- creates a new Berkeley DB table for only the core tables
- */
- int create_all(void)
- {
- tbl_cache_p _tbc = tables;
- int rc;
- rc = 0;
-
- #ifdef EXTRA_DEBUG
- time_t tim1 = time(NULL);
- time_t tim2;
- #endif
- while(_tbc)
- {
- if(_tbc->dtp)
- if((rc = create(_tbc->dtp->name)) != 0 )
- break;
- _tbc = _tbc->next;
- }
-
- #ifdef EXTRA_DEBUG
- tim2 = time(NULL);
- int i = tim2 - tim1;
- printf("took %i sec\n", i);
- #endif
- return rc;
- }
- /**
- * file_list --
- * returns a sorted linkedlist of all files in d
- *
- * parmameter d is the directory name
- * parameter tn is optional,
- * if tablename (tn) is specified returns only jnl files for tablename (tn)
- * else returns a sorted linkedlist of all files in d
- * returns lnode_p
- * the head linknode points to the latests file.
- */
- lnode_p file_list(char* d, char* tn)
- {
- DIR *dirp;
- int i, j, len;
- char *fn;
- char *list[MAXFILES];
- char dir[MAX_FILENAME_SIZE];
- struct dirent *dp;
- lnode_p h,n;
-
- h = n = NULL;
- i = j = 0;
-
- if(!d)
- {
- fprintf(stderr, "[file_list]: null path to schema files.\n");
- return NULL;
- }
-
- memset(dir, 0, MAX_FILENAME_SIZE);
- strcpy(dir, d);
- strcat(dir, "/");
- //strcat(dir, ".");
- dirp = opendir(dir);
-
- while ((dp = readdir(dirp)) != NULL)
- { j=0;
- if (i> (MAXFILES-1) )
- continue;
-
- fn = dp->d_name;
-
- if (fn[0] == '.')
- continue;
-
- if(tn)
- {
- /* only looking for jnl files */
- len = strlen(tn);
- if (!strstr(fn, ".jnl")) continue;
- if (strncmp(fn, tn, len)) continue;
- }
-
- j = strlen(fn) +1;
- list[i] = malloc(sizeof(char) * j);
- memset(list[i], 0 , j);
- strcat(list[i], fn);
- i++;
- }
-
- closedir(dirp);
- qsort(list, i, sizeof(char*), compare);
-
- for(j=0;j<i;j++)
- {
- n = malloc(sizeof(lnode_t));
- if(!n) return NULL;
- n->prev=NULL;
- n->p = list[j];
- if(h) h->prev = n;
- n->next = h;
- h = n;
- }
- return h;
- }
- /** qsort C-string comparison function */
- int compare (const void *a, const void *b)
- {
- const char **ia = (const char **)a;
- const char **ib = (const char **)b;
- return strcmp(*ia, *ib);
- }
- /**
- * recover -- given a journal filename, creates a new db w. metadata, and replays
- * the events in journalized order.
- * Results in a new db containing the journaled data.
- *
- * fn (filename) must be in the form:
- * location-20070803175446.jnl
- */
- int recover(char* jfn)
- {
- #ifdef EXTRA_DEBUG
- time_t tim1 = time(NULL);
- time_t tim2;
- #endif
- int len, i, cs, ci, cd, cu;
- char *v, *s;
- char line [MAX_ROW_SIZE];
- char tn [MAX_TABLENAME_SIZE];
- char fn [MAX_FILENAME_SIZE];
- char op [7]; //INSERT, DELETE, UPDATE are all 7 char wide (w. null)
- FILE * fp = NULL;
- tbl_cache_p tbc = NULL;
- table_p tp = NULL;
- i = 0 ;
- cs = ci = cd = cu = 0;
-
- if(!strstr(jfn, ".jnl"))
- {
- fprintf(stderr, "[recover]: Does NOT look like a journal file: %s.\n", jfn);
- return 1;
- }
-
- if(!db_home)
- {
- fprintf(stderr, "[recover]: null path to db_home.\n");
- return 1;
- }
-
- /*tablename tn*/
- s = strchr(jfn, '-');
- len = s - jfn;
- strncpy(tn, jfn, len);
- tn[len] = 0;
-
- /*create abs path to journal file relative to db_home*/
- memset(fn, 0 , MAX_FILENAME_SIZE);
- strcat(fn, db_home);
- strcat(fn, "/");
- strcat(fn, jfn);
-
- fp = fopen(fn, "r");
- if(!fp)
- {
- fprintf(stderr, "[recover]: FAILED to load journal file: %s.\n", jfn);
- return 2;
- }
-
- tbc = get_table(tn);
- if(!tbc)
- {
- fprintf(stderr, "[recover]: Table %s is not supported.\n",tn);
- fprintf(stderr, "[recover]: FAILED to load journal file: %s.\n", jfn);
- fclose(fp);
- return 2;
- }
-
- if(!tbc || !tbc->dtp)
- {
- fprintf(stderr, "[recover]: FAILED to get find metadata for : %s.\n", tn);
- fclose(fp);
- return 3;
- }
- tp = tbc->dtp;
-
- while ( fgets(line , MAX_ROW_SIZE, fp) != NULL )
- {
- len = strlen(line);
- if(line[0] == '#' || line[0] == '\n') continue;
-
- if(len > 0) line[len-1] = 0; /*chomp trailing \n */
-
- v = strchr(line, '|');
- len = v - line;
-
- strncpy(op, line, len);
- op[len] = 0;
-
- switch( get_op(op, len) )
- {
- case INSERT:
- v++; //now v points to data
- len = strlen(v);
- insert(tp, v, len);
- ci++;
- break;
-
- case UPDATE:
- v++;
- len = strlen(v);
- update(tp, v, len);
- cu++;
- break;
-
- case DELETE:
- //v is really the key
- delete(tp, v, len);
- cd++;
- break;
-
- case UNKNOWN_OP:
- fprintf(stderr,"[recover]: UnknownOP - Skipping ROW: %s\n",line);
- cs++;
- continue;
- }
- i++;
- }
-
- #ifdef EXTRA_DEBUG
- printf("Processed journal file: %s.\n", jfn);
- printf("INSERT %i records.\n",ci);
- printf("UPDATE %i records.\n",cu);
- printf("DELETE %i records.\n",cd);
- printf("SKIPed %i records.\n",cs);
- printf("------------------------\n");
- printf("Total %i records.\n",i);
-
- tim2 = time(NULL);
- i = tim2 - tim1;
- printf("took %i sec\n", i);
- #endif
-
- fclose(fp);
-
- return 0;
- }
- /**
- * recover_all -- Iterates over all core tables in enumerated order for recovery from
- * journal files (.jnl).
- * The parm 'lastn' is the number of journal files needed to be recovered.
- * Hardcoded to only find MAXFILES.
- *
- * e.g.
- * 25 journal files are present for the 'acc' table, however you only
- * want to restore the latest 3; so lastn=3.
- */
- int recover_all(int lastn)
- {
- lnode_p n, h;
- tbl_cache_p _tbc = tables;
-
- if(MAXFILES < lastn) return 1;
- if(!schema_dir)
- {
- fprintf(stderr, "[recover_all]: null path to schema files.\n");
- return 1;
- }
- if(!db_home)
- {
- fprintf(stderr, "[recover_all]: null path to db_home.\n");
- return 1;
- }
-
- while(_tbc)
- {
- int j;
-
- if(_tbc->dtp)
- h = file_list(db_home, _tbc->dtp->name);
- n = h;
-
- /*lastn; move to the oldest of the N*/
- for(j=1;j<lastn;j++)
- if(n && (n->next != NULL) )
- n = n->next;
- while(n)
- { printf("[recover_all] recovering file: %s\n",n->p);
- if(recover(n->p))
- fprintf(stderr, "[recover_all]: Error while recovering: [%s]\n. Continuing..\n",n->p);
- n = n->prev;
- }
-
- while(h) /*free mem*/
- { n = h->next;
- free(h->p);
- free(h);
- h = n;
- }
-
- _tbc = _tbc->next;
- }
-
- return 0;
- }
- /**
- * extract_key -- uses the internal schema to extract the key from the data
- * row that was found in the journal.
- * caller provides inititialize memory for destination key (k).
- * data is provided ; key is filled in
- */
- int extract_key(table_p tp, char* k, char* d)
- {
- char *s, *p;
- char buf[MAX_ROW_SIZE];
- int n, len;
-
- if(!tp || !k || !d) return -1;
- len=n=0;
- p = k;
-
- /*copy data so we can tokenize w.o trampling */
- len = strlen(d);
- strncpy(buf, d, len);
- buf[len] = 0;
-
- s = strtok(buf, "|");
- while(s!=NULL && n<MAX_NUM_COLS)
- {
- len = strlen(s);
- if( (tp->ncols-1) > n)
- {
- if( tp->colp[n]->kflag )
- {
- strncpy(p, s, len);
- p+=len;
-
- *p = '|';
- p++;
- }
- }
-
- s=strtok(NULL, "|");
- n++;
- }
-
- *p = 0;
- return 0;
- }
- /**
- * delete -- deletes a row from the db we are trying to rebuild
- */
- int delete(table_p tp, char* k, int len)
- {
- DBT key;
- DB *db;
-
- if(!tp || !k) return 1;
- if((db = get_db(tp)) == NULL) return 2;
-
- memset(&key, 0, sizeof(DBT));
- key.data = k;
- key.ulen = MAX_ROW_SIZE;
- key.size = len;
-
- if ( db->del(db, NULL, &key, 0))
- {
- fprintf(stderr, "[delete] FAILED --> [%.*s] \n", len, k);
- return 3;
- }
-
- return 0;
- }
- /**
- * _insert -- inserts a new row in to the db we are trying to rebuild
- * I needed this to directly insert metadata when the db is created.
- */
- int _insert(DB* db, char* k, char* v, int klen, int vlen)
- {
- DBT key, data;
-
- if(!db || !k || !v) return 1;
-
- memset(&key, 0, sizeof(DBT));
- key.data = k;
- key.ulen = MAX_ROW_SIZE;
- key.size = klen;
-
- memset(&data, 0, sizeof(DBT));
- data.data = v;
- data.ulen = MAX_ROW_SIZE;
- data.size = vlen;
- if (db->put(db, NULL, &key, &data, 0))
- {
- fprintf(stderr, "[insert] FAILED --> [%.*s] \n", vlen, v);
- return 1;
- }
- return 0;
- }
- /**
- * insert -- given the data row (v) and its length (vlen), we build the corresponding
- * key, and insert the data in to the db.
- * This will over-right the value if already present.
- */
- int insert(table_p tp, char* v, int vlen)
- {
- char k[MAX_ROW_SIZE];
- int rc, klen;
- DB *db;
-
- if(!tp || !v) return 1;
- if((db = get_db(tp)) == NULL) return 2;
-
- memset(k,0,MAX_ROW_SIZE);
- if( extract_key(tp, k, v) )
- {
- fprintf(stderr, "[insert] failed to extract key for row: %.*s",vlen, v);
- return 2;
- }
-
- klen = strlen(k);
- rc = _insert(db, k, v, klen, vlen);
-
- return rc;
- }
- /**
- * update -- given the data row (v) and its length (vlen), we build the corresponding
- * key, and update the data in the db.
- * This is implemented as DELETE + INSERT.
- */
- int update(table_p tp, char* v, int len)
- {
- char k[MAX_ROW_SIZE];
-
- if(!tp || !v) return 1;
-
- memset(k,0,MAX_ROW_SIZE);
- if( extract_key(tp, k, v) )
- {
- fprintf(stderr, "[update] failed to extract key for row: %.*s",len, v);
- return 2;
- }
-
- /* if( delete(tp, k, strlen(k)) ) return 3; */
- if( insert(tp, v, len) ) return 4;
- return 0;
- }
- /**
- * get_op -- used to convert the string operation name to an enumerated op
- */
- int get_op(char* op, int len)
- {
- if((len==6) && strstr("INSERT",op) ) return INSERT;
- if((len==6) && strstr("UPDATE",op) ) return UPDATE;
- if((len==6) && strstr("DELETE",op) ) return DELETE;
-
- return UNKNOWN_OP;
- }
- /**
- * load_schema -- sets up the internal representation of the schema.
- */
- int load_schema(char* d)
- { int rc;
- char *tn;
- char line1 [MAX_ROW_SIZE];
- char line2 [MAX_ROW_SIZE];
- char fn [MAX_FILENAME_SIZE];
- tbl_cache_p tbc = NULL;
- table_p tp = NULL;
- FILE * fp = NULL;
- lnode_p h,n;
-
- rc=0;
- h = n = NULL;
-
- if(!d)
- {
- fprintf(stderr, "[load_schema]: null path to schema files.\n");
- return 1;
- }
-
- tables = (tbl_cache_p)malloc(sizeof(tbl_cache_t));
- if(!tables) return 1;
-
- h = file_list(d, NULL);
-
- while(h)
- {
- n = h->next;
-
- /*create abs path to journal file (relative to db_home) */
- memset(fn, 0 , MAX_FILENAME_SIZE);
- strcat(fn, d);
- strcat(fn, "/");
- strcat(fn, h->p);
-
- fp = fopen(fn, "r");
- if(!fp)
- {
- fprintf(stderr, "[load_schema]: FAILED to load schema file: %s.\n", h->p);
- break;
- }
-
- tn = h->p;
- tbc = get_table(tn);
- if(!tbc)
- {
- fprintf(stderr, "[load_schema]: Table %s is not supported.\n",tn);
- fprintf(stderr, "[load_schema]: FAILED to load data for table: %s.\n", tn);
- goto done;
- }
-
- tp = tbc->dtp;
-
- while ( fgets(line1 , MAX_ROW_SIZE, fp) != NULL )
- {
- if ( fgets(line2 , MAX_ROW_SIZE, fp) != NULL )
- {
- if(strstr(line1, METADATA_COLUMNS))
- {
- if(0!=load_metadata_columns(tp, line2))
- {
- fprintf(stderr, "[load_schema]: FAILED to load METADATA COLS in table: %s.\n", tn);
- goto done;
- }
- }
-
- if(strstr(line1, METADATA_KEY))
- {
- if(0!=load_metadata_key(tp, line2))
- {
- fprintf(stderr, "[load_schema]: FAILED to load METADATA KEYS in table: %s.\n", tn);
- goto done;
- }
- }
- }
- else
- {
- fprintf(stderr, "[load_schema]: FAILED to read schema value in table: %s.\n", tn);
- goto done;
- }
-
- }
- done:
- fclose(fp);
- h = n;
- }
-
- while(h) /*free mem*/
- { n = h->next;
- free(h->p);
- free(h);
- h = n;
- }
-
- return rc;
- }
- /**
- * get_table -- return pointer to lazy initialized table struct
- */
- tbl_cache_p get_table(char *_s)
- {
- tbl_cache_p _tbc = tables;
- table_p _tp = NULL;
- while(_tbc)
- {
- if(_tbc->dtp)
- {
- if(_tbc->dtp->name
- && !strcmp(_tbc->dtp->name,_s))
- {
- return _tbc;
- }
- }
- _tbc = _tbc->next;
- }
-
- _tbc = (tbl_cache_p)malloc(sizeof(tbl_cache_t));
- if(!_tbc)
- return NULL;
-
- _tp = create_table(_s);
-
- if(!_tp)
- {
- fprintf(stderr, "[get_table]: failed to create table.\n");
- free(_tbc);
- return NULL;
- }
-
- _tbc->dtp = _tp;
-
- if(tables)
- (tables)->prev = _tbc;
-
- _tbc->next = tables;
- tables = _tbc;
- return _tbc;
- }
- /**
- * create_table -- returns an initialed table struct
- */
- table_p create_table(char *_s)
- {
- int i;
- table_p tp = NULL;
-
- tp = (table_p)malloc(sizeof(table_t));
- if(!tp) return NULL;
-
- i=strlen(_s)+1;
- tp->name = (char*)malloc(i*sizeof(char));
- strncpy(tp->name, _s, i);
-
- tp->ncols=0;
- tp->nkeys=0;
- tp->ro=0;
- tp->logflags=0;
- tp->db = NULL;
-
- for(i=0;i<MAX_NUM_COLS;i++)
- tp->colp[i] = NULL;
-
- return tp;
- }
- /**
- * load_metadata_columns -- parses the METADATA_COLUMNS line into the internal
- * representation.
- */
- int load_metadata_columns(table_p _tp, char* line)
- {
- int ret,n,len;
- char *s = NULL;
- char cn[64], ct[16];
- column_p col;
- ret = n = len = 0;
-
- if(!_tp) return -1;
- if(_tp->ncols!=0) return 0;
-
- /* eg: line = "table_name(str) table_version(int)" */
- s = strtok(line, " \t");
- while(s!=NULL && n<MAX_NUM_COLS)
- {
- /* eg: meta[0]=table_name meta[1]=str */
- sscanf(s,"%20[^(](%10[^)])[^\n]", cn, ct);
-
- /* create column*/
- col = (column_p) malloc(sizeof(column_t));
- if(!col)
- { fprintf(stderr, "load_metadata_columns: out of memory \n");
- return -1;
- }
-
- /* set name*/
- len = strlen( cn )+1;
- col->name = (char*)malloc(len * sizeof(char));
- strcpy(col->name, cn );
-
- /* set type*/
- len = strlen( ct )+1;
- col->type = (char*)malloc(len * sizeof(char));
- strcpy(col->type, ct );
-
- _tp->colp[n] = col;
- n++;
- _tp->ncols++;
- s=strtok(NULL, " \t");
- }
- return 0;
- }
- /**
- * load_metadata_key -- parses the METADATA_KEY line into the internal
- * representation.
- */
- int load_metadata_key(table_p _tp, char* line)
- {
- int ret,n,ci;
- char *s = NULL;
- ret = n = ci = 0;
-
- if(!_tp)return -1;
-
- s = strtok(line, " \t");
- while(s!=NULL && n< _tp->ncols)
- {
- ret = sscanf(s,"%i", &ci);
- if(ret != 1) return -1;
- if( _tp->colp[ci] )
- { _tp->colp[ci]->kflag = 1;
- _tp->nkeys++;
- }
- n++;
- s=strtok(NULL, " ");
- }
-
- return 0;
- }
- /**
- * get_db -- lazy initialized DB access
- * Its like this so we get new db files only for the tables that have
- * journal files.
- * The db file on disk will be named:
- * <tablename>.new
- */
- DB* get_db(table_p tp)
- {
- int rc;
- DB* db;
- char dfn[MAX_FILENAME_SIZE];
-
- if( !tp) return NULL;
- if( tp->db) return tp->db;
-
- memset(dfn, 0, MAX_FILENAME_SIZE);
- if(db_home)
- {
- strcpy(dfn, db_home);
- strcat(dfn, "/");
- }
-
- /*creation of DB follows*/
- strcat(dfn, tp->name);
-
- if ((rc = db_create(&db, NULL, 0)) != 0)
- {
- fprintf(stderr, "[create_table]: error db_create for table: %s.\n",dfn);
- return NULL;
- }
-
- if ((rc = db->open(db, NULL, dfn, NULL, DB_HASH, DB_CREATE, 0664)) != 0)
- {
- fprintf(stderr, "[create_table]: error opening %s.\n",dfn);
- fprintf(stderr, "[create_table]: error msg: %s.\n",db_strerror(rc));
- return NULL;
- }
- tp->db = db;
-
- import_schema(tp);
-
- return db;
- }
- /**
- */
- int import_schema(table_p tp)
- {
- int rc, len1, len2;
- char line1 [MAX_ROW_SIZE];
- char line2 [MAX_ROW_SIZE];
- char fn [MAX_FILENAME_SIZE];
- FILE * fp = NULL;
- rc = 0;
-
- if(!schema_dir)
- {
- fprintf(stderr, "[import_schema]: null schema dir.\n");
- return 1;
- }
-
- if(!tp)
- {
- fprintf(stderr, "[import_schema]: null table parameter.\n");
- return 1;
- }
-
- /*create abs path to journal file (relative to db_home) */
- memset(fn, 0 , MAX_FILENAME_SIZE);
- strcat(fn, schema_dir);
- strcat(fn, "/");
- strcat(fn, tp->name);
-
- fp = fopen(fn, "r");
- if(!fp)
- {
- fprintf(stderr, "[import_schema]: FAILED to open def schema file: %s.\n", fn);
- return 1;
- }
- while ( fgets(line1 , MAX_ROW_SIZE, fp) != NULL )
- {
- if ( fgets(line2 , MAX_ROW_SIZE, fp) != NULL )
- {
- len1 = strlen(line1)-1;
- len2 = strlen(line2)-1;
- line1[len1] = 0;
- line2[len2] = 0;
-
- if((rc = _insert(tp->db, line1, line2, len1, len2) )!=0)
- {
- fprintf(stderr, "[import_schema]: FAILED to write schema def into table: %s.\n", tp->name);
- goto done;
- }
- }
- else
- {
- fprintf(stderr, "[import_schema]: FAILED to read schema def value in table: %s.\n", tp->name);
- goto done;
- }
-
- }
- done:
- fclose(fp);
- return rc;
- }
- /**
- * cleanup -- frees memory; closes any files.
- */
- void cleanup(void)
- {
- //cleanup
- while(tables)
- { int i;
- tbl_cache_p n = tables->next;
- table_p tp = tables->dtp;
- if(tp)
- {
- free(tp->name);
- for(i=0;i< tp->ncols;i++)
- {
- free(tp->colp[i]->name);
- free(tp->colp[i]->type);
- free(tp->colp[i]);
- }
-
- if(tp->db)
- tp->db->close(tp->db, 0);
-
- free(tp);
- }
- free(tables);
- tables = n;
- }
- }
|