00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <time.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <dirent.h>
00036
00037 #include "../../mem/shm_mem.h"
00038 #include "../../mem/mem.h"
00039 #include "../../dprint.h"
00040
00041 #include "dbt_util.h"
00042 #include "dbt_lib.h"
00043
00044
00050 int dbt_check_mtime(const str *tbn, const str *dbn, time_t *mt)
00051 {
00052 char path[512];
00053 struct stat s;
00054 int ret = 0;
00055
00056 path[0] = 0;
00057 if(dbn && dbn->s && dbn->len>0)
00058 {
00059 if(dbn->len+tbn->len<511)
00060 {
00061 strncpy(path, dbn->s, dbn->len);
00062 path[dbn->len] = '/';
00063 strncpy(path+dbn->len+1, tbn->s, tbn->len);
00064 path[dbn->len+tbn->len+1] = 0;
00065 }
00066 }
00067 if(path[0] == 0)
00068 {
00069 strncpy(path, tbn->s, tbn->len);
00070 path[tbn->len] = 0;
00071 }
00072 if(stat(path, &s) == 0)
00073 {
00074 if((int)s.st_mtime > (int)*mt)
00075 {
00076 ret = 1;
00077 *mt = s.st_mtime;
00078 LM_DBG("[%.*s] was updated\n", tbn->len, tbn->s);
00079 }
00080 } else {
00081 LM_DBG("stat failed on [%.*s]\n", tbn->len, tbn->s);
00082 ret = -1;
00083 }
00084 return ret;
00085 }
00086
00090 dbt_table_p dbt_load_file(const str *tbn, const str *dbn)
00091 {
00092 FILE *fin=NULL;
00093 char path[512], buf[4096];
00094 int c, crow, ccol, bp, sign, max_auto;
00095 dbt_val_t dtval;
00096 dbt_table_p dtp = NULL;
00097 dbt_column_p colp, colp0 = NULL;
00098 dbt_row_p rowp, rowp0 = NULL;
00099
00100 enum {DBT_FLINE_ST, DBT_NLINE_ST, DBT_DATA_ST} state;
00101
00102 LM_DBG("request for table [%.*s]\n", tbn->len, tbn->s);
00103
00104 if(!tbn || !tbn->s || tbn->len<=0 || tbn->len>=255)
00105 return NULL;
00106 path[0] = 0;
00107 if(dbn && dbn->s && dbn->len>0)
00108 {
00109 LM_DBG("db is [%.*s]\n", dbn->len, dbn->s);
00110 if(dbn->len+tbn->len<511)
00111 {
00112 strncpy(path, dbn->s, dbn->len);
00113 path[dbn->len] = '/';
00114 strncpy(path+dbn->len+1, tbn->s, tbn->len);
00115 path[dbn->len+tbn->len+1] = 0;
00116 }
00117 }
00118 if(path[0] == 0)
00119 {
00120 strncpy(path, tbn->s, tbn->len);
00121 path[tbn->len] = 0;
00122 }
00123
00124 LM_DBG("loading file [%s]\n", path);
00125 fin = fopen(path, "rt");
00126 if(!fin)
00127 return NULL;
00128
00129 dtp = dbt_table_new(tbn, dbn, path);
00130 if(!dtp)
00131 goto done;
00132
00133 state = DBT_FLINE_ST;
00134 crow = ccol = -1;
00135 colp = colp0 = NULL;
00136 rowp = rowp0 = NULL;
00137 c = fgetc(fin);
00138 max_auto = 0;
00139 while(c!=EOF)
00140 {
00141 switch(state)
00142 {
00143 case DBT_FLINE_ST:
00144
00145 bp = 0;
00146 while(c==DBT_DELIM_C)
00147 c = fgetc(fin);
00148 if(c==DBT_DELIM_R && !colp0)
00149 goto clean;
00150 if(c==DBT_DELIM_R)
00151 {
00152 if(dtp->nrcols <= 0)
00153 goto clean;
00154 dtp->colv = (dbt_column_p*)
00155 shm_malloc(dtp->nrcols*sizeof(dbt_column_p));
00156 if(!dtp->colv)
00157 goto clean;
00158 colp0 = dtp->cols;
00159 for(ccol=0; ccol<dtp->nrcols && colp0; ccol++)
00160 {
00161 dtp->colv[ccol] = colp0;
00162 colp0 = colp0->next;
00163 }
00164 state = DBT_NLINE_ST;
00165 break;
00166 }
00167 while(c!=DBT_DELIM_C && c!='(' && c!=DBT_DELIM_R)
00168 {
00169 if(c==EOF)
00170 goto clean;
00171 buf[bp++] = c;
00172 c = fgetc(fin);
00173 }
00174 colp = dbt_column_new(buf, bp);
00175 if(!colp)
00176 goto clean;
00177
00178 while(c==DBT_DELIM_C)
00179 c = fgetc(fin);
00180 if(c!='(')
00181 goto clean;
00182 c = fgetc(fin);
00183 while(c==DBT_DELIM_C)
00184 c = fgetc(fin);
00185
00186 switch(c)
00187 {
00188 case 's':
00189 case 'S':
00190 colp->type = DB1_STR;
00191 LM_DBG("column[%d] is STR!\n", ccol+1);
00192 break;
00193 case 'i':
00194 case 'I':
00195 colp->type = DB1_INT;
00196 LM_DBG("column[%d] is INT!\n", ccol+1);
00197 break;
00198 case 'd':
00199 case 'D':
00200 colp->type = DB1_DOUBLE;
00201 LM_DBG("column[%d] is DOUBLE!\n", ccol+1);
00202 break;
00203 case 'b':
00204 case 'B':
00205 colp->type = DB1_BLOB;
00206 LM_DBG("column[%d] is BLOB!\n", ccol+1);
00207 break;
00208 case 't':
00209 case 'T':
00210 colp->type = DB1_DATETIME;
00211 LM_DBG("column[%d] is TIME!\n", ccol+1);
00212 break;
00213 default:
00214 LM_DBG("wrong column type!\n");
00215 goto clean;
00216 }
00217
00218 while(c!='\n' && c!=EOF && c!=')' && c!= ',')
00219 {
00220 if(colp->type == DB1_STR && (c=='i'|| c=='I'))
00221 {
00222 colp->type = DB1_STRING;
00223 LM_DBG("column[%d] is actually STRING!\n", ccol+1);
00224 }
00225 c = fgetc(fin);
00226 }
00227 if(c==',')
00228 {
00229
00230 c = fgetc(fin);
00231 while(c==DBT_DELIM_C)
00232 c = fgetc(fin);
00233 if(c=='N' || c=='n')
00234 {
00235
00236 colp->flag |= DBT_FLAG_NULL;
00237 }
00238 else if(colp->type==DB1_INT && dtp->auto_col<0
00239 && (c=='A' || c=='a'))
00240 {
00241
00242 colp->flag |= DBT_FLAG_AUTO;
00243 dtp->auto_col = ccol+1;
00244 }
00245 else
00246 goto clean;
00247 while(c!=')' && c!=DBT_DELIM_R && c!=EOF)
00248 c = fgetc(fin);
00249 }
00250 if(c == ')')
00251 {
00252
00253 if(colp0)
00254 {
00255 colp->prev = colp0;
00256 colp0->next = colp;
00257 }
00258 else
00259 dtp->cols = colp;
00260 colp0 = colp;
00261 dtp->nrcols++;
00262 c = fgetc(fin);
00263 }
00264 else
00265 goto clean;
00266 ccol++;
00267 break;
00268
00269 case DBT_NLINE_ST:
00270
00271 while(c==DBT_DELIM_R)
00272 c = fgetc(fin);
00273 if(rowp)
00274 {
00275 if(dbt_table_check_row(dtp, rowp))
00276 goto clean;
00277
00278 if(!rowp0)
00279 dtp->rows = rowp;
00280 else
00281 {
00282 rowp0->next = rowp;
00283 rowp->prev = rowp0;
00284 }
00285 rowp0 = rowp;
00286 dtp->nrrows++;
00287 }
00288 if(c==EOF)
00289 break;
00290 crow++;
00291 ccol = 0;
00292 rowp = dbt_row_new(dtp->nrcols);
00293 if(!rowp)
00294 goto clean;
00295 state = DBT_DATA_ST;
00296
00297 break;
00298
00299 case DBT_DATA_ST:
00300
00301
00302
00303 if(ccol == dtp->nrcols && (c==DBT_DELIM_R || c==EOF))
00304 {
00305 state = DBT_NLINE_ST;
00306 break;
00307 }
00308 if(ccol>= dtp->nrcols)
00309 goto clean;
00310
00311 switch(dtp->colv[ccol]->type)
00312 {
00313 case DB1_INT:
00314 case DB1_DATETIME:
00315
00316 dtval.val.int_val = 0;
00317 dtval.type = dtp->colv[ccol]->type;
00318
00319 if(c==DBT_DELIM ||
00320 (ccol==dtp->nrcols-1
00321 && (c==DBT_DELIM_R || c==EOF)))
00322 dtval.nul = 1;
00323 else
00324 {
00325 dtval.nul = 0;
00326 sign = 1;
00327 if(c=='-')
00328 {
00329 sign = -1;
00330 c = fgetc(fin);
00331 }
00332 if(c<'0' || c>'9')
00333 goto clean;
00334 while(c>='0' && c<='9')
00335 {
00336 dtval.val.int_val=dtval.val.int_val*10+c-'0';
00337 c = fgetc(fin);
00338 }
00339 dtval.val.int_val *= sign;
00340
00341
00342 }
00343 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00344 goto clean;
00345 if(dbt_row_set_val(rowp,&dtval,dtp->colv[ccol]->type,
00346 ccol))
00347 goto clean;
00348 if(ccol == dtp->auto_col)
00349 max_auto = (max_auto<dtval.val.int_val)?
00350 dtval.val.int_val:max_auto;
00351 break;
00352
00353 case DB1_DOUBLE:
00354
00355 dtval.val.double_val = 0.0;
00356 dtval.type = DB1_DOUBLE;
00357
00358 if(c==DBT_DELIM ||
00359 (ccol==dtp->nrcols-1
00360 && (c==DBT_DELIM_R || c==EOF)))
00361 dtval.nul = 1;
00362 else
00363 {
00364 dtval.nul = 0;
00365 sign = 1;
00366 if(c=='-')
00367 {
00368 sign = -1;
00369 c = fgetc(fin);
00370 }
00371 if(c<'0' || c>'9')
00372 goto clean;
00373 while(c>='0' && c<='9')
00374 {
00375 dtval.val.double_val = dtval.val.double_val*10
00376 + c - '0';
00377 c = fgetc(fin);
00378 }
00379 if(c=='.')
00380 {
00381 c = fgetc(fin);
00382 bp = 1;
00383 while(c>='0' && c<='9')
00384 {
00385 bp *= 10;
00386 dtval.val.double_val+=((double)(c-'0'))/bp;
00387 c = fgetc(fin);
00388 }
00389 }
00390 dtval.val.double_val *= sign;
00391
00392
00393 }
00394 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00395 goto clean;
00396 if(dbt_row_set_val(rowp,&dtval,DB1_DOUBLE,ccol))
00397 goto clean;
00398 break;
00399
00400 case DB1_STR:
00401 case DB1_STRING:
00402 case DB1_BLOB:
00403
00404
00405 dtval.val.str_val.s = NULL;
00406 dtval.val.str_val.len = 0;
00407 dtval.type = dtp->colv[ccol]->type;
00408
00409 bp = 0;
00410 if(c==DBT_DELIM ||
00411 (ccol == dtp->nrcols-1
00412 && (c == DBT_DELIM_R || c==EOF)))
00413 dtval.nul = 1;
00414 else
00415 {
00416 dtval.nul = 0;
00417 while(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00418 {
00419 if(c=='\\')
00420 {
00421 c = fgetc(fin);
00422 switch(c)
00423 {
00424 case 'n':
00425 c = '\n';
00426 break;
00427 case 'r':
00428 c = '\r';
00429 break;
00430 case 't':
00431 c = '\t';
00432 break;
00433 case '\\':
00434 c = '\\';
00435 break;
00436 case DBT_DELIM:
00437 c = DBT_DELIM;
00438 break;
00439 case '0':
00440 c = 0;
00441 break;
00442 default:
00443 goto clean;
00444 }
00445 }
00446 buf[bp++] = c;
00447 c = fgetc(fin);
00448 }
00449 dtval.val.str_val.s = buf;
00450 dtval.val.str_val.len = bp;
00451
00453 }
00454 if(c!=DBT_DELIM && c!=DBT_DELIM_R && c!=EOF)
00455 goto clean;
00456 if(dbt_row_set_val(rowp,&dtval,dtp->colv[ccol]->type,
00457 ccol))
00458 goto clean;
00459 break;
00460 default:
00461 goto clean;
00462 }
00463 if(c==DBT_DELIM)
00464 c = fgetc(fin);
00465 ccol++;
00466 break;
00467 }
00468 }
00469
00470 if(max_auto)
00471 dtp->auto_val = max_auto;
00472
00473 done:
00474 if(fin)
00475 fclose(fin);
00476 return dtp;
00477 clean:
00478
00479
00480 LM_DBG("error at row=%d col=%d c=%c\n", crow+1, ccol+1, c);
00481 if(dtp)
00482 dbt_table_free(dtp);
00483 return NULL;
00484 }
00485
00486
00490 int dbt_print_table(dbt_table_p _dtp, str *_dbn)
00491 {
00492 dbt_column_p colp = NULL;
00493 dbt_row_p rowp = NULL;
00494 FILE *fout = NULL;
00495 int ccol;
00496 char *p, path[512];
00497
00498 if(!_dtp || !_dtp->name.s || _dtp->name.len <= 0)
00499 return -1;
00500
00501 if(!_dbn || !_dbn->s || _dbn->len <= 0)
00502 {
00503 fout = stdout;
00504 fprintf(fout, "\n Content of [%.*s::%.*s]\n",
00505 _dtp->dbname.len, _dtp->dbname.s,
00506 _dtp->name.len, _dtp->name.s);
00507 }
00508 else
00509 {
00510 if(_dtp->name.len+_dbn->len > 510)
00511 return -1;
00512 strncpy(path, _dbn->s, _dbn->len);
00513 path[_dbn->len] = '/';
00514 strncpy(path+_dbn->len+1, _dtp->name.s, _dtp->name.len);
00515 path[_dbn->len+_dtp->name.len+1] = 0;
00516 fout = fopen(path, "wt");
00517 if(!fout)
00518 return -1;
00519 }
00520
00521 colp = _dtp->cols;
00522 while(colp)
00523 {
00524 switch(colp->type)
00525 {
00526 case DB1_INT:
00527 fprintf(fout, "%.*s(int", colp->name.len, colp->name.s);
00528 break;
00529 case DB1_DOUBLE:
00530 fprintf(fout, "%.*s(double", colp->name.len, colp->name.s);
00531 break;
00532 case DB1_STR:
00533 fprintf(fout, "%.*s(str", colp->name.len, colp->name.s);
00534 break;
00535 case DB1_STRING:
00536 fprintf(fout, "%.*s(string", colp->name.len, colp->name.s);
00537 break;
00538 case DB1_BLOB:
00539 fprintf(fout, "%.*s(blob", colp->name.len, colp->name.s);
00540 break;
00541 case DB1_DATETIME:
00542 fprintf(fout, "%.*s(time", colp->name.len, colp->name.s);
00543 break;
00544 default:
00545 if(fout!=stdout)
00546 fclose(fout);
00547 return -1;
00548 }
00549
00550 if(colp->flag & DBT_FLAG_NULL)
00551 fprintf(fout,",null");
00552 else if(colp->type==DB1_INT && colp->flag & DBT_FLAG_AUTO)
00553 fprintf(fout,",auto");
00554 fprintf(fout,")");
00555
00556 colp = colp->next;
00557 if(colp)
00558 fprintf(fout,"%c", DBT_DELIM_C);
00559 }
00560 fprintf(fout, "%c", DBT_DELIM_R);
00561 rowp = _dtp->rows;
00562 while(rowp)
00563 {
00564 for(ccol=0; ccol<_dtp->nrcols; ccol++)
00565 {
00566 switch(_dtp->colv[ccol]->type)
00567 {
00568 case DB1_DATETIME:
00569 case DB1_INT:
00570 if(!rowp->fields[ccol].nul)
00571 fprintf(fout,"%d",
00572 rowp->fields[ccol].val.int_val);
00573 break;
00574 case DB1_DOUBLE:
00575 if(!rowp->fields[ccol].nul)
00576 fprintf(fout, "%.2f",
00577 rowp->fields[ccol].val.double_val);
00578 break;
00579 case DB1_STR:
00580 case DB1_STRING:
00581 case DB1_BLOB:
00582 if(!rowp->fields[ccol].nul)
00583 {
00584 p = rowp->fields[ccol].val.str_val.s;
00585 while(p < rowp->fields[ccol].val.str_val.s
00586 + rowp->fields[ccol].val.str_val.len)
00587 {
00588 switch(*p)
00589 {
00590 case '\n':
00591 fprintf(fout, "\\n");
00592 break;
00593 case '\r':
00594 fprintf(fout, "\\r");
00595 break;
00596 case '\t':
00597 fprintf(fout, "\\t");
00598 break;
00599 case '\\':
00600 fprintf(fout, "\\\\");
00601 break;
00602 case DBT_DELIM:
00603 fprintf(fout, "\\%c", DBT_DELIM);
00604 break;
00605 case '\0':
00606 fprintf(fout, "\\0");
00607 break;
00608 default:
00609 fprintf(fout, "%c", *p);
00610 }
00611 p++;
00612 }
00613 }
00614 break;
00615 default:
00616 if(fout!=stdout)
00617 fclose(fout);
00618 return -1;
00619 }
00620 if(ccol<_dtp->nrcols-1)
00621 fprintf(fout, "%c",DBT_DELIM);
00622 }
00623 fprintf(fout, "%c", DBT_DELIM_R);
00624 rowp = rowp->next;
00625 }
00626
00627 if(fout!=stdout)
00628 fclose(fout);
00629
00630 return 0;
00631 }
00632