/[MITgcm]/mitgcm.org/devel/buildweb/pkg/swish-e/src/db_native.c
ViewVC logotype

Annotation of /mitgcm.org/devel/buildweb/pkg/swish-e/src/db_native.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1.1.1 - (hide annotations) (download) (vendor branch)
Fri Sep 20 19:47:29 2002 UTC (22 years, 10 months ago) by adcroft
Branch: Import, MAIN
CVS Tags: baseline, HEAD
Changes since 1.1: +0 -0 lines
File MIME type: text/plain
Importing web-site building process.

1 adcroft 1.1 /*
2     **
3     ** This program and library is free software; you can redistribute it and/or
4     ** modify it under the terms of the GNU (Library) General Public License
5     ** as published by the Free Software Foundation; either version 2
6     ** of the License, or any later version.
7     **
8     ** This program is distributed in the hope that it will be useful,
9     ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10     ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11     ** GNU (Library) General Public License for more details.
12     **
13     ** You should have received a copy of the GNU (Library) General Public License
14     ** along with this program; if not, write to the Free Software
15     ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16     **
17     **
18     **
19     ** 2001-05-07 jmruiz init coding
20     **
21     */
22    
23     #include <time.h>
24     #include "swish.h"
25     #include "mem.h"
26     #include "file.h"
27     #include "error.h"
28     #include "string.h"
29     #include "compress.h"
30     #include "hash.h"
31     #include "db.h"
32     #include "swish_qsort.h"
33     #include "ramdisk.h"
34     #include "db_native.h"
35    
36     #ifdef USE_BTREE
37     #define WRITE_WORDS_RAMDISK 0
38     #else
39     #define WRITE_WORDS_RAMDISK 1
40     #endif
41    
42     // #define DEBUG_PROP 1
43    
44     /*
45     -- init structures for this module
46     */
47    
48     void initModule_DBNative(SWISH * sw)
49     {
50     struct MOD_DB *Db;
51    
52     Db = (struct MOD_DB *) emalloc(sizeof(struct MOD_DB));
53    
54     Db->DB_name = (char *) estrdup("native");
55    
56     Db->DB_Create = DB_Create_Native;
57     Db->DB_Open = DB_Open_Native;
58     Db->DB_Close = DB_Close_Native;
59     Db->DB_Remove = DB_Remove_Native;
60    
61     Db->DB_InitWriteHeader = DB_InitWriteHeader_Native;
62     Db->DB_WriteHeaderData = DB_WriteHeaderData_Native;
63     Db->DB_EndWriteHeader = DB_EndWriteHeader_Native;
64    
65     Db->DB_InitReadHeader = DB_InitReadHeader_Native;
66     Db->DB_ReadHeaderData = DB_ReadHeaderData_Native;
67     Db->DB_EndReadHeader = DB_EndReadHeader_Native;
68    
69     Db->DB_InitWriteWords = DB_InitWriteWords_Native;
70     Db->DB_GetWordID = DB_GetWordID_Native;
71     Db->DB_WriteWord = DB_WriteWord_Native;
72    
73     #ifndef USE_BTREE
74     Db->DB_WriteWordHash = DB_WriteWordHash_Native;
75     #else
76     Db->DB_UpdateWordID = DB_UpdateWordID_Native;
77     Db->DB_DeleteWordData = DB_DeleteWordData_Native;
78     #endif
79    
80     Db->DB_WriteWordData = DB_WriteWordData_Native;
81     Db->DB_EndWriteWords = DB_EndWriteWords_Native;
82    
83     Db->DB_InitReadWords = DB_InitReadWords_Native;
84     Db->DB_ReadWordHash = DB_ReadWordHash_Native;
85     Db->DB_ReadFirstWordInvertedIndex = DB_ReadFirstWordInvertedIndex_Native;
86     Db->DB_ReadNextWordInvertedIndex = DB_ReadNextWordInvertedIndex_Native;
87     Db->DB_ReadWordData = DB_ReadWordData_Native;
88     Db->DB_EndReadWords = DB_EndReadWords_Native;
89    
90     Db->DB_InitWriteFiles = DB_InitWriteFiles_Native;
91     Db->DB_WriteFile = DB_WriteFile_Native;
92     Db->DB_EndWriteFiles = DB_EndWriteFiles_Native;
93    
94     Db->DB_InitReadFiles = DB_InitReadFiles_Native;
95     Db->DB_ReadFile = DB_ReadFile_Native;
96     Db->DB_EndReadFiles = DB_EndReadFiles_Native;
97    
98     Db->DB_InitWriteSortedIndex = DB_InitWriteSortedIndex_Native;
99     Db->DB_WriteSortedIndex = DB_WriteSortedIndex_Native;
100     Db->DB_EndWriteSortedIndex = DB_EndWriteSortedIndex_Native;
101    
102     Db->DB_InitReadSortedIndex = DB_InitReadSortedIndex_Native;
103     Db->DB_ReadSortedIndex = DB_ReadSortedIndex_Native;
104     Db->DB_ReadSortedData = DB_ReadSortedData_Native;
105     Db->DB_EndReadSortedIndex = DB_EndReadSortedIndex_Native;
106    
107     Db->DB_WriteProperty = DB_WriteProperty_Native;
108     Db->DB_WritePropPositions = DB_WritePropPositions_Native;
109     Db->DB_ReadProperty = DB_ReadProperty_Native;
110     Db->DB_ReadPropPositions = DB_ReadPropPositions_Native;
111     Db->DB_Reopen_PropertiesForRead = DB_Reopen_PropertiesForRead_Native;
112    
113     #ifdef USE_BTREE
114     Db->DB_WriteTotalWordsPerFile = DB_WriteTotalWordsPerFile_Native;
115     Db->DB_ReadTotalWordsPerFile = DB_ReadTotalWordsPerFile_Native;
116     #endif
117    
118     sw->Db = Db;
119    
120     return;
121     }
122    
123    
124     /*
125     -- release all wired memory for this module
126     */
127    
128     void freeModule_DBNative(SWISH * sw)
129     {
130     efree(sw->Db->DB_name);
131     efree(sw->Db);
132     sw->Db = NULL;
133     return;
134     }
135    
136    
137    
138     /* ---------------------------------------------- */
139    
140    
141    
142     /*
143     -- Config Directives
144     -- Configuration directives for this Module
145     -- return: 0/1 = none/config applied
146     */
147    
148     int configModule_DBNative(SWISH * sw, StringList * sl)
149     {
150     // struct MOD_DBNative *md = sw->DBNative;
151     // char *w0 = sl->word[0];
152     int retval = 1;
153    
154    
155     retval = 0; // tmp due to empty routine
156    
157     return retval;
158     }
159    
160    
161    
162    
163    
164    
165     /* Does an index file have a readable format?
166     */
167    
168     static void DB_CheckHeader(struct Handle_DBNative *DB)
169     {
170     long swish_magic;
171    
172     fseek(DB->fp, 0, 0);
173     swish_magic = readlong(DB->fp, fread);
174    
175     if (swish_magic != SWISH_MAGIC)
176     {
177     set_progerr(INDEX_FILE_ERROR, DB->sw, "File \"%s\" has an unknown format.", DB->cur_index_file);
178     return;
179     }
180    
181    
182    
183     {
184     long
185     #ifdef USE_BTREE
186     btree,
187     worddata,
188     array,
189     presorted,
190     #endif
191     prop;
192    
193     DB->unique_ID = readlong(DB->fp, fread);
194     prop = readlong(DB->prop, fread);
195    
196     if (DB->unique_ID != prop)
197     {
198     set_progerr(INDEX_FILE_ERROR, DB->sw, "Index file '%s' and property file '%s' are not related.", DB->cur_index_file, DB->cur_prop_file);
199     return;
200     }
201    
202     #ifdef USE_BTREE
203     btree = readlong(DB->fp_btree, fread);
204     if (DB->unique_ID != btree)
205     {
206     set_progerr(INDEX_FILE_ERROR, DB->sw, "Index file '%s' and btree file '%s' are not related.", DB->cur_index_file, DB->cur_btree_file);
207     return;
208     }
209    
210     worddata = readlong(DB->fp_worddata, fread);
211     if (DB->unique_ID != worddata)
212     {
213     set_progerr(INDEX_FILE_ERROR, DB->sw, "Index file '%s' and worddata file '%s' are not related.", DB->cur_index_file, DB->cur_worddata_file);
214     return;
215     }
216    
217     array = readlong(DB->fp_array, fread);
218     if (DB->unique_ID != array)
219     {
220     set_progerr(INDEX_FILE_ERROR, DB->sw, "Index file '%s' and array file '%s' are not related.", DB->cur_index_file, DB->cur_array_file);
221     return;
222     }
223    
224     presorted = readlong(DB->fp_presorted, fread);
225    
226     if (DB->unique_ID != presorted)
227     {
228     set_progerr(INDEX_FILE_ERROR, DB->sw, "Index file '%s' and presorted index file '%s' are not related.", DB->cur_index_file, DB->cur_presorted_file);
229     return;
230     }
231     #endif
232     }
233    
234     }
235    
236     static struct Handle_DBNative *newNativeDBHandle(SWISH *sw, char *dbname)
237     {
238     struct Handle_DBNative *DB;
239    
240     /* Allocate structure */
241     DB = (struct Handle_DBNative *) emalloc(sizeof(struct Handle_DBNative));
242    
243     DB->sw = sw; /* for error messages */
244    
245     DB->offsetstart = 0;
246     #ifndef USE_BTREE
247     DB->hashstart = 0;
248     #endif
249    
250     DB->nextwordoffset = 0;
251     DB->num_words = 0;
252    
253     #ifndef USE_BTREE
254     DB->wordhash_counter = 0;
255     DB->wordhashdata = NULL;
256     #endif
257    
258     DB->worddata_counter = 0;
259     DB->lastsortedindex = 0;
260     DB->next_sortedindex = 0;
261    
262     #ifndef USE_BTREE
263     DB->rd = NULL;
264     #endif
265    
266     DB->tmp_index = 0; /* flags that the index is opened as create as a temporary file name */
267     DB->tmp_prop = 0;
268     DB->cur_index_file = NULL;
269     DB->cur_prop_file = NULL;
270     DB->fp = NULL;
271     DB->prop = NULL;
272    
273     #ifdef USE_BTREE
274     DB->bt = NULL;
275     DB->fp_btree = NULL;
276     DB->tmp_btree = 0;
277     DB->cur_btree_file = NULL;
278    
279     DB->worddata = NULL;
280     DB->fp_worddata = NULL;
281     DB->tmp_worddata = 0;
282     DB->cur_worddata_file = NULL;
283    
284     DB->fp_array = NULL;
285     DB->tmp_array = 0;
286     DB->cur_array_file = NULL;
287    
288     DB->presorted_array = NULL;
289     DB->presorted_root_node = NULL;
290     DB->presorted_propid = NULL;
291     DB->n_presorted_array = 0;
292     DB->tmp_presorted = 0;
293     DB->cur_presorted_file = NULL;
294     DB->fp_presorted = NULL;
295     DB->cur_presorted_array = NULL;
296     DB->cur_presorted_propid = 0;
297     DB->totwords_array = NULL;
298     DB->props_array = NULL;
299     #endif
300    
301    
302     if (WRITE_WORDS_RAMDISK)
303     {
304     DB->w_tell = ramdisk_tell;
305     DB->w_write = ramdisk_write;
306     DB->w_seek = ramdisk_seek;
307     DB->w_read = ramdisk_read;
308     DB->w_close = ramdisk_close;
309     DB->w_putc = ramdisk_putc;
310     DB->w_getc = ramdisk_getc;
311     }
312     else
313     {
314     DB->w_tell = ftell;
315     DB->w_write = fwrite;
316     DB->w_seek = fseek;
317     DB->w_read = fread;
318     DB->w_close = fclose;
319     DB->w_putc = fputc;
320     DB->w_getc = fgetc;
321     }
322    
323     DB->dbname = estrdup(dbname);
324    
325     return DB;
326     }
327    
328    
329     void *DB_Create_Native(SWISH *sw, char *dbname)
330     {
331     int i;
332     long swish_magic;
333     char *filename;
334     #ifdef USE_BTREE
335     FILE *fp_tmp;
336     #endif
337     struct Handle_DBNative *DB;
338    
339     swish_magic = SWISH_MAGIC;
340     /* Allocate structure */
341     DB = (struct Handle_DBNative *) newNativeDBHandle(sw, dbname);
342     DB->mode = DB_CREATE;
343     DB->unique_ID = (long) time(NULL); /* Ok, so if more than one index is created the second... */
344    
345     #ifdef USE_TEMPFILE_EXTENSION
346     filename = emalloc(strlen(dbname) + strlen(USE_TEMPFILE_EXTENSION) + strlen(PROPFILE_EXTENSION) + strlen(BTREE_EXTENSION) + strlen(WORDDATA_EXTENSION) + strlen(ARRAY_EXTENSION) + strlen(PRESORTED_EXTENSION) + 1);
347     strcpy(filename, dbname);
348     strcat(filename, USE_TEMPFILE_EXTENSION);
349     DB->tmp_index = 1;
350     #else
351     filename = emalloc(strlen(dbname) + strlen(PROPFILE_EXTENSION) + +strlen(BTREE_EXTENSION) + strlen(WORDDATA_EXTENSION) + strlen(ARRAY_EXTENSION) + strlen(PRESORTED_EXTENSION) + 1);
352     strcpy(filename, dbname);
353     #endif
354    
355    
356     /* Create index File */
357    
358     CreateEmptyFile(filename);
359     if (!(DB->fp = openIndexFILEForReadAndWrite(filename)))
360     progerrno("Couldn't create the index file \"%s\": ", filename);
361    
362     DB->cur_index_file = estrdup(filename);
363     printlong(DB->fp, swish_magic, fwrite);
364     printlong(DB->fp, DB->unique_ID, fwrite);
365    
366    
367     /* Create property File */
368     strcpy(filename, dbname);
369     strcat(filename, PROPFILE_EXTENSION);
370    
371     #ifdef USE_TEMPFILE_EXTENSION
372     strcat(filename, USE_TEMPFILE_EXTENSION);
373     DB->tmp_prop = 1;
374     #endif
375    
376     CreateEmptyFile(filename);
377     if (!(DB->prop = openIndexFILEForWrite(filename)))
378     progerrno("Couldn't create the property file \"%s\": ", filename);
379    
380     DB->cur_prop_file = estrdup(filename);
381     printlong(DB->prop, DB->unique_ID, fwrite);
382    
383    
384     #ifdef USE_BTREE
385     /* Create Btree File */
386     strcpy(filename, dbname);
387     strcat(filename, BTREE_EXTENSION);
388     #ifdef USE_TEMPFILE_EXTENSION
389     strcat(filename, USE_TEMPFILE_EXTENSION);
390     DB->tmp_btree = 1;
391     #endif
392     CreateEmptyFile(filename);
393     if (!(fp_tmp = openIndexFILEForReadAndWrite(filename)))
394     progerrno("Couldn't create the btree file \"%s\": ", filename);
395     DB->cur_btree_file = estrdup(filename);
396     printlong(fp_tmp, DB->unique_ID, fwrite);
397     DB->fp_btree = fp_tmp;
398     DB->bt=BTREE_Create(DB->fp_btree,4096);
399    
400    
401     /* Create WordData File */
402     strcpy(filename, dbname);
403     strcat(filename, WORDDATA_EXTENSION);
404     #ifdef USE_TEMPFILE_EXTENSION
405     strcat(filename, USE_TEMPFILE_EXTENSION);
406     DB->tmp_worddata = 1;
407     #endif
408     CreateEmptyFile(filename);
409     if (!(fp_tmp = openIndexFILEForReadAndWrite(filename)))
410     progerrno("Couldn't create the worddata file \"%s\": ", filename);
411     printlong(fp_tmp, DB->unique_ID, fwrite);
412     DB->fp_worddata = fp_tmp;
413     DB->cur_worddata_file = estrdup(filename);
414     DB->worddata=WORDDATA_Open(DB->fp_worddata);
415    
416     /* Create Array File */
417     strcpy(filename, dbname);
418     strcat(filename, ARRAY_EXTENSION);
419     #ifdef USE_TEMPFILE_EXTENSION
420     strcat(filename, USE_TEMPFILE_EXTENSION);
421     DB->tmp_array = 1;
422     #endif
423     CreateEmptyFile(filename);
424     if (!(fp_tmp = openIndexFILEForReadAndWrite(filename)))
425     progerrno("Couldn't create the array file \"%s\": ", filename);
426     printlong(fp_tmp, DB->unique_ID, fwrite);
427     DB->cur_array_file = estrdup(filename);
428     DB->fp_array = fp_tmp;
429     DB->totwords_array = ARRAY_Create(DB->fp_array);
430     DB->props_array = ARRAY_Create(DB->fp_array);
431    
432     /* Create PreSorted Index File */
433     strcpy(filename, dbname);
434     strcat(filename, PRESORTED_EXTENSION);
435    
436     #ifdef USE_TEMPFILE_EXTENSION
437     strcat(filename, USE_TEMPFILE_EXTENSION);
438     DB->tmp_presorted = 1;
439     #endif
440    
441     CreateEmptyFile(filename);
442     if (!(DB->fp_presorted = openIndexFILEForWrite(filename)))
443     progerrno("Couldn't create the presorted index file \"%s\": ", filename);
444    
445     DB->cur_presorted_file = estrdup(filename);
446     printlong(DB->fp_presorted, DB->unique_ID, fwrite);
447    
448     #endif
449    
450     efree(filename);
451    
452    
453     for (i = 0; i < MAXCHARS; i++)
454     DB->offsets[i] = 0L;
455    
456     #ifndef USE_BTREE
457     for (i = 0; i < VERYBIGHASHSIZE; i++)
458     DB->hashoffsets[i] = 0L;
459     for (i = 0; i < VERYBIGHASHSIZE; i++)
460     DB->lasthashval[i] = 0L;
461     #endif
462    
463    
464    
465    
466     /* Reserve space for offset pointers */
467     DB->offsetstart = ftell(DB->fp);
468     for (i = 0; i < MAXCHARS; i++)
469     printlong(DB->fp, (long) 0, fwrite);
470    
471     #ifndef USE_BTREE
472     DB->hashstart = ftell(DB->fp);
473     for (i = 0; i < VERYBIGHASHSIZE; i++)
474     printlong(DB->fp, (long) 0, fwrite);
475     #endif
476    
477     return (void *) DB;
478     }
479    
480    
481     /*******************************************************************
482     * DB_Open_Native
483     *
484     *******************************************************************/
485    
486     void *DB_Open_Native(SWISH *sw, char *dbname,int mode)
487     {
488     struct Handle_DBNative *DB;
489     int i;
490     FILE *(*openRoutine)(char *) = NULL;
491     char *s;
492     #ifdef USE_BTREE
493     FILE *fp_tmp;
494     #endif
495    
496     switch(mode)
497     {
498     case DB_READ:
499     openRoutine = openIndexFILEForRead;
500     break;
501     case DB_READWRITE:
502     openRoutine = openIndexFILEForReadAndWrite;
503     break;
504     default:
505     openRoutine = openIndexFILEForRead;
506     }
507    
508     DB = (struct Handle_DBNative *) newNativeDBHandle(sw, dbname);
509     DB->mode = mode;
510    
511     /* Open index File */
512     if (!(DB->fp = openRoutine(dbname)))
513     {
514     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Could not open the index file '%s': ", dbname);
515     return (void *) DB;
516     }
517    
518     DB->cur_index_file = estrdup(dbname);
519    
520     s = emalloc(strlen(dbname) + strlen(PROPFILE_EXTENSION) + 1);
521    
522     strcpy(s, dbname);
523     strcat(s, PROPFILE_EXTENSION);
524    
525     if (!(DB->prop = openRoutine(s)))
526     {
527     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the property file \"%s\": ", s);
528     return (void *) DB;
529     }
530    
531     DB->cur_prop_file = s;
532    
533     #ifdef USE_BTREE
534    
535     s = emalloc(strlen(dbname) + strlen(BTREE_EXTENSION) + 1);
536    
537     strcpy(s, dbname);
538     strcat(s, BTREE_EXTENSION);
539    
540     if (!(fp_tmp = openRoutine(s)))
541     {
542     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the btree file \"%s\": ", s);
543     return (void *) DB;
544     }
545    
546    
547    
548     DB->fp_btree = fp_tmp;
549     DB->cur_btree_file = s;
550    
551     s = emalloc(strlen(dbname) + strlen(PRESORTED_EXTENSION) + 1);
552    
553     strcpy(s, dbname);
554     strcat(s, PRESORTED_EXTENSION);
555    
556     if (!(DB->fp_presorted = openRoutine(s)))
557     {
558     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the presorted index file \"%s\": ", s);
559     return (void *) DB;
560     }
561    
562    
563     DB->cur_presorted_file = s;
564    
565    
566    
567     s = emalloc(strlen(dbname) + strlen(WORDDATA_EXTENSION) + 1);
568    
569     strcpy(s, dbname);
570     strcat(s, WORDDATA_EXTENSION);
571    
572     if (!(fp_tmp = openRoutine(s)))
573     {
574     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the worddata file \"%s\": ", s);
575     return (void *) DB;
576     }
577    
578    
579     DB->fp_worddata = fp_tmp;
580     DB->cur_worddata_file = s;
581    
582     s = emalloc(strlen(dbname) + strlen(ARRAY_EXTENSION) + 1);
583    
584     strcpy(s, dbname);
585     strcat(s, ARRAY_EXTENSION);
586    
587     if (!(fp_tmp = openRoutine(s)))
588     {
589     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the array file \"%s\": ", s);
590     return (void *) DB;
591     }
592    
593     DB->fp_array = fp_tmp;
594     DB->cur_array_file = s;
595    
596     s = emalloc(strlen(dbname) + strlen(PRESORTED_EXTENSION) + 1);
597    
598     strcpy(s, dbname);
599     strcat(s, PRESORTED_EXTENSION);
600    
601     if (!(DB->fp_presorted = openRoutine(s)))
602     {
603     set_progerrno(INDEX_FILE_ERROR, DB->sw, "Couldn't open the presorted index file \"%s\": ", s);
604     return (void *) DB;
605     }
606    
607     DB->cur_presorted_file = s;
608    
609     #endif
610    
611     /* Validate index files */
612     DB_CheckHeader(DB);
613     if ( DB->sw->lasterror )
614     return (void *) DB;
615    
616     /* Read offsets lookuptable */
617     DB->offsetstart = ftell(DB->fp);
618     for (i = 0; i < MAXCHARS; i++)
619     DB->offsets[i] = readlong(DB->fp, fread);
620    
621     #ifndef USE_BTREE
622     /* Read hashoffsets lookuptable */
623     DB->hashstart = ftell(DB->fp);
624     for (i = 0; i < VERYBIGHASHSIZE; i++)
625     DB->hashoffsets[i] = readlong(DB->fp, fread);
626     #else
627     DB->bt = BTREE_Open(DB->fp_btree,4096,DB->offsets[WORDPOS]);
628     DB->worddata = WORDDATA_Open(DB->fp_worddata);
629     DB->totwords_array = ARRAY_Open(DB->fp_array,DB->offsets[TOTALWORDSPERFILEPOS]);
630     DB->props_array = ARRAY_Open(DB->fp_array,DB->offsets[FILEOFFSETPOS]);
631    
632     /* Put the file pointer of props file at the end of the file
633     ** This is very important because if we are in update mode
634     ** we must avoid the properties to be overwritten
635     */
636     fseek(DB->prop,0,SEEK_END);
637     #endif
638    
639     return (void *) DB;
640     }
641    
642     /****************************************************************
643     * This closes a file, and will rename if flagged as such
644     * Frees the associated current file name
645     *
646     *****************************************************************/
647    
648     static void DB_Close_File_Native(FILE ** fp, char **filename, int *tempflag)
649     {
650     if (!*fp)
651     progerr("Called close on non-opened file '%s'", *filename);
652    
653     if (fclose(*fp))
654     progerrno("Failed to close file '%s': ", *filename);
655    
656     *fp = NULL;
657    
658     #ifdef USE_TEMPFILE_EXTENSION
659     if (*tempflag)
660     {
661     char *newname = estrdup(*filename);
662    
663     newname[strlen(newname) - strlen(USE_TEMPFILE_EXTENSION)] = '\0';
664    
665     #if defined(_WIN32) || defined (__VMS)
666     if (isfile(newname))
667     if (remove(newname))
668     progerrno("Failed to unlink '%s' before renaming. : ", newname);
669     #endif
670    
671     if (rename(*filename, newname))
672     progerrno("Failed to rename '%s' to '%s' : ", *filename, newname);
673    
674     *tempflag = 0; /* no longer opened as a temporary file */
675     efree(newname);
676     }
677     #endif
678    
679     efree(*filename);
680     *filename = NULL;
681     }
682    
683    
684    
685    
686     void DB_Close_Native(void *db)
687     {
688     int i;
689     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
690     FILE *fp = DB->fp;
691    
692     /* Close (and rename) property file, if it's open */
693     DB_Close_File_Native(&DB->prop, &DB->cur_prop_file, &DB->tmp_prop);
694    
695     #ifdef USE_BTREE
696     /* Close (and rename) array file, if it's open */
697     if(DB->fp_array)
698     {
699     if(DB->totwords_array)
700     {
701     DB->offsets[TOTALWORDSPERFILEPOS] = ARRAY_Close(DB->totwords_array);
702     DB->totwords_array = NULL;
703     }
704     if(DB->props_array)
705     {
706     DB->offsets[FILEOFFSETPOS] = ARRAY_Close(DB->props_array);
707     DB->props_array = NULL;
708     }
709     DB_Close_File_Native(&DB->fp_array, &DB->cur_array_file, &DB->tmp_array);
710     }
711     /* Close (and rename) worddata file, if it's open */
712     if(DB->worddata)
713     {
714     WORDDATA_Close(DB->worddata);
715     DB_Close_File_Native(&DB->fp_worddata, &DB->cur_worddata_file, &DB->tmp_worddata);
716     DB->worddata = NULL;
717     }
718     /* Close (and rename) btree file, if it's open */
719     if(DB->bt)
720     {
721     DB->offsets[WORDPOS] = BTREE_Close(DB->bt);
722     DB_Close_File_Native(&DB->fp_btree, &DB->cur_btree_file, &DB->tmp_btree);
723     DB->bt = NULL;
724     }
725    
726     /* Close (and rename) presorted index file, if it's open */
727     if(DB->fp_presorted)
728     {
729     DB_Close_File_Native(&DB->fp_presorted, &DB->cur_presorted_file, &DB->tmp_presorted);
730     }
731     if(DB->presorted_array)
732     {
733     for(i = 0; i < DB->n_presorted_array; i++)
734     {
735     if(DB->presorted_array[i])
736     ARRAY_Close(DB->presorted_array[i]);
737     DB->presorted_array[i] = NULL;
738     }
739     efree(DB->presorted_array);
740     }
741     if(DB->presorted_root_node)
742     efree(DB->presorted_root_node);
743     if(DB->presorted_propid)
744     efree(DB->presorted_propid);
745     #endif
746    
747     if (DB->mode == DB_CREATE) /* If we are indexing update offsets to words and files */
748     {
749     /* Update internal pointers */
750    
751     fseek(fp, DB->offsetstart, 0);
752     for (i = 0; i < MAXCHARS; i++)
753     printlong(fp, DB->offsets[i], fwrite);
754    
755     #ifndef USE_BTREE
756     fseek(fp, DB->hashstart, 0);
757     for (i = 0; i < VERYBIGHASHSIZE; i++)
758     printlong(fp, DB->hashoffsets[i], fwrite);
759     #endif
760     }
761    
762     /* Close (and rename) the index file */
763     DB_Close_File_Native(&DB->fp, &DB->cur_index_file, &DB->tmp_index);
764    
765    
766     if (DB->dbname)
767     efree(DB->dbname);
768     efree(DB);
769     }
770    
771     void DB_Remove_Native(void *db)
772     {
773     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
774    
775    
776     /* this is currently not used */
777     /* $$$ remove the prop file too */
778     fclose(DB->fp);
779     remove(DB->dbname);
780     efree(DB->dbname);
781     efree(DB);
782     }
783    
784    
785     /*--------------------------------------------*/
786     /*--------------------------------------------*/
787     /* Header stuff */
788     /*--------------------------------------------*/
789     /*--------------------------------------------*/
790    
791     int DB_InitWriteHeader_Native(void *db)
792     {
793     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
794    
795     if(DB->offsets[HEADERPOS])
796     {
797     /* If DB->offsets[HEADERPOS] is not 0 we are in update mode
798     ** So, put the pointer file in the header start position to overwrite
799     ** the header
800     */
801     fseek(DB->fp,DB->offsets[HEADERPOS],SEEK_SET);
802     }
803     else
804     {
805     /* The index file is being created. So put the header in the
806     ** current file position (coincides with the end of the file
807     */
808     DB->offsets[HEADERPOS] = ftell(DB->fp);
809     }
810     return 0;
811     }
812    
813    
814     int DB_EndWriteHeader_Native(void *db)
815     {
816     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
817     FILE *fp = DB->fp;
818    
819     /* End of header delimiter */
820     fputc(0, fp);
821    
822     return 0;
823     }
824    
825     int DB_WriteHeaderData_Native(int id, unsigned char *s, int len, void *db)
826     {
827     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
828    
829     FILE *fp = DB->fp;
830    
831     compress1(id, fp, fputc);
832     compress1(len, fp, fputc);
833     fwrite(s, len, sizeof(char), fp);
834    
835     return 0;
836     }
837    
838    
839     int DB_InitReadHeader_Native(void *db)
840     {
841     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
842    
843     fseek(DB->fp, DB->offsets[HEADERPOS], 0);
844     return 0;
845     }
846    
847     int DB_ReadHeaderData_Native(int *id, unsigned char **s, int *len, void *db)
848     {
849     int tmp;
850     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
851     FILE *fp = DB->fp;
852    
853     tmp = uncompress1(fp, fgetc);
854     *id = tmp;
855     if (tmp)
856     {
857     tmp = uncompress1(fp, fgetc);
858     *s = (unsigned char *) emalloc(tmp + 1);
859     *len = tmp;
860     fread(*s, *len, sizeof(char), fp);
861     }
862     else
863     {
864     len = 0;
865     *s = NULL;
866     }
867     return 0;
868     }
869    
870     int DB_EndReadHeader_Native(void *db)
871     {
872     return 0;
873     }
874    
875     /*--------------------------------------------*/
876     /*--------------------------------------------*/
877     /* Word Stuff */
878     /*--------------------------------------------*/
879     /*--------------------------------------------*/
880    
881     int DB_InitWriteWords_Native(void *db)
882     {
883    
884     #ifndef USE_BTREE
885     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
886     DB->offsets[WORDPOS] = ftell(DB->fp);
887     #endif
888    
889     return 0;
890     }
891    
892     int cmp_wordhashdata(const void *s1, const void *s2)
893     {
894     int *i = (int *) s1;
895     int *j = (int *) s2;
896    
897     return (*i - *j);
898     }
899    
900     int DB_EndWriteWords_Native(void *db)
901     {
902     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
903     FILE *fp = (FILE *) DB->fp;
904     #ifndef USE_BTREE
905     int i,
906     wordlen;
907     long wordID,
908     f_hash_offset,
909     f_offset,
910     word_pos;
911     #else
912     FILE *fp_tmp;
913     #endif
914    
915     #ifdef USE_BTREE
916    
917     /* If we close the BTREE here we can save some memory bytes */
918     /* Close (and rename) worddata file, if it's open */
919     fp_tmp =DB->worddata->fp;
920     WORDDATA_Close(DB->worddata);
921     DB->worddata=NULL;
922     DB_Close_File_Native(&fp_tmp, &DB->cur_worddata_file, &DB->tmp_worddata);
923    
924     fp_tmp = DB->bt->fp;
925     DB->offsets[WORDPOS] = BTREE_Close(DB->bt);
926     DB->bt = NULL;
927     DB_Close_File_Native(&fp_tmp, &DB->cur_btree_file, &DB->tmp_btree);
928    
929     /* Restore file pointer at the end of file */
930     fseek(DB->fp, 0, SEEK_END);
931     #else
932    
933     /* Free hash zone */
934     Mem_ZoneFree(&DB->hashzone);
935    
936     /* Now update word's data offset into the list of words */
937     /* Simple check words and worddata must match */
938    
939     if (DB->num_words != DB->wordhash_counter)
940     progerrno("Internal DB_native error - DB->num_words != DB->wordhash_counter: ");
941    
942     if (DB->num_words != DB->worddata_counter)
943     progerrno("Internal DB_native error - DB->num_words != DB->worddata_counter: ");
944    
945     /* Sort wordhashdata to be writte to allow sequential writes */
946     swish_qsort(DB->wordhashdata, DB->num_words, 3 * sizeof(long), cmp_wordhashdata);
947    
948     if (WRITE_WORDS_RAMDISK)
949     {
950     fp = (FILE *) DB->rd;
951     }
952     for (i = 0; i < DB->num_words; i++)
953     {
954     wordID = DB->wordhashdata[3 * i];
955     f_hash_offset = DB->wordhashdata[3 * i + 1];
956     f_offset = DB->wordhashdata[3 * i + 2];
957    
958     word_pos = wordID;
959     if (WRITE_WORDS_RAMDISK)
960     {
961     word_pos -= DB->offsets[WORDPOS];
962     }
963     /* Position file pointer in word */
964     DB->w_seek(fp, word_pos, SEEK_SET);
965     /* Jump over word length and word */
966     wordlen = uncompress1(fp, DB->w_getc); /* Get Word length */
967     DB->w_seek(fp, (long) wordlen, SEEK_CUR); /* Jump Word */
968     /* Write offset to next chain */
969     printlong(fp, f_hash_offset, DB->w_write);
970     /* Write offset to word data */
971     printlong(fp, f_offset, DB->w_write);
972     }
973    
974     efree(DB->wordhashdata);
975     DB->wordhashdata = NULL;
976     DB->worddata_counter = 0;
977     DB->wordhash_counter = 0;
978    
979     if (WRITE_WORDS_RAMDISK)
980     {
981     unsigned char buffer[4096];
982     long ramdisk_size;
983     long read = 0;
984    
985     ramdisk_seek((FILE *) DB->rd, 0, SEEK_END);
986     ramdisk_size = ramdisk_tell((FILE *) DB->rd);
987     /* Write ramdisk to fp end free it */
988     fseek((FILE *) DB->fp, DB->offsets[WORDPOS], SEEK_SET);
989     ramdisk_seek((FILE *) DB->rd, 0, SEEK_SET);
990     while (ramdisk_size)
991     {
992     read = ramdisk_read(buffer, 4096, 1, (FILE *) DB->rd);
993     fwrite(buffer, read, 1, DB->fp);
994     ramdisk_size -= read;
995     }
996     ramdisk_close((FILE *) DB->rd);
997     }
998     /* Restore file pointer at the end of file */
999     fseek(DB->fp, 0, SEEK_END);
1000     fputc(0, DB->fp); /* End of words mark */
1001    
1002     #endif
1003    
1004     return 0;
1005     }
1006    
1007     #ifndef USE_BTREE
1008     long DB_GetWordID_Native(void *db)
1009     {
1010     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1011     FILE *fp = DB->fp;
1012     long pos = 0;
1013    
1014     if (WRITE_WORDS_RAMDISK)
1015     {
1016     if (!DB->rd)
1017     {
1018     /* ramdisk size as suggested by Bill Meier */
1019     DB->rd = ramdisk_create("RAM Disk: write words", 32 * 4096);
1020     }
1021     pos = DB->offsets[WORDPOS];
1022     fp = (FILE *) DB->rd;
1023     }
1024     pos += DB->w_tell(fp);
1025    
1026     return pos; /* Native database uses position as a Word ID */
1027     }
1028    
1029     int DB_WriteWord_Native(char *word, long wordID, void *db)
1030     {
1031     int i,
1032     wordlen;
1033     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1034    
1035     FILE *fp = DB->fp;
1036    
1037     i = (int) ((unsigned char) word[0]);
1038    
1039     if (!DB->offsets[i])
1040     DB->offsets[i] = wordID;
1041    
1042    
1043     /* Write word length, word and a NULL offset */
1044     wordlen = strlen(word);
1045    
1046     if (WRITE_WORDS_RAMDISK)
1047     {
1048     fp = (FILE *) DB->rd;
1049     }
1050     compress1(wordlen, fp, DB->w_putc);
1051     DB->w_write(word, wordlen, sizeof(char), fp);
1052    
1053     printlong(fp, (long) 0, DB->w_write); /* hash chain */
1054     printlong(fp, (long) 0, DB->w_write); /* word's data pointer */
1055    
1056     DB->num_words++;
1057    
1058     return 0;
1059     }
1060    
1061     long DB_WriteWordData_Native(long wordID, unsigned char *worddata, int lendata, void *db)
1062     {
1063     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1064     FILE *fp = DB->fp;
1065     struct numhash *numhash;
1066     int numhashval;
1067    
1068     /* We must be at the end of the file */
1069    
1070     if (!DB->worddata_counter)
1071     {
1072     /* We are starting writing worddata */
1073     /* If inside a ramdisk we must preserve its space */
1074     if (WRITE_WORDS_RAMDISK)
1075     {
1076     long ramdisk_size;
1077    
1078     ramdisk_seek((FILE *) DB->rd, 0, SEEK_END);
1079     ramdisk_size = ramdisk_tell((FILE *) DB->rd);
1080     /* Preserve ramdisk size in DB file */
1081     /* it will be write later */
1082     fseek((FILE *) DB->fp, ramdisk_size, SEEK_END);
1083     }
1084     }
1085     /* Search for word's ID */
1086     numhashval = bignumhash(wordID);
1087     for (numhash = DB->hash[numhashval]; numhash; numhash = numhash->next)
1088     if (DB->wordhashdata[3 * numhash->index] == wordID)
1089     break;
1090     if (!numhash)
1091     progerrno("Internal db_native.c error in DB_WriteWordData_Native: ");
1092     DB->wordhashdata[3 * numhash->index + 2] = ftell(fp);
1093    
1094     DB->worddata_counter++;
1095    
1096     /* Write the worddata to disk */
1097     compress1(lendata, fp, fputc);
1098     fwrite(worddata, lendata, 1, fp);
1099    
1100     /* A NULL byte to indicate end of word data */
1101     fputc(0, fp);
1102    
1103     return 0;
1104     }
1105    
1106     #else
1107    
1108     long DB_GetWordID_Native(void *db)
1109     {
1110     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1111    
1112     return DB->worddata->lastid;
1113     }
1114    
1115     int DB_WriteWord_Native(char *word, long wordID, void *db)
1116     {
1117     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1118    
1119     BTREE_Insert(DB->bt, (unsigned char *)word, strlen(word), (unsigned long) wordID);
1120    
1121     DB->num_words++;
1122    
1123     return 0;
1124     }
1125    
1126     int DB_UpdateWordID_Native(char *word, long new_wordID, void *db)
1127     {
1128     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1129    
1130     BTREE_Update(DB->bt, (unsigned char *)word, strlen(word), (unsigned long) new_wordID);
1131    
1132     return 0;
1133     }
1134    
1135     int DB_DeleteWordData_Native(long wordID, void *db)
1136     {
1137     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1138     int dummy;
1139    
1140     WORDDATA_Del(DB->worddata, wordID, &dummy);
1141    
1142     return 0;
1143     }
1144    
1145     long DB_WriteWordData_Native(long wordID, unsigned char *worddata, int lendata, void *db)
1146     {
1147     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1148     DB->worddata_counter++;
1149    
1150     /* Write the worddata to disk */
1151     WORDDATA_Put(DB->worddata,lendata,worddata);
1152    
1153     return 0;
1154     }
1155    
1156     #endif
1157    
1158     #ifndef USE_BTREE
1159     int DB_WriteWordHash_Native(char *word, long wordID, void *db)
1160     {
1161     int i,
1162     hashval,
1163     numhashval;
1164     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1165     struct numhash *numhash;
1166    
1167     if (!DB->wordhash_counter)
1168     {
1169     /* Init hash array */
1170     for (i = 0; i < BIGHASHSIZE; i++)
1171     DB->hash[i] = NULL;
1172     DB->hashzone = Mem_ZoneCreate("WriteWordHash", DB->num_words * sizeof(struct numhash), 0);
1173    
1174     /* If we are here we have finished WriteWord_Native */
1175     /* If using ramdisk - Reserve space upto the size of the ramdisk */
1176     if (WRITE_WORDS_RAMDISK)
1177     {
1178     long ram_size = DB->w_seek((FILE *) DB->rd, 0, SEEK_END);
1179    
1180     fseek(DB->fp, ram_size, SEEK_SET);
1181     }
1182    
1183     DB->wordhashdata = emalloc(3 * DB->num_words * sizeof(long));
1184     }
1185    
1186     hashval = verybighash(word);
1187    
1188     if (!DB->hashoffsets[hashval])
1189     {
1190     DB->hashoffsets[hashval] = wordID;
1191     }
1192    
1193     DB->wordhashdata[3 * DB->wordhash_counter] = wordID;
1194     DB->wordhashdata[3 * DB->wordhash_counter + 1] = (long) 0;
1195    
1196    
1197     /* Add to the hash */
1198     numhash = (struct numhash *) Mem_ZoneAlloc(DB->hashzone, sizeof(struct numhash));
1199    
1200     numhashval = bignumhash(wordID);
1201     numhash->index = DB->wordhash_counter;
1202     numhash->next = DB->hash[numhashval];
1203     DB->hash[numhashval] = numhash;
1204    
1205     DB->wordhash_counter++;
1206    
1207     /* Update previous word in hashlist */
1208     if (DB->lasthashval[hashval])
1209     {
1210     /* Search for DB->lasthashval[hashval] */
1211     numhashval = bignumhash(DB->lasthashval[hashval]);
1212     for (numhash = DB->hash[numhashval]; numhash; numhash = numhash->next)
1213     if (DB->wordhashdata[3 * numhash->index] == DB->lasthashval[hashval])
1214     break;
1215     if (!numhash)
1216     progerrno("Internal db_native.c error in DB_WriteWordHash_Native: ");
1217     DB->wordhashdata[3 * numhash->index + 1] = (long) wordID;
1218     }
1219     DB->lasthashval[hashval] = wordID;
1220    
1221     return 0;
1222     }
1223     #endif
1224    
1225     int DB_InitReadWords_Native(void *db)
1226     {
1227     return 0;
1228     }
1229    
1230     int DB_EndReadWords_Native(void *db)
1231     {
1232     return 0;
1233     }
1234    
1235     #ifndef USE_BTREE
1236     int DB_ReadWordHash_Native(char *word, long *wordID, void *db)
1237     {
1238     int wordlen,
1239     res,
1240     hashval;
1241     long offset,
1242     dataoffset;
1243     char *fileword = NULL;
1244     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1245     FILE *fp = DB->fp;
1246    
1247    
1248     /* If there is not a star use the hash approach ... */
1249     res = 1;
1250    
1251     /* Get hash file offset */
1252     hashval = verybighash(word);
1253     if (!(offset = DB->hashoffsets[hashval]))
1254     {
1255     *wordID = 0;
1256     return 0;
1257     }
1258     /* Search for word */
1259     while (res)
1260     {
1261     /* Position in file */
1262     fseek(fp, offset, SEEK_SET);
1263     /* Get word */
1264     wordlen = uncompress1(fp, fgetc);
1265     fileword = emalloc(wordlen + 1);
1266     fread(fileword, 1, wordlen, fp);
1267     fileword[wordlen] = '\0';
1268     offset = readlong(fp, fread); /* Next hash */
1269     dataoffset = readlong(fp, fread); /* Offset to Word data */
1270    
1271     res = strcmp(word, fileword);
1272     efree(fileword);
1273    
1274     if (!res)
1275     break; /* Found !! */
1276     else if (!offset)
1277     {
1278     dataoffset = 0;
1279     break;
1280     }
1281     }
1282     *wordID = dataoffset;
1283     return 0;
1284     }
1285    
1286     int DB_ReadFirstWordInvertedIndex_Native(char *word, char **resultword, long *wordID, void *db)
1287     {
1288     int wordlen,
1289     i,
1290     res,
1291     len,
1292     found;
1293     long dataoffset = 0;
1294     char *fileword = NULL;
1295     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1296     FILE *fp = DB->fp;
1297    
1298    
1299     len = strlen(word);
1300    
1301     i = (int) ((unsigned char) word[0]);
1302    
1303     if (!DB->offsets[i])
1304     {
1305     *resultword = NULL;
1306     *wordID = 0;
1307     return 0;
1308     }
1309     found = 1;
1310     fseek(fp, DB->offsets[i], 0);
1311    
1312     /* Look for first occurrence */
1313     wordlen = uncompress1(fp, fgetc);
1314     fileword = (char *) emalloc(wordlen + 1);
1315    
1316     while (wordlen)
1317     {
1318     fread(fileword, 1, wordlen, fp);
1319     fileword[wordlen] = '\0';
1320     readlong(fp, fread); /* jump hash offset */
1321     dataoffset = readlong(fp, fread); /* Get offset to word's data */
1322     if (!(res = strncmp(word, fileword, len))) /*Found!! */
1323     {
1324     DB->nextwordoffset = ftell(fp); /* preserve next word pos */
1325     break;
1326     }
1327     if (res < 0)
1328     {
1329     dataoffset = 0;
1330     break;
1331     }
1332     /* Go to next value */
1333     wordlen = uncompress1(fp, fgetc); /* Next word */
1334     if (!wordlen)
1335     {
1336     dataoffset = 0;
1337     break;
1338     }
1339     efree(fileword);
1340     fileword = (char *) emalloc(wordlen + 1);
1341     }
1342     if (!dataoffset)
1343     {
1344     efree(fileword);
1345     *resultword = NULL;
1346     }
1347     else
1348     *resultword = fileword;
1349     *wordID = dataoffset;
1350    
1351     return 0;
1352     }
1353    
1354     int DB_ReadNextWordInvertedIndex_Native(char *word, char **resultword, long *wordID, void *db)
1355     {
1356     int len,
1357     wordlen;
1358     long dataoffset;
1359     char *fileword;
1360     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1361     FILE *fp = DB->fp;
1362    
1363     if (!DB->nextwordoffset)
1364     {
1365     *resultword = NULL;
1366     *wordID = 0;
1367     return 0;
1368     }
1369    
1370     len = strlen(word);
1371    
1372    
1373     fseek(fp, DB->nextwordoffset, SEEK_SET);
1374    
1375     wordlen = uncompress1(fp, fgetc);
1376     fileword = (char *) emalloc(wordlen + 1);
1377    
1378     fread(fileword, 1, wordlen, fp);
1379     fileword[wordlen] = '\0';
1380     if (strncmp(word, fileword, len))
1381     {
1382     efree(fileword);
1383     fileword = NULL;
1384     dataoffset = 0; /* No more data */
1385     DB->nextwordoffset = 0;
1386     }
1387     else
1388     {
1389     readlong(fp, fread); /* jump hash offset */
1390     dataoffset = readlong(fp, fread); /* Get data offset */
1391     DB->nextwordoffset = ftell(fp);
1392     }
1393     *resultword = fileword;
1394     *wordID = dataoffset;
1395    
1396     return 0;
1397    
1398     }
1399    
1400    
1401     long DB_ReadWordData_Native(long wordID, unsigned char **worddata, int *lendata, void *db)
1402     {
1403     int len;
1404     unsigned char *buffer;
1405     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1406     FILE *fp = DB->fp;
1407    
1408     fseek(fp, wordID, 0);
1409     len = uncompress1(fp, fgetc);
1410     buffer = emalloc(len);
1411     fread(buffer, len, 1, fp);
1412    
1413     *worddata = buffer;
1414     *lendata = len;
1415    
1416     return 0;
1417     }
1418    
1419    
1420     #else
1421     int DB_ReadWordHash_Native(char *word, long *wordID, void *db)
1422     {
1423     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1424     unsigned char *dummy;
1425     int dummy2;
1426    
1427     if((*wordID = (long)BTREE_Search(DB->bt,word,strlen(word),&dummy,&dummy2,1)) < 0)
1428     *wordID = 0;
1429     else
1430     efree(dummy);
1431     return 0;
1432     }
1433    
1434     int DB_ReadFirstWordInvertedIndex_Native(char *word, char **resultword, long *wordID, void *db)
1435     {
1436     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1437     unsigned char *found;
1438     int found_len;
1439    
1440    
1441     if((*wordID = (long)BTREE_Search(DB->bt,word,strlen(word), &found, &found_len, 0)) < 0)
1442     {
1443     *resultword = NULL;
1444     *wordID = 0;
1445     }
1446     else
1447     {
1448    
1449     *resultword = emalloc(found_len + 1);
1450     memcpy(*resultword,found,found_len);
1451     (*resultword)[found_len]='\0';
1452     efree(found);
1453     if (strncmp(word, *resultword, strlen(word))>0)
1454     return DB_ReadNextWordInvertedIndex_Native(word, resultword, wordID, db);
1455     }
1456    
1457     return 0;
1458     }
1459    
1460     int DB_ReadNextWordInvertedIndex_Native(char *word, char **resultword, long *wordID, void *db)
1461     {
1462     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1463     unsigned char *found;
1464     int found_len;
1465    
1466     if((*wordID = (long)BTREE_Next(DB->bt, &found, &found_len)) < 0)
1467     {
1468     *resultword = NULL;
1469     *wordID = 0;
1470     }
1471     else
1472     {
1473     *resultword = emalloc(found_len + 1);
1474     memcpy(*resultword,found,found_len);
1475     (*resultword)[found_len]='\0';
1476     efree(found);
1477     if (strncmp(word, *resultword, strlen(word)))
1478     {
1479     efree(*resultword);
1480     *resultword = NULL;
1481     *wordID = 0; /* No more data */
1482     }
1483     }
1484     return 0;
1485     }
1486    
1487     long DB_ReadWordData_Native(long wordID, unsigned char **worddata, int *lendata, void *db)
1488     {
1489     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1490    
1491     *worddata = WORDDATA_Get(DB->worddata,wordID,lendata);
1492    
1493     return 0;
1494     }
1495    
1496     #endif
1497    
1498    
1499     /*--------------------------------------------*/
1500     /*--------------------------------------------*/
1501     /* FileList Stuff */
1502     /*--------------------------------------------*/
1503     /*--------------------------------------------*/
1504    
1505    
1506     int DB_EndWriteFiles_Native(void *db)
1507     {
1508     return 0;
1509     }
1510    
1511     int DB_WriteFile_Native(int filenum, unsigned char *filedata, int sz_filedata, void *db)
1512     {
1513     return 0;
1514     }
1515    
1516     int DB_InitReadFiles_Native(void *db)
1517     {
1518     return 0;
1519     }
1520    
1521     int DB_ReadFile_Native(int filenum, unsigned char **filedata, int *sz_filedata, void *db)
1522     {
1523     return 0;
1524     }
1525    
1526    
1527     int DB_EndReadFiles_Native(void *db)
1528     {
1529    
1530     return 0;
1531     }
1532    
1533    
1534     /*--------------------------------------------*/
1535     /*--------------------------------------------*/
1536     /* Sorted data Stuff */
1537     /*--------------------------------------------*/
1538     /*--------------------------------------------*/
1539    
1540     #ifdef USE_BTREE
1541     int DB_InitWriteSortedIndex_Native(void *db, int n_props)
1542     {
1543     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1544     FILE *fp = DB->fp_presorted;
1545     int i;
1546    
1547     DB->offsets[SORTEDINDEX] = ftell(fp);
1548    
1549     /* Write number of properties */
1550     printlong(fp,(unsigned long) n_props, fwrite);
1551    
1552     DB->n_presorted_array = n_props;
1553     DB->presorted_array = (ARRAY **)emalloc(n_props * sizeof(ARRAY *));
1554     DB->presorted_root_node = (unsigned long *)emalloc(n_props * sizeof(unsigned long));
1555     for(i = 0; i < n_props ; i++)
1556     {
1557     DB->presorted_array[i] = NULL;
1558     DB->presorted_root_node[i] = 0;
1559     /* Reserve space for propidx and Array Pointer */
1560     printlong(fp,(unsigned long) 0, fwrite);
1561     printlong(fp,(unsigned long) 0, fwrite);
1562     }
1563     DB->next_sortedindex = 0;
1564     return 0;
1565     }
1566    
1567     int DB_WriteSortedIndex_Native(int propID, int *data, int n,void *db)
1568     {
1569     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1570     FILE *fp = DB->fp_presorted;
1571     ARRAY *arr;
1572     int i;
1573    
1574     arr = ARRAY_Create(fp);
1575     for(i = 0 ; i < n ; i++)
1576     {
1577     ARRAY_Put(arr,i,data[i]);
1578     /*
1579     if(!(i%10000))
1580     {
1581     ARRAY_FlushCache(arr);
1582     printf("%d %d \r",propID,i);
1583     }
1584     */
1585     }
1586    
1587     DB->presorted_root_node[DB->next_sortedindex] = ARRAY_Close(arr);
1588    
1589     fseek(fp,DB->offsets[SORTEDINDEX] + (1 + 2 * DB->next_sortedindex) *sizeof(unsigned long),SEEK_SET);
1590     printlong(fp,(unsigned long) propID, fwrite);
1591     printlong(fp,(unsigned long) DB->presorted_root_node[DB->next_sortedindex], fwrite);
1592    
1593     DB->next_sortedindex++;
1594    
1595     return 0;
1596     }
1597    
1598     int DB_EndWriteSortedIndex_Native(void *db)
1599     {
1600     return 0;
1601     }
1602    
1603    
1604     int DB_InitReadSortedIndex_Native(void *db)
1605     {
1606     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1607     FILE *fp = DB->fp_presorted;
1608     int i;
1609    
1610     fseek(fp,DB->offsets[SORTEDINDEX],SEEK_SET);
1611    
1612     /* Read number of properties */
1613     DB->n_presorted_array = readlong(fp,fread);
1614    
1615     DB->presorted_array = (ARRAY **)emalloc(DB->n_presorted_array * sizeof(ARRAY *));
1616     DB->presorted_root_node = (unsigned long *)emalloc(DB->n_presorted_array * sizeof(unsigned long));
1617     DB->presorted_propid = (unsigned long *)emalloc(DB->n_presorted_array * sizeof(unsigned long));
1618     for(i = 0; i < DB->n_presorted_array ; i++)
1619     {
1620     DB->presorted_array[i] = NULL;
1621     DB->presorted_propid[i] = readlong(fp,fread);
1622     DB->presorted_root_node[i] = readlong(fp,fread);
1623     }
1624     return 0;
1625    
1626     }
1627    
1628     int DB_ReadSortedIndex_Native(int propID, unsigned char **data, int *sz_data,void *db)
1629     {
1630     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1631     FILE *fp = DB->fp_presorted;
1632     int i;
1633    
1634     if(!DB->cur_presorted_array || DB->cur_presorted_propid != (unsigned long)propID)
1635     {
1636     for(i = 0; i < DB->n_presorted_array ; i++)
1637     {
1638     if((unsigned long)propID == DB->presorted_propid[i])
1639     {
1640     DB->cur_presorted_propid = propID;
1641     DB->cur_presorted_array = DB->presorted_array[i] = ARRAY_Open(fp,DB->presorted_root_node[i]);
1642     break;
1643     }
1644     }
1645     }
1646     if(DB->cur_presorted_array)
1647     {
1648     *data = (unsigned char *)DB->cur_presorted_array;
1649     *sz_data = sizeof(DB->cur_presorted_array);
1650     }
1651     else
1652     {
1653     *data = NULL;
1654     *sz_data = 0;
1655     }
1656    
1657     return 0;
1658     }
1659    
1660    
1661     int DB_ReadSortedData_Native(int *data,int index, int *value, void *db)
1662     {
1663     *value = ARRAY_Get((ARRAY *)data,index);
1664     return 0;
1665     }
1666    
1667     int DB_EndReadSortedIndex_Native(void *db)
1668     {
1669     return 0;
1670     }
1671    
1672     #else
1673     int DB_InitWriteSortedIndex_Native(void *db)
1674     {
1675     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1676    
1677     DB->offsets[SORTEDINDEX] = ftell(DB->fp);
1678     DB->next_sortedindex = DB->offsets[SORTEDINDEX];
1679     return 0;
1680     }
1681    
1682     int DB_WriteSortedIndex_Native(int propID, unsigned char *data, int sz_data,void *db)
1683     {
1684     long tmp1,tmp2;
1685     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1686     FILE *fp = DB->fp;
1687    
1688    
1689     fseek(fp, DB->next_sortedindex, 0);
1690    
1691    
1692     tmp1 = ftell(fp);
1693    
1694     printlong(fp,(long)0,fwrite); /* Pointer to next table if any */
1695    
1696     /* Write ID */
1697     compress1(propID,fp,fputc);
1698    
1699     /* Write len of data */
1700     compress1(sz_data,fp,putc);
1701    
1702     /* Write data */
1703     fwrite(data,sz_data,1,fp);
1704    
1705     DB->next_sortedindex = tmp2 = ftell(fp);
1706    
1707    
1708     if(DB->lastsortedindex)
1709     {
1710     fseek(fp,DB->lastsortedindex,0);
1711     printlong(fp,tmp1,fwrite);
1712     fseek(fp,tmp2,0);
1713     }
1714     DB->lastsortedindex = tmp1;
1715     return 0;
1716     }
1717    
1718     int DB_EndWriteSortedIndex_Native(void *db)
1719     {
1720     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1721     FILE *fp = DB->fp;
1722    
1723     printlong(fp,(long)0,fwrite); /* No next table mark - Useful if no presorted indexes */
1724     /* NULL meta id- Only useful if no presorted indexes */
1725     fputc(0, fp);
1726    
1727     return 0;
1728     }
1729    
1730    
1731     int DB_InitReadSortedIndex_Native(void *db)
1732     {
1733     return 0;
1734     }
1735    
1736     int DB_ReadSortedIndex_Native(int propID, unsigned char **data, int *sz_data,void *db)
1737     {
1738     long next, id, tmp;
1739     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1740     FILE *fp = DB->fp;
1741    
1742     fseek(fp,DB->offsets[SORTEDINDEX],0);
1743    
1744    
1745     next = readlong(fp,fread);
1746     /* read propID */
1747     id = uncompress1(fp,fgetc);
1748    
1749    
1750     while(1)
1751     {
1752     if(id == propID)
1753     {
1754     tmp = uncompress1(fp,fgetc);
1755     *sz_data = tmp;
1756    
1757     *data = emalloc(*sz_data);
1758     fread(*data,*sz_data,1,fp);
1759     return 0;
1760     }
1761     if(next)
1762     {
1763     fseek(fp,next,0);
1764     next = readlong(fp,fread);
1765     id = uncompress1(fp,fgetc);
1766     }
1767     else
1768     {
1769     *sz_data = 0;
1770     *data = NULL;
1771     return 0;
1772     }
1773     }
1774     return 0;
1775     }
1776    
1777     int DB_ReadSortedData_Native(int *data,int index, int *value, void *db)
1778     {
1779     *value = data[index];
1780     return 0;
1781     }
1782    
1783     int DB_EndReadSortedIndex_Native(void *db)
1784     {
1785     return 0;
1786     }
1787    
1788    
1789     #endif
1790    
1791    
1792    
1793    
1794     /*
1795     ** Jose Ruiz 04/00
1796     ** Store a portable long with just four bytes
1797     */
1798     void printlong(FILE * fp, unsigned long num, size_t(*f_write) (const void *, size_t, size_t, FILE *))
1799     {
1800     num = PACKLONG(num); /* Make the number portable */
1801     f_write(&num, MAXLONGLEN, 1, fp);
1802     }
1803    
1804     /*
1805     ** Jose Ruiz 04/00
1806     ** Read a portable long (just four bytes)
1807     */
1808     unsigned long readlong(FILE * fp, size_t(*f_read) (void *, size_t, size_t, FILE *))
1809     {
1810     unsigned long num;
1811    
1812     f_read(&num, MAXLONGLEN, 1, fp);
1813     return UNPACKLONG(num); /* Make the number readable */
1814     }
1815    
1816    
1817    
1818     /****************************************************************************
1819     * Writing Properites (not for USE_BTREE)
1820     *
1821     * Properties are written sequentially to the .prop file.
1822     * Fixed length records of the file length and seek position into the
1823     * property file are written sequentially to the main index (which is why
1824     * there's a separate .prop file).
1825     *
1826     * DB_InitWriteFiles is called first time a property is written
1827     * to save the offset of the property index table in the main index.
1828     * It's simply a ftell() of the current position in the index and that
1829     * seek position is stored in the main index "offsets" table.
1830     *
1831     * DB_WriteProperty writes a property.
1832     *
1833     * DB_WritePropPositions write the seek pointers to the main index and
1834     * *must* be called after processing each file.
1835     * This is all done in WritePropertiesToDisk().
1836     *
1837     * The index tables are all based on the count of properties in the index.
1838     * So, to read you find the start of the prop pointers table by the value
1839     * stored in the offsets table. Since we have a fixed number of properties
1840     * we know the size of an entry in the prop pointers table, one record per filenum.
1841     * Index into the prop seek positions table and grab the pointers to the properties.
1842     *
1843     *
1844     *****************************************************************************/
1845    
1846    
1847     int DB_InitWriteFiles_Native(void *db)
1848     {
1849     #ifndef USE_BTREE
1850     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1851    
1852     DB->offsets[FILELISTPOS] = ftell(DB->fp);
1853    
1854     #ifdef DEBUG_PROP
1855     printf("InitWriteFiles: Start of property table in main index at offset: %ld\n", DB->offsets[FILELISTPOS] );
1856     #endif
1857    
1858     #endif
1859    
1860     return 0;
1861     }
1862    
1863    
1864     /****************************************************************************
1865     * Writes a property to the property file
1866     *
1867     * Creates a PROP_INDEX structure in the file entry that caches all
1868     * the seek pointers into the .prop file, if it doesn't already exist.
1869     *
1870     * Stores in the fi->prop_index structure the seek address of this property and the physical length
1871     *
1872     * Writes to the prop file:
1873     * <uncompressed length><property (possibly compressed)>
1874     *
1875     *
1876     *****************************************************************************/
1877    
1878     void DB_WriteProperty_Native( IndexFILE *indexf, FileRec *fi, int propID, char *buffer, int buf_len, int uncompressed_len, void *db)
1879     {
1880     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1881     size_t written_bytes;
1882     PROP_INDEX *pindex = fi->prop_index;
1883     PROP_LOCATION *prop_loc;
1884     INDEXDATAHEADER *header = &indexf->header;
1885     int count = header->property_count;
1886     int index_size;
1887     int propIDX = header->metaID_to_PropIDX[propID];
1888     #ifdef DEBUG_PROP
1889     long prop_start_pos;
1890     #endif
1891    
1892     if ( count <= 0 )
1893     return;
1894    
1895    
1896     if (!DB->prop)
1897     progerr("Property database file not opened\n");
1898    
1899    
1900     /* Create place to store seek positions and lengths on first call for this file */
1901     if ( !pindex )
1902     {
1903     index_size = sizeof( PROP_INDEX ) + sizeof( PROP_LOCATION ) * (count - 1);
1904     pindex = fi->prop_index = emalloc( index_size );
1905     memset( pindex, 0, index_size );
1906     }
1907    
1908    
1909     /* make an alias */
1910     prop_loc = &pindex->prop_position[ propIDX ];
1911    
1912    
1913    
1914     /* write the property to disk */
1915    
1916     if ((prop_loc->seek = ftell(DB->prop)) == -1)
1917     progerrno("O/S failed to tell me where I am - file number %d metaID %d : ", fi->filenum, propID);
1918    
1919    
1920     /* First write the uncompressed size */
1921     compress1( uncompressed_len+1, DB->prop, putc);
1922    
1923     #ifdef DEBUG_PROP
1924     prop_start_pos = ftell(DB->prop);
1925     #endif
1926    
1927    
1928    
1929     if ((written_bytes = fwrite(buffer, 1, buf_len, DB->prop)) != buf_len) /* Write data */
1930     progerrno("Failed to write file number %d metaID %d to property file. Tried to write %d, wrote %Zu : ", fi->filenum, propID, buf_len,
1931     written_bytes);
1932    
1933     prop_loc->length = buf_len; /* length of this prop */
1934    
1935    
1936     #ifdef DEBUG_PROP
1937     printf("Write Prop: file %d PropIDX %d (meta %d) at file offset %ld (data at %ld) <uncompressed_len> %ld bytes <prop> %Zu bytes\n",
1938     fi->filenum, propIDX, propID, prop_loc->seek, prop_start_pos, prop_start_pos - prop_loc->seek, written_bytes);
1939     #endif
1940     }
1941    
1942    
1943     /****************************************************************************
1944     * Writes out the seek positions for the properties
1945     *
1946     * This writes out a fixed size records, one for each property. Each
1947     * record is a list of <length>:<seek pos> entries, one for
1948     * each property defined. Length is null if this file doesn't have a
1949     * property.
1950     *
1951     * The advantage of the fixed width records is that they can be written
1952     * to disk after each file, saving RAM, and more importanly, all the
1953     * files don't need to be read when searhing. Can just seek to the
1954     * file of interest, read the table, then read the property file.
1955     *
1956     * This comes at a cost of disk space (and maybe disk access speed),
1957     * since much of the data in the table written to disk could be compressed.
1958     *
1959     * An optional approach would be to only save the seek positions, plus
1960     * an extra seek position at the end (the next position after the last
1961     * property. Then could calculate length by comparing the various start
1962     * positions.
1963     *
1964     * For, say, five properties this would save 5 x 4(bytes/int) 20 bytes per
1965     * file. But we need an extra position, so that's 20 - 4 = 16. So, for
1966     * 100,000 files that's only 1.6M of disk space. Probably not worth the trouble.
1967     *
1968     *
1969     *****************************************************************************/
1970     void DB_WritePropPositions_Native(IndexFILE *indexf, FileRec *fi, void *db)
1971     {
1972     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
1973     PROP_INDEX *pindex = fi->prop_index;
1974     INDEXDATAHEADER *header = &indexf->header;
1975     int count = header->property_count;
1976     int index_size;
1977     int i;
1978     #ifdef USE_BTREE
1979     long seek_pos;
1980     #endif
1981    
1982    
1983    
1984     /* Just in case there were no properties for this file */
1985     if ( !pindex )
1986     {
1987     index_size = sizeof( PROP_INDEX ) + sizeof( PROP_LOCATION ) * (count - 1);
1988     pindex = fi->prop_index = emalloc( index_size );
1989     memset( pindex, 0, index_size );
1990     }
1991    
1992     #ifdef USE_BTREE
1993     /* now calculate index */
1994     seek_pos = ((fi->filenum - 1) * count) * 2;
1995     #endif
1996    
1997     #ifdef DEBUG_PROP
1998     printf("Writing seek positions to index for file %d\n", fi->filenum );
1999     #endif
2000    
2001    
2002     /* Write out the prop index */
2003     for ( i = 0; i < count; i++ )
2004     {
2005     /* make an alias */
2006     PROP_LOCATION *prop_loc = &pindex->prop_position[ i ];
2007    
2008     #ifndef USE_BTREE
2009    
2010     #ifdef DEBUG_PROP
2011     printf(" PropIDX: %d length: %ld, seek: %ld main index location: %ld\n",
2012     i, prop_loc->length, prop_loc->seek, ftell( DB->fp ) );
2013     #endif
2014    
2015     /* Write in portable format */
2016     printlong( DB->fp, prop_loc->length, fwrite );
2017     printlong( DB->fp, prop_loc->seek, fwrite );
2018    
2019    
2020     #else
2021     ARRAY_Put( DB->props_array,seek_pos++, prop_loc->length);
2022     ARRAY_Put( DB->props_array,seek_pos++, prop_loc->seek);
2023     #endif
2024     }
2025    
2026     efree( pindex );
2027     fi->prop_index = NULL;;
2028     }
2029    
2030     /****************************************************************************
2031     * Reads in the seek positions for the properties
2032     *
2033     *
2034     *****************************************************************************/
2035     void DB_ReadPropPositions_Native(IndexFILE *indexf, FileRec *fi, void *db)
2036     {
2037     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
2038     PROP_INDEX *pindex = fi->prop_index;
2039     INDEXDATAHEADER *header = &indexf->header;
2040     int count = header->property_count;
2041     int index_size;
2042     long seek_pos;
2043     int i;
2044    
2045     if ( count <= 0 )
2046     return;
2047    
2048    
2049     /* create a place to store them */
2050    
2051     index_size = sizeof( PROP_INDEX ) + sizeof( PROP_LOCATION ) * (count - 1);
2052    
2053     pindex = fi->prop_index = emalloc( index_size );
2054     memset( pindex, 0, index_size );
2055    
2056    
2057     #ifndef USE_BTREE
2058     /* now calculate seek_pos */
2059     // seek_pos = ((fi->filenum - 1) * index_size) + DB->offsets[FILELISTPOS];
2060     // printlong currently always writes 4 bytes, so 8 bytes for length and seek
2061     seek_pos = ((fi->filenum - 1) * 8 * count) + DB->offsets[FILELISTPOS];
2062    
2063    
2064     /* and seek to table */
2065     if (fseek(DB->fp, seek_pos, 0) == -1)
2066     progerrno("Failed to seek to property index located at %ld for file number %d : ", seek_pos, fi->filenum);
2067    
2068    
2069     #ifdef DEBUG_PROP
2070     printf("Fetching seek positions for file %d\n", fi->filenum );
2071     printf(" property index table at %ld, this file at %ld\n", DB->offsets[FILELISTPOS], seek_pos );
2072     #endif
2073    
2074    
2075     /* Read in the prop indexes */
2076     for ( i=0; i < count; i++ )
2077     {
2078     /* make an alias */
2079     PROP_LOCATION *prop_loc = &pindex->prop_position[ i ];
2080    
2081     prop_loc->length = readlong( DB->fp, fread );
2082     prop_loc->seek = readlong( DB->fp, fread );
2083    
2084     #ifdef DEBUG_PROP
2085     printf(" PropIDX: %d Length: %ld Seek: %ld\n", i, prop_loc->length, prop_loc->seek );
2086     #endif
2087    
2088    
2089     }
2090     #else
2091    
2092     /* now calculate index */
2093     seek_pos = ((fi->filenum - 1) * count) * 2;
2094    
2095     /* Read in the prop indexes */
2096     for ( i=0; i < count; i++ )
2097     {
2098     /* make an alias */
2099     PROP_LOCATION *prop_loc = &pindex->prop_position[ i ];
2100    
2101     prop_loc->length = ARRAY_Get(DB->props_array, seek_pos++);
2102     prop_loc->seek = ARRAY_Get(DB->props_array, seek_pos++);
2103     }
2104     #endif
2105     }
2106    
2107    
2108    
2109     /****************************************************************************
2110     * Reads a property from the property file
2111     *
2112     * Returns:
2113     * *char (buffer -- must be destoryed by caller)
2114     *
2115     *****************************************************************************/
2116     char *DB_ReadProperty_Native(IndexFILE *indexf, FileRec *fi, int propID, int *buf_len, int *uncompressed_len, void *db)
2117     {
2118     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
2119     PROP_INDEX *pindex = fi->prop_index;
2120     INDEXDATAHEADER *header = &indexf->header;
2121     int count = header->property_count;
2122     long seek_pos;
2123     int propIDX;
2124     PROP_LOCATION *prop_loc;
2125     char *buffer;
2126     long length;
2127    
2128    
2129     propIDX = header->metaID_to_PropIDX[propID];
2130    
2131     if ( count <= 0 )
2132     return NULL;
2133    
2134    
2135     /* read in the index pointers if not already loaded */
2136     if ( !pindex )
2137     {
2138     DB_ReadPropPositions_Native( indexf, fi, db);
2139     pindex = fi->prop_index;
2140     }
2141    
2142    
2143     if ( !pindex )
2144     progerr("Failed to call DB_ReadProperty_Native with seek positions");
2145    
2146     prop_loc = &pindex->prop_position[ propIDX ];
2147    
2148    
2149    
2150     seek_pos = pindex->prop_position[propIDX].seek;
2151     length = pindex->prop_position[propIDX].length;
2152    
2153     *buf_len = length; /* pass the length back */
2154    
2155    
2156     /* Any for this metaID? */
2157     if (!length )
2158     return NULL;
2159    
2160    
2161    
2162    
2163     if (fseek(DB->prop, seek_pos, 0) == -1)
2164     progerrno("Failed to seek to properties located at %ld for file number %d : ", seek_pos, fi->filenum);
2165    
2166     #ifdef DEBUG_PROP
2167     printf("Fetching filenum: %d propIDX: %d at seek: %ld (length is %ld)\n", fi->filenum, propIDX, seek_pos, length);
2168     #endif
2169    
2170    
2171     /* read uncomprssed size (for use in zlib uncompression) */
2172     *uncompressed_len = uncompress1( DB->prop, fgetc ) - 1;
2173    
2174     #ifdef DEBUG_PROP
2175     printf(" Fetched uncompressed length of %d (%ld bytes storage), now fetching %ld prop bytes from %ld\n",
2176     *uncompressed_len, ftell( DB->prop ) - seek_pos, length, ftell( DB->prop ) );
2177     #endif
2178    
2179    
2180     /* allocate a read buffer */
2181     buffer = emalloc(length);
2182    
2183    
2184     if (fread(buffer, 1, length, DB->prop) != length)
2185     progerrno("Failed to read properties located at %ld for file number %d : ", seek_pos, fi->filenum);
2186    
2187     return buffer;
2188     }
2189    
2190    
2191     /****************************************************************
2192     * This routine closes the property file and reopens it as
2193     * readonly to improve seek times.
2194     * Note: It does not rename the property file.
2195     *****************************************************************/
2196    
2197     void DB_Reopen_PropertiesForRead_Native(void *db)
2198     {
2199     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
2200     int no_rename = 0;
2201     char *s = estrdup(DB->cur_prop_file);
2202    
2203    
2204     /* Close property file */
2205     DB_Close_File_Native(&DB->prop, &DB->cur_prop_file, &no_rename);
2206    
2207    
2208     if (!(DB->prop = openIndexFILEForRead(s)))
2209     progerrno("Couldn't open the property file \"%s\": ", s);
2210    
2211     DB->cur_prop_file = s;
2212     }
2213    
2214    
2215    
2216     #ifdef USE_BTREE
2217    
2218    
2219     int DB_WriteTotalWordsPerFile_Native(SWISH *sw, int idx, int wordcount, void *db)
2220     {
2221     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
2222    
2223     ARRAY_Put(DB->totwords_array,idx,wordcount);
2224    
2225     return 0;
2226     }
2227    
2228    
2229     int DB_ReadTotalWordsPerFile_Native(SWISH *sw, int index, int *value, void *db)
2230     {
2231     struct Handle_DBNative *DB = (struct Handle_DBNative *) db;
2232    
2233     *value = ARRAY_Get((ARRAY *)DB->totwords_array,index);
2234     return 0;
2235     }
2236    
2237    
2238     #endif

  ViewVC Help
Powered by ViewVC 1.1.22