Bookmark BDB and XDXF engine has been cleaned from some bugs.
[mdictionary] / src / bookmarks / bdb / src / berkeleyRead.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <db/db.h>
4 #include <string.h>
5 #include <glib.h>
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/time.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12
13
14
15 typedef unsigned int uint;
16
17 static int bm_compare_key_trans(const DBT *a, const DBT *b) {
18         uint* tmpa = (uint*)(a->data);
19         uint* tmpb = (uint*)(b->data);
20
21         if((*tmpa) == (*tmpb)) return 0;
22         if(*tmpa > *tmpb)  return 1;
23         else               return -1;
24 }
25 //------------------------------------------------------------------------------
26 static int bm_compare_key_words(const DBT *a, const DBT *b) {
27         char* tmpa = g_utf8_casefold((char*)(a->data),-1);
28         char* tmpb = g_utf8_casefold((char*)(b->data),-1);
29         int result = g_utf8_collate(tmpa,tmpb);
30         g_free(tmpa);
31         g_free(tmpb);
32         return result;
33 }
34
35 //------------------------------------------------------------------------------
36 int read_berkeley_in_string_mode(DB* dbp) {
37         DBT key = { NULL , 0 };
38         DBT val = { NULL , 0 };
39
40         int result = dbp->seq(dbp, &key, &val, R_FIRST);
41         uint count = 1;
42         uint a = 0;
43         uint b = 0;
44         uint c = 0;
45         uint i = 0;
46         uint* t = NULL;
47         while(1 != result) {
48                 if(-1 == result) {
49                         printf("---Error! While sequentiall reading database\n");
50                         return 10;
51                 };
52                 memcpy(&a, val.data, sizeof(uint));
53                 t = (uint*)(val.data + sizeof(uint));
54                 printf("%4d. word = %-30s [%-2d record(s)] => \n",count, (char*)(key.data), a);
55
56                 for(i=0; i < a; ++i) {
57                         b = t[i*2];
58                         c = t[i*2 + 1];
59                         printf("\t%4u.%u. ID = %u [hash = %#x]\n",count,i+1,b,c);
60                 }
61                 
62                 result = dbp->seq(dbp, &key, &val, R_NEXT);
63                 ++count;
64         }
65         return 0;
66 }
67 //------------------------------------------------------------------------------
68 int read_berkeley_in_binary_mode(DB* dbp) {
69         DBT key = { NULL , 0 };
70         DBT val = { NULL , 0 };
71
72         uint count = 1;
73         uint a = 0;
74         char* s = NULL;
75         int result = dbp->seq(dbp, &key, &val, R_FIRST);
76         while(1 != result) {
77                 if(-1 == result) {
78                         printf("---Error! While sequentiall reading database\n");
79                         return 10;
80                 };
81                 memcpy(&a, key.data, sizeof(uint));
82                 s = (char*) (val.data);
83                 if(a == 0) {
84                         uint b = 0;
85                         memcpy(&b , val.data, sizeof(uint));
86                         printf("%4u. ID = %-4u value(freeID)=%u\n",count,a,b);
87                 }
88                 else {
89                         printf("%4u. ID = %-4u string=\'%s\'\n",count,a,s);
90                 }
91
92                 result = dbp->seq(dbp, &key, &val, R_NEXT);
93                 ++count;
94         }
95         return 0;
96 }
97 //------------------------------------------------------------------------------
98 int berkeley_del_record(DB* dbp,char mode,char* id) {
99         uint a;
100         DBT key = { NULL , 0 };
101         if('s' == mode) {
102                 printf("Delete key: %s...",id);
103                 key.data = id;
104                 key.size = strlen(id) + 1;
105         }
106         else if('b' == mode) {
107                 if(1 != sscanf(id,"%u",&a)) {
108                         printf("ID has wrong format - it should be unsigned int!\n");
109                         return 25;
110                 };
111                 printf("Deleting record with id=%u\n",a);
112                 key.size = sizeof(uint);
113                 key.data = &a;
114         }
115         else {
116                 printf("not supported mode for delete action!\n");
117                 return 24;
118         };
119
120         int result = dbp->del(dbp,&key,0);
121         if(1 == result) {
122                 printf("... there was no such an element!\n");
123         }
124         else if(-1 == result) {
125                 printf("---Error while deleteing record!\n");
126                 return 29;
127         }
128         else {
129                 printf("... record deleted!\n");
130         }
131
132         return 0;
133 }
134 //------------------------------------------------------------------------------
135 int berkeley_fnd_record(DB* dbp,char mode,char* id) {
136         uint a = 0;
137         DBT key = { NULL , 0 };
138         DBT val = { NULL , 0 };
139         if('s' == mode) {
140                 printf("Searching for key: %s...\n",id);
141                 key.data = id;
142                 key.size = strlen(id) + 1;
143         }
144         else if('b'== mode) {
145                 if(1 != sscanf(id,"%u",&a)) {
146                         printf("ID has wrong format - it should be unsigned int!\n");
147                         return 35;
148                 };
149                 printf("Searching for record with id=%u\n",a);
150                 key.size = sizeof(uint);
151                 key.data = &a;
152         }
153         else {
154                 printf("not supported mode for find action!\n");
155                 return 30;
156         };
157
158         int result = dbp->get(dbp,&key,&val,0);
159         if(1 == result) {
160                 printf("... there was no such a record\n");
161         }
162         else if(-1 == result) {
163                 printf("---Error while searching for the record!\n");
164                 return 29;
165         }
166         else {
167                 uint* t = NULL;
168                 uint b = 0, c = 0, i = 0;
169                 char* s = NULL;
170                 switch(mode) {
171                         case 's':
172 // ------------------------------
173         memcpy(&a, val.data, sizeof(uint));
174         t = (uint*)(val.data + sizeof(uint));
175         printf("Element word = %-30s [%-2d record(s)] => \n", (char*)(key.data), a);
176
177         for(i=0; i < a; ++i) {
178                 b = t[i*2];
179                 c = t[i*2 + 1];
180                 printf("\t%2u. ID = %u [hash = %#xu]\n",i+1,b,c);
181         }
182                         break;
183 // ------------------------------
184                         case 'b':
185 // ------------------------------
186         s = (char*) (val.data);
187         if(a == 0) {
188                 memcpy(&b , val.data, sizeof(uint));
189                 printf("Element ID = %-4u value(freeID)=%u\n",a,b);
190         }
191         else {
192                 printf("Element ID = %-4u string=\'%s\'\n",a,s);
193         }
194                         break;
195 // ------------------------------
196                         default:
197                                 printf("Not supported mode!\n");
198                                 return 30;
199                 }
200         }
201         return 0;
202 }
203 //------------------------------------------------------------------------------
204 int berkeley_fnd_pattern_record(DB* dbp,char mode,char* id) {
205         DBT key = { NULL , 0 };
206         DBT val = { NULL , 0 };
207
208         if('s' == mode) {
209                 int result = dbp->seq(dbp, &key, &val, R_FIRST);
210                 uint count = 1;
211                 uint a = 0;
212                 uint b = 0;
213                 uint c = 0;
214                 uint i = 0;
215                 uint* t = NULL;
216                 char* tmp = g_utf8_casefold(id,-1);
217                 uint len = strlen(tmp);
218         printf("dlugosc: %u\n",len);
219                 char* tmp2 = NULL;
220                 while(1 != result) {
221                         if(-1 == result) {
222                                 printf("---Error! While sequentiall reading database\n");
223                                 return 10;
224                         };
225                         tmp2 = g_utf8_casefold((char*)(key.data),len);
226                         if(0 == g_utf8_collate(tmp2,tmp) || len == 0) {
227                                 memcpy(&a, val.data, sizeof(uint));
228                                 t = (uint*)(val.data + sizeof(uint));
229                                 printf("%4d. word = %-30s [%-2d record(s)] => \n",count, (char*)(key.data), a);
230                 
231                                 for(i=0; i < a; ++i) {
232                                         b = t[i*2];
233                                         c = t[i*2 + 1];
234                                         printf("\t%4u.%u. ID = %u [hash = %#xu]\n",count,i+1,b,c);
235                                 }
236                         }
237                         result = dbp->seq(dbp, &key, &val, R_NEXT);
238                         ++count;
239                 }
240                 free(tmp);
241                 return 0;
242         }
243         else {
244                 printf("Searching for pattern is not supported in binary mode!");
245                 return 65;
246         }
247 }
248 //------------------------------------------------------------------------------
249 int berkeley_del_pattern_record(DB* dbp,char mode,char *id) {
250         DBT key = { NULL , 0 };
251         DBT val = { NULL , 0 };
252
253         if('s' == mode) {
254                 int result = dbp->seq(dbp, &key, &val, R_FIRST);
255                 uint count = 0;
256                 uint a = 0;
257                 uint b = 0;
258                 uint c = 0;
259                 uint i = 0;
260                 uint* t = NULL;
261                 char* tmp = g_utf8_casefold(id,-1);
262                 uint len = strlen(tmp);
263                 char* tmp2 = NULL;
264                 while(1 != result) {
265                         if(-1 == result) {
266                                 printf("---Error! While sequentiall reading database\n");
267                                 return 10;
268                         };
269                         tmp2 = g_utf8_casefold((char*)(key.data),len);
270                         if(0 == g_utf8_collate(tmp2,tmp) || len == 0) {
271                                 // delete actual record
272
273                                 memcpy(&a, val.data, sizeof(uint));
274                                 t = (uint*)(val.data + sizeof(uint));
275                                 printf("Deleting record %4d. word = %-30s [%-2d record(s)] => \n",count, (char*)(key.data), a);
276                 
277                                 for(i=0; i < a; ++i) {
278                                         b = t[i*2];
279                                         c = t[i*2 + 1];
280                                         printf("\t%4u.%u. ID = %u [hash = %#xu]\n",count,i+1,b,c);
281                                 }
282                                 int result = dbp->del(dbp,&key,0);
283                                 if(1 == result) {
284                                         printf("---Error find element but could not delete it!\n");
285                                 }
286                                 else if(-1 == result) {
287                                         printf("---Error while deleteing record!\n");
288                                         return 29;
289                                 }
290                                 else {
291                                         printf("... record deleted!\n");
292                                 }
293                                 count++;
294                         }
295                         free(tmp2); tmp2 = NULL;
296                         result = dbp->seq(dbp, &key, &val, R_NEXT);
297                 }
298                 printf("%u record were deleted totaly.\n",count);
299                 free(tmp);
300                 return 0;
301         }
302         else {
303                 printf("Searching for pattern is not supported in binary mode!");
304                 return 65;
305         }
306 }
307 //------------------------------------------------------------------------------
308 int berkeley_add_record(DB* dbp,char mode,char* id, char* value) {
309         DBT key = { NULL , 0 };
310         DBT val = { NULL , 0 };
311         
312         int result = 0;
313         uint a = 0, i = 0, error = 0, b = 0, c = 0;
314         uint* t = NULL;
315         char* tmp = malloc(200);
316         char* tmp_original = tmp;
317         if('s' == mode) {
318                 printf("Adding record with key = %s...\n",id);
319                 key.data = id;
320                 key.size = strlen(id) + 1;
321                 while(1) {
322                 if(2 != sscanf(value,"%u%[ 0-9]",&a,tmp)) {
323                         result = 43;
324                         break;
325                 }
326                 val.size = sizeof(uint) * (a*2 + 1);
327                 t = (uint*)malloc( val.size );
328                 t[0] = a;
329                 for(i=0; i< a; ++i) {
330                         if(2 != sscanf(tmp,"%u%[ 0-9]",&b,tmp)) {
331                                 error = 1;
332                                 break;
333                         };
334                         t[1+i*2] = b;
335                         int n = sscanf(tmp,"%u%[ 0-9]",&b,tmp);
336                         if(( (2 != n) && (i!=(a-1)) ) || ((1!=n) && (i==(a-1)))) {
337                                 error = 1;
338                                 break;
339                         };
340                         t[1+i*2+1] = b;
341                 }
342                 if(error) {
343                         printf("Wrong value for string database!\n");
344                         result = 44;
345                         break;
346                 }
347                 val.data = t;
348                 break ;}
349         }
350         else if('b'== mode) {
351                 if(1 != sscanf(id,"%u",&a)) {
352                         printf("ID has wrong format - it should be unsigned int!\n");
353                         return 45;
354                 };
355                 printf("Adding record with id=%u\n",a);
356                 key.size = sizeof(uint);
357                 key.data = &a;
358                 if(0 == a) {
359                         if(1 != sscanf(value,"%u",&c)) {
360                                 printf("Value has wrong format for record with ID=0 (freeID - unsinged int)\n");
361                                 return 46;
362                         };      
363                         val.size = key.size;
364                         val.data = &c;
365                 }
366                 else {
367                         val.size = strlen(value) + 1;
368                         val.data = value;
369                 }
370         }
371         else {
372                 printf("---Not supported mode for add action!\n");
373                 return 40;
374         };
375         
376         if(0 != result) {
377                 if(t) free(t);
378                 free(tmp_original);
379                 return result;
380         }
381         
382         result = dbp->put(dbp, &key, &val, R_NOOVERWRITE);
383         if(1 == result) {
384                 printf("Such a key already exist in database!\n");
385                 result = 41;
386         }
387         else if(-1 == result) {
388                 printf("---Error while adding new record!\n");
389                 result =  49;
390         }
391         else {
392                 printf("New record has been added.\n");
393                 if(-1 == dbp->sync(dbp, 0)) {
394                         printf("---Error while saving data to file! Record could be lost.\n");
395                         result = 48;
396                 }
397         }
398         if(t) free(t);
399         return result;
400 }
401 //------------------------------------------------------------------------------
402 int main(int argc, char* argv[]) {
403         int help = 0, i = 0;
404         for(i=1;i<argc;++i) {
405                 if((0 == strcmp("help",argv[i])) ||
406                    (0 == strcmp("--help",argv[i])) ||
407                    (0 == strcmp("-help",argv[i])) ||
408                    (0 == strcmp("-h",argv[i])) ||
409                    (0 == strcmp("/h",argv[i])) ||
410                    (0 == strcmp("/help",argv[i]))) {
411                         help = 1;
412                         break;
413                 }
414         }
415         if((argc < 3) || help) {
416                 printf("[Usage: bdbprint s|b file_name.db (action identifier_of_record (optional_value))]\n"
417                        "\tfile_name.db - database to open and print\n"
418                        "\t           s - open in string mode, every key is treated as a string\n"
419                        "\t           b - open in binary mode, every key is treated as a unsigned integer\n"
420                        "\t      action - optional action to do on the base\n"
421                        "\t\t       del - delete record with key=identifier_of_record\n"
422                        "\t\t       add - add new record with key=identifier_of_record\n"
423                        "\t\t       fnd - find record with key=identifier_of_record\n"
424                        "\t\t\t    optional_value - value for add action\n");
425                 return 100;
426         };
427
428         char* filename = argv[2];
429         char* _mode = argv[1];
430         if((strlen(_mode) > 1) || ( ('s' != _mode[0]) && ('b' != _mode[0]) )) {
431                 printf("Wrong mode! Mode could be only s or b [\'s\' , \'b\']!\n");
432                 return 2;
433         }
434         char mode = _mode[0];
435
436         BTREEINFO info = {
437           0,                    /* permit duplicate keys? */
438           0,                    /* cache size; 0 - default size */
439           0,                    /* page size; 0 - default */
440           0,                    /* byte order; 0 - use host order */
441           0,                    /* min page number per page; 0 - default=2 */
442           bm_compare_key_words, /* comparision function */
443           NULL                  /* prefix comparision function */
444         };
445         if('b' == mode) {
446                 info.compare = bm_compare_key_trans;
447         }
448         u_int32_t flags = O_CREAT | O_RDWR;
449         DB *dbp = dbopen(filename, flags, 0755, DB_BTREE, &info);
450         if(NULL == dbp) {
451                 printf("Could not open database: %s!\n",filename);
452                 return 1;
453         };
454
455         int result = 0;
456         if(argc == 3) {
457                 printf("Printing database: \'%s\' in mode %s :\n", filename, _mode);
458                 if('s' == mode) {
459                         result = read_berkeley_in_string_mode(dbp);
460                 }
461                 else if('b' == mode) {
462                         result = read_berkeley_in_binary_mode(dbp);
463                 }
464         }
465         else if(argc > 3) {
466                 printf("Do not print - only action... [mode=%s]\n",_mode);
467                 if(argc < 5) {
468                         printf("Wrong number of parameters! probably You did not give id of record for action.\n");
469                         return 21;
470                 };
471                 char* action = argv[3];
472                 if(strcmp(action,"del") == 0) {
473                         if('*' == argv[4][0]) {
474                                 result = berkeley_del_pattern_record(dbp,mode,&(argv[4][1]));
475                         }
476                         else {
477                                 result = berkeley_del_record(dbp,mode,argv[4]);
478                         }
479                 }
480                 else if(strcmp(action,"fnd") == 0) {
481                         if('*' == argv[4][0]) {
482                                 result = berkeley_fnd_pattern_record(dbp,mode,argv[4]+1);
483                         }
484                         else {
485                                 result = berkeley_fnd_record(dbp,mode,argv[4]);
486                         }
487                 }
488                 else if(strcmp(action,"add") == 0) {
489                         if(argc < 6) {
490                                 printf("You did not give value for new record!\n");
491                                 return 22;
492                         };
493                         result = berkeley_add_record(dbp,mode,argv[4],argv[5]);
494                 }
495                 else {
496                         printf("Not supported action: %s! The only good values are: add, del, fnd.\n",action);
497                         result = 20;
498                 }
499         }
500
501         dbp->close(dbp);
502         return result;
503 }
504 //------------------------------------------------------------------------------