source: tags/ms_r16q2/ARBDB/admap.cxx

Last change on this file was 14006, checked in by westram, 9 years ago
  • partial merge from 'alilink' into 'trunk'
    • adds GB_remove_hierarchy_callback
    • adds new flavor of GB_add_hierarchy_callback (allows to install path before it exists)
    • several refactoring in callback code
  • adds:
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : admap.cxx                                         //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "gb_key.h"
12#include "gb_map.h"
13#include "gb_index.h"
14#include <arb_file.h>
15
16#define ADMAP_BYTE_ORDER    0x01020304
17#define GB_MAX_MAPPED_FILES 10
18
19#ifdef DIGITAL
20#   define ALIGN_BITS 3
21#else
22#   define ALIGN_BITS 2                             // if ALIGN_BITS == 3 we get problems when writing pointer-arrays
23#endif
24
25#define ALIGN(size)     (((((size)-1)>>ALIGN_BITS)+1)<<ALIGN_BITS)
26#define PTR_DIFF(p1, p2) ((char*)(p1)-(char*)(p2))
27
28struct gbdata_offset
29{
30    GBDATA *gbd;
31    long    index;                                  // new index
32    long    offset;                                 // offset in mapfile (initialized with -1)
33};
34
35struct gbdByKey {                                   // one for each diff. keyQuark
36    int            cnt;
37    gbdata_offset *gbdoff;
38};
39
40static gbdByKey *gb_gbk = NULL;
41
42
43inline long MAKEREL(long rel_to, long offset) {
44    gb_assert(rel_to);
45    return offset ? offset-rel_to : 0;
46}
47
48// ---------------------------
49//      sort and binsearch
50
51#define cmp(h1, h2) ((long)(h1).gbd - (long)(h2).gbd)
52
53#define swap(h1, h2)                        \
54    do {                                    \
55        gbdata_offset xxx = (h1);           \
56        (h1) = (h2);                        \
57        (h2) = xxx;                         \
58    } while (0)
59
60static void downheap(gbdata_offset *heap, int idx, int num)
61{
62    int idx2  = idx<<1;
63    int idx21 = idx2+1;
64    gb_assert(idx>=1);
65
66    if (idx2>num)
67        return;                     // no lson -> done
68
69    if (cmp(heap[idx2], heap[idx])>0)           // lson is bigger than actual
70    {
71        if (idx21 <= num &&             // rson exists
72            cmp(heap[idx2], heap[idx21])<0) // lson is smaller than rson
73        {
74            swap(heap[idx], heap[idx21]);
75            downheap(heap, idx21, num);
76        }
77        else
78        {
79            swap(heap[idx], heap[idx2]);
80            downheap(heap, idx2, num);
81        }
82    } else if (idx21 <= num &&              // rson exists
83              cmp(heap[idx], heap[idx21])<0)        // rson is bigger than actual
84    {
85        swap(heap[idx], heap[idx21]);
86        downheap(heap, idx21, num);
87    }
88}
89
90static void sort_gbdata_offsets(gbdata_offset *gbdo, int num)
91{
92    int i;
93    gbdata_offset *heap = gbdo-1;
94#if defined(DEBUG)
95    int onum = num;
96#endif // DEBUG
97
98    gb_assert(gbdo!=NULL);
99    gb_assert(num>=1);
100
101    for (i=num/2; i>=1; i--)
102        downheap(heap, i, num); // make heap
103
104    while (num>1)   // sort heap
105    {
106        gbdata_offset big = heap[1];
107
108        heap[1] = heap[num];
109        downheap(heap, 1, num-1);
110        heap[num] = big;
111        num--;
112    }
113
114#ifdef DEBUG
115    for (i=1; i<onum; i++) { // test if sorted
116        gb_assert(cmp(heap[i], heap[i+1])<0);
117    }
118#endif
119}
120
121static gbdata_offset *find_gbdata_offset(GBQUARK quark, GBDATA *gbd) {
122    gbdata_offset *gbdo = gb_gbk[quark].gbdoff;
123    long l=0,
124        h=gb_gbk[quark].cnt-1,
125        m;
126
127    gb_assert(h>=l);
128    gb_assert(gbdo!=NULL);
129
130    while (1) {
131        long cmpres;
132
133        m = (l+h)>>1;
134        cmpres = (long)gbd - (long)gbdo[m].gbd;
135
136        if (cmpres == 0) {  // equal m
137            return &gbdo[m];
138        }
139        else {
140            if (l==h) break;
141            if (cmpres < 0) h = m;
142            else        l = m+1;
143        }
144    }
145
146    printf("not found(1): gbd=%lx\n", (long)gbd);
147    gb_assert(0);   // should never occur
148    return 0;
149}
150
151static long getrel_GBDATA(long rel_to, GBDATA *gbd) {
152    // calcs offset of 'gbd' in mapfile _relative_ to offset 'rel_to'
153
154    if (gbd) {
155        GBQUARK quark = gbd->rel_father ? GB_KEY_QUARK(gbd) : 0; // cause Main->data->father==NULL !!
156        gbdata_offset *gbdo = gb_gbk[quark].gbdoff;
157        int l=0,
158            h=gb_gbk[quark].cnt-1,
159            m;
160
161        gb_assert(h>=l);
162        gb_assert(gbdo!=NULL);
163
164        while (1)
165        {
166            long cmpres;
167
168            m = (l+h)>>1;
169            cmpres = (long)gbd - (long)gbdo[m].gbd;
170
171            if (cmpres == 0) {  // equal m
172                return MAKEREL(rel_to, gbdo[m].offset);
173            }
174            else {
175                if (l==h) break;
176
177                if (cmpres < 0) h = m;
178                else        l = m+1;
179            }
180        }
181
182        printf("not found(2): gbd=%lx\n", (long)gbd);
183        gb_assert(0);   // should never occur
184    }
185
186    return 0;
187}
188
189#undef cmp
190#undef swap
191
192/* ********************************************************
193   write - routines
194   ******************************************************** */
195
196static bool writeError;
197
198static void ftwrite_aligned(const void *ptr, size_t ali_siz, FILE *fil) {
199    gb_assert(ali_siz == ALIGN(ali_siz));
200    if (!writeError && fwrite((const char *)ptr, 1, ali_siz, fil) != ali_siz) {
201        writeError = true;
202    }
203}
204
205static char alignment_bytes[ALIGN(1)] = { 0 }; // zero-filled buffer with maximum alignment size
206
207static size_t ftwrite_unaligned(const void *ptr, size_t unali_siz, FILE *fil) {
208    // ftwrite_unaligned does the same as ftwrite_aligned,
209    // but does not access uninitialized memory (that's better for valgrind)
210
211    if (!writeError) {
212        size_t ali_siz   = ALIGN(unali_siz);
213        size_t pad_bytes = ali_siz-unali_siz;
214
215        if (fwrite((const char*)(ptr), 1, unali_siz, fil) == unali_siz) {
216            if (pad_bytes == 0 || fwrite(alignment_bytes, 1, pad_bytes, fil) == pad_bytes) {
217                return ali_siz; // success -> return size written
218            }
219        }
220    }
221    return 0; // failure
222}
223
224static long write_IE(gb_if_entries *ie, FILE *out, long *offset) {
225    // parameters mean the same as in write_GBDATA
226    long ieoffset = ie ? *offset : 0;
227
228    while (ie)
229    {
230        gb_if_entries copy;
231        size_t        copy_size;
232
233        if (out) {
234            copy.rel_ie_gbd = (GB_REL_GBDATA) getrel_GBDATA(*offset, GB_IF_ENTRIES_GBD(ie));
235            copy.rel_ie_next = (GB_REL_IFES)(ie->rel_ie_next ? ALIGN(sizeof(copy)) : 0);
236
237            copy_size = ftwrite_unaligned(&copy, sizeof(copy), out);
238        }
239        else {
240            copy_size = ALIGN(sizeof(copy));
241        }
242
243        *offset += copy_size;
244        ie = GB_IF_ENTRIES_NEXT(ie);
245    }
246
247    return ieoffset;
248}
249
250static long write_IFS(gb_index_files *ifs, FILE *out, long *offset) {
251    // parameters mean the same as in write_GBDATA
252    long    ifsoffset,
253        nextoffset,
254        entriesoffset;
255
256    if (!ifs) return 0;
257
258    nextoffset = write_IFS(GB_INDEX_FILES_NEXT(ifs), out, offset);
259
260    // entries
261
262    {
263        GB_REL_IFES *ie     = GB_INDEX_FILES_ENTRIES(ifs);
264        GB_REL_IFES *iecopy;
265        size_t       iesize = ALIGN((size_t)(ifs->hash_table_size)*sizeof(*ie));
266        int          idx;
267
268        STATIC_ASSERT(ALIGN(sizeof(*ie))==sizeof(*ie));
269
270        iecopy = (GB_REL_IFES *)malloc(iesize);
271        memcpy(iecopy, ie, iesize);
272
273        // write index entries an calc absolute offsets
274
275        for (idx=0; idx<ifs->hash_table_size; idx++) {
276            iecopy[idx] = (GB_REL_IFES) write_IE(GB_ENTRIES_ENTRY(ie, idx), out, offset);
277        }
278
279        // convert to relative offsets and write them
280
281        entriesoffset = *offset;
282        for (idx=0; idx<ifs->hash_table_size; idx++) {
283            iecopy[idx] = (GB_REL_IFES)MAKEREL(entriesoffset, (long)iecopy[idx]);
284        }
285
286        if (out) ftwrite_aligned(iecopy, iesize, out);
287        *offset += iesize;
288
289        free(iecopy);
290    }
291
292    // ifs
293
294    {
295        gb_index_files ifscopy = *ifs;
296        size_t         ifscopy_size;
297
298        ifsoffset = *offset;
299
300        ifscopy.rel_if_next = (GB_REL_IFS)MAKEREL(ifsoffset, nextoffset);
301        ifscopy.rel_entries = (GB_REL_PIFES)MAKEREL(ifsoffset, entriesoffset);
302
303        if (out) ifscopy_size = ftwrite_unaligned(&ifscopy, sizeof(ifscopy), out);
304        else     ifscopy_size = ALIGN(sizeof(ifscopy));
305
306        *offset += ifscopy_size;
307    }
308
309    return ifsoffset;
310}
311
312static void convertFlags4Save(gb_flag_types *flags, gb_flag_types2 *flags2, gb_flag_types3 */*flags3*/) {
313    flags->unused      = 0;
314    flags->user_flags  = 0;
315    gb_assert(flags->temporary==0);
316    flags->saved_flags = 0;
317
318    flags2->last_updated     = 0;
319    flags2->user_bits        = 0;
320    flags2->folded_container = 0;
321    flags2->update_in_server = 0;
322    flags2->header_changed   = 0;
323}
324static long write_GBDATA(GB_MAIN_TYPE */*Main*/, GBDATA *gbd, GBQUARK quark, FILE *out, long *offset, GB_MAIN_IDX main_idx) {
325    /*
326      if out==NULL -> only calculate size
327
328       changes     'offset' according to size of written data
329       returns     offset of GBDATA in mapfile
330     */
331    long gbdoffset;
332
333    gb_assert(gbd->flags.temporary==0);
334
335    if (gbd->is_container()) {
336        GBCONTAINER *gbc     = gbd->as_container();
337        GBCONTAINER  gbccopy = *gbc;
338
339        long headeroffset;
340        long ifsoffset;
341
342        // header
343
344        {
345            gb_header_list *header        = GB_DATA_LIST_HEADER(gbc->d);
346            long            headermemsize = ALIGN(gbc->d.headermemsize*sizeof(*header));
347            int             nitems        = gbc->d.nheader;
348
349            headeroffset = *offset;
350
351            gb_assert(PTR_DIFF(&(header[1]), &(header[0])) == sizeof(*header)); // @@@@
352
353            if (headermemsize) {     // if container is non-empty
354                if (out) {
355                    int             valid      = 0; // no of non-temporary items
356                    gb_header_list *headercopy = (gb_header_list*) malloc(headermemsize);
357
358                    STATIC_ASSERT(sizeof(*headercopy) == ALIGN(sizeof(*headercopy)));
359                    memset(headercopy, 0x0, headermemsize);
360
361                    for (int item = 0; item<nitems; item++) {
362                        GBDATA *gbd2 = GB_HEADER_LIST_GBD(header[item]);
363                        long hs_offset;
364
365                        if (!gbd2 || gbd2->flags.temporary) continue;
366
367                        hs_offset = headeroffset + PTR_DIFF(&(headercopy[valid]), &(headercopy[0]));
368
369                        headercopy[valid].flags = header[item].flags;
370                        headercopy[valid].flags.flags &= 1;
371                        headercopy[valid].flags.changed = 0;
372                        headercopy[valid].flags.ever_changed = 0;
373                        headercopy[valid].rel_hl_gbd = (GB_REL_GBDATA)getrel_GBDATA(hs_offset, gbd2);
374
375                        /* printf("header[%i->%i].rel_hl_gbd = %li\n", item,valid,
376                           headercopy[valid].rel_hl_gbd); */
377
378                        gb_assert(headercopy[valid].rel_hl_gbd != 0);
379                        valid++;
380                    }
381
382
383                    gbccopy.d.size          = gbccopy.d.nheader = valid;
384                    gbccopy.d.headermemsize = valid;
385
386                    headermemsize = ALIGN(valid * sizeof(*header));
387                    ftwrite_aligned(headercopy, headermemsize, out);
388                    free(headercopy);
389
390                }
391                else {                              // Calc new indices and size of header
392                    int valid = 0;                  // no of non-temporary items
393                    for (int item = 0; item<nitems; item++) {
394                        GBDATA *gbd2 = GB_HEADER_LIST_GBD(header[item]);
395                        gbdata_offset *dof;
396                        if (!gbd2 || gbd2->flags.temporary) continue;
397                        dof = find_gbdata_offset(header[item].flags.key_quark, gbd2);
398                        dof->index = valid;
399                        valid++;
400                    }
401                    gb_assert((size_t)headermemsize >= valid * sizeof(*header));
402                    headermemsize = ALIGN(valid * sizeof(*header));
403                }
404            }
405            else {
406                gb_assert(header==0);
407                headeroffset=0;
408            }
409
410            *offset += headermemsize;
411        }
412
413        // ifs
414
415        ifsoffset = write_IFS(GBCONTAINER_IFS(gbc), out, offset);
416
417        // gbc
418
419        gbdoffset = *offset;
420        {
421            size_t gbccopy_size;
422            if (out) {
423                gbdata_offset *dof = find_gbdata_offset(quark, gbc);
424                gbccopy.index = dof->index;
425                gb_assert(dof->index <= gbc->index); // very simple check
426
427                gbccopy.rel_father = (GB_REL_CONTAINER)getrel_GBDATA(gbdoffset, GB_FATHER(gbc));
428
429                gbccopy.ext = NULL;
430                convertFlags4Save(&(gbccopy.flags), &(gbccopy.flags2), &(gbccopy.flags3));
431                gbccopy.d.rel_header = (GB_REL_HLS)MAKEREL(gbdoffset+PTR_DIFF(&(gbc->d), gbc), headeroffset);
432                // rel_header is relative to gbc->d !!!
433                gbccopy.main_idx = main_idx;
434                gbccopy.index_of_touched_one_son = 0;
435                gbccopy.header_update_date = 0;
436                gbccopy.rel_ifs = (GB_REL_IFS)MAKEREL(gbdoffset, ifsoffset);
437
438                // TEST_INITIALIZED(gbccopy);
439
440                gbccopy_size = ftwrite_unaligned(&gbccopy, sizeof(gbccopy), out);
441            }
442            else {
443                gbccopy_size = ALIGN(sizeof(gbccopy));
444            }
445            *offset += gbccopy_size;
446        }
447    }
448    else { // GBENTRY
449        GBENTRY *gbe = gbd->as_entry();
450        GBENTRY  gbecopy;
451
452        // init mem to silence valgrind
453        // (GBENTRY contains 4 unused bytes; see ad_load.cxx@TEST_GBDATA_size
454        // @@@ should be fixed; fix needs mapfile-format-version-increment)
455        memset(&gbecopy, 0, sizeof(gbecopy));
456
457        gbecopy = *gbe;  // make copy to avoid change of mem
458
459        if (gbe->stored_external()) {
460            long   exoffset = *offset;
461            size_t ex_size;
462
463            if (out) ex_size = ftwrite_unaligned(gbe->info.ex.get_data(), gbecopy.info.ex.memsize, out);
464            else ex_size     = ALIGN(gbecopy.info.ex.memsize);
465
466            *offset                  += ex_size;
467            gbecopy.info.ex.rel_data  = (GB_REL_STRING)MAKEREL(*offset+PTR_DIFF(&(gbe->info), gbe), exoffset);
468        }
469
470        gbdoffset = *offset;
471
472        {
473            size_t gbecopy_size;
474            if (out) {
475                gbdata_offset *dof = find_gbdata_offset(quark, gbe);
476                gbecopy.index = dof->index;
477                gb_assert(dof->index <= gbe->index); // very simple check
478
479                gbecopy.rel_father  = (GB_REL_CONTAINER)getrel_GBDATA(gbdoffset, GB_FATHER(gbe));
480                gbecopy.ext         = NULL;
481                gbecopy.server_id   = GBTUM_MAGIC_NUMBER;
482                convertFlags4Save(&(gbecopy.flags), &(gbecopy.flags2), NULL);
483                gbecopy.cache_index = 0;
484
485                // TEST_INITIALIZED(gbecopy);
486
487                gbecopy_size = ftwrite_unaligned(&gbecopy, sizeof(gbecopy), out);
488            }
489            else {
490                gbecopy_size = ALIGN(sizeof(gbecopy));
491            }
492            *offset += gbecopy_size;
493        }
494    }
495
496    return gbdoffset;
497}
498
499static long writeGbdByKey(GB_MAIN_TYPE *Main, gbdByKey *gbk, FILE *out, GB_MAIN_IDX main_idx)
500{
501    int idx;
502    int idx2;
503    long offset = ALIGN(sizeof(gb_map_header));
504
505    for (idx=0; idx<Main->keycnt; idx++)
506    {
507        for (idx2=0; idx2<gbk[idx].cnt; idx2++)
508        {
509            IF_ASSERTION_USED(long gboffset =) write_GBDATA(Main, gbk[idx].gbdoff[idx2].gbd, idx, out, &offset, main_idx);
510            gb_assert(gboffset == gbk[idx].gbdoff[idx2].offset);
511        }
512    }
513
514    return offset;
515}
516
517static long calcGbdOffsets(GB_MAIN_TYPE *Main, gbdByKey *gbk)
518{
519    int idx;
520    int idx2;
521    long offset = ALIGN(sizeof(gb_map_header));
522
523    for (idx=0; idx<Main->keycnt; idx++)
524    {
525        for (idx2=0; idx2<gbk[idx].cnt; idx2++)
526        {
527            gbk[idx].gbdoff[idx2].offset =
528                write_GBDATA(Main, gbk[idx].gbdoff[idx2].gbd, idx, NULL, &offset, 0);
529        }
530    }
531
532    return offset;
533}
534
535/* ********************************************************
536   handle gbdByKey
537   ******************************************************** */
538
539static void scanGbdByKey(GB_MAIN_TYPE *Main, GBDATA *gbd, gbdByKey *gbk) {
540    if (gbd->flags.temporary) return;
541
542    if (gbd->is_container()) {
543        GBCONTAINER *gbc = gbd->as_container();
544        for (int idx=0; idx < gbc->d.nheader; idx++) {
545            GBDATA *gbd2 = GBCONTAINER_ELEM(gbc, idx);
546            if (gbd2) scanGbdByKey(Main, gbd2, gbk);
547        }
548    }
549
550    GBQUARK quark = GB_KEY_QUARK(gbd);
551
552#if defined(DEBUG)
553    if (quark == 0) {
554        printf("KeyQuark==0 found:\n");
555        GB_dump_db_path(gbd);
556    }
557#endif // DEBUG
558    gb_assert(gbk[quark].gbdoff!=0);
559
560    gbk[quark].gbdoff[gbk[quark].cnt].gbd = gbd;
561    gbk[quark].gbdoff[gbk[quark].cnt].offset = -1;   // -1 is impossible as offset in file
562    gbk[quark].cnt++;
563}
564
565static gbdByKey *createGbdByKey(GB_MAIN_TYPE *Main)
566{
567    int       idx;
568    gbdByKey *gbk = (gbdByKey*)GB_calloc(Main->keycnt, sizeof(*gbk));
569
570    if (!gbk) goto err1;
571
572    for (idx=0; idx<Main->keycnt; idx++) {
573        gbk[idx].cnt = 0;
574
575        gb_Key& KEY = Main->keys[idx];
576        if (KEY.key && KEY.nref>0) {
577            gbk[idx].gbdoff  = (gbdata_offset *)GB_calloc(KEY.nref, sizeof(*(gbk[idx].gbdoff)));
578            if (!gbk[idx].gbdoff) goto err2;
579        }
580    }
581
582    gbk[0].gbdoff = (gbdata_offset *)GB_calloc(1, sizeof(*(gbk[0].gbdoff))); // @@@ FIXME : this is maybe allocated twice (5 lines above and here), maybe idx == 0 is special ?
583
584    scanGbdByKey(Main, Main->gb_main(), gbk);
585
586    for (idx=0; idx<Main->keycnt; idx++)
587        if (gbk[idx].cnt)
588            sort_gbdata_offsets(gbk[idx].gbdoff, gbk[idx].cnt);
589
590    return gbk;
591
592    // error handling:
593
594 err2 : while (idx>=0)
595 {
596     free(gbk[idx].gbdoff);
597     idx--;
598 }
599    free(gbk);
600 err1 : GB_memerr();
601    return NULL;
602}
603
604static void freeGbdByKey(GB_MAIN_TYPE *Main, gbdByKey *gbk)
605{
606    int idx;
607
608    for (idx=0; idx<Main->keycnt; idx++) free(gbk[idx].gbdoff);
609    free(gbk);
610}
611
612/* ********************************************************
613   save
614   ******************************************************** */
615
616GB_ERROR gb_save_mapfile(GB_MAIN_TYPE *Main, GB_CSTR path) {
617    GB_ERROR error = NULL;
618
619    gb_gbk = createGbdByKey(Main);
620    if (!gb_gbk) error = GB_await_error();
621    else {
622        FILE *out  = fopen(path, "w");
623        writeError = out==NULL;                         // global flag
624
625        gb_assert(ADMAP_ID_LEN <= strlen(ADMAP_ID));
626
627        if (!writeError) {
628            IF_ASSERTION_USED(long calcOffset=)
629                calcGbdOffsets(Main, gb_gbk);
630
631            gb_map_header mheader;
632            memset(&mheader, 0, sizeof(mheader));
633            strcpy(mheader.mapfileID, ADMAP_ID);        // header
634
635            mheader.version    = ADMAP_VERSION;
636            mheader.byte_order = ADMAP_BYTE_ORDER;
637
638            GB_MAIN_IDX main_idx_4_save = gb_make_main_idx(Main); // Generate a new main idx (temporary during save)
639            mheader.main_idx            = main_idx_4_save;
640
641            mheader.main_data_offset = getrel_GBDATA(1, Main->gb_main())+1;
642
643            ftwrite_unaligned(&mheader, sizeof(mheader), out);
644
645            gb_assert(GB_FATHER(Main->root_container) == Main->dummy_father);
646            SET_GB_FATHER(Main->root_container, NULL);
647   
648            IF_ASSERTION_USED(long writeOffset =)
649                writeGbdByKey(Main, gb_gbk, out, main_idx_4_save);
650            SET_GB_FATHER(Main->root_container, Main->dummy_father);
651
652            gb_assert(calcOffset==writeOffset);
653
654            freeGbdByKey(Main, gb_gbk);
655            gb_gbk = NULL;
656
657            {
658                GB_MAIN_IDX org_main_idx     = Main->dummy_father->main_idx;
659                Main->dummy_father->main_idx = main_idx_4_save;
660                Main->release_main_idx();
661                Main->dummy_father->main_idx = org_main_idx;
662            }
663        }
664
665        if (out && fclose(out) != 0) writeError = true;
666       
667        if (writeError) {
668            error = GB_IO_error("saving fastloadfile", path);
669            GB_unlink_or_warn(path, &error);
670        }
671    }
672
673    return error;
674}
675
676bool GB_supports_mapfile() {
677#if (MEMORY_TEST == 1)
678    return false;
679#else
680    return true;
681#endif
682}
683
684int gb_is_valid_mapfile(const char *path, gb_map_header *mheader, int verbose) {
685    /* Test whether mapfile is valid
686     * returns
687     *     -1   no map file found / MEMORY_TEST (don't use mapfile)
688     *      0   mapfile error
689     *      1   mapfile ok
690     */
691
692#if ( MEMORY_TEST == 1)
693    // Don't map anything in memory debug mode
694    UNUSED_IN_MEMTEST(path);
695    UNUSED_IN_MEMTEST(mheader);
696    UNUSED_IN_MEMTEST(verbose);
697    return -1;
698#else
699    FILE *in = fopen(path, "r");
700    if (in) {
701        GB_ERROR error = NULL;
702
703        if (verbose) printf("ARB: Opening FastLoad File '%s' ...\n", path);
704        if (fread((char *)mheader, sizeof(*mheader), 1, in) != 1) {
705            error = GB_IO_error("reading header", path);
706        }
707        fclose(in);
708
709        if (!error) {
710            const char *error_form = 0;
711
712            if (strcmp(mheader->mapfileID, ADMAP_ID)!=0)    error_form = "'%s' is not a ARB-FastLoad-File";
713            else if (mheader->version!=ADMAP_VERSION)       error_form = "FastLoad-File '%s' has wrong version";
714            else if (mheader->byte_order!=ADMAP_BYTE_ORDER) error_form = "FastLoad-File '%s' has wrong byte order";
715
716            if (error_form) error = GBS_global_string(error_form, path);
717        }
718
719        if (error) {
720            GB_export_error(error);
721            GB_print_error();
722            return 0;
723        }
724        return 1;
725    }
726    return -1;
727#endif
728}
729
730/* The module admalloc.c must be able to determine whether a memory block
731 * is inside the mapped file. So we store the location of the mapped file in
732 * the following variables:
733 */
734static char *fileMappedTo[GB_MAX_MAPPED_FILES];
735static long  fileLen[GB_MAX_MAPPED_FILES];
736static int   mappedFiles = 0;
737
738GBDATA *gb_map_mapfile(const char *path)
739{
740    gb_map_header mheader;
741
742    if (gb_is_valid_mapfile(path, &mheader, 1)>0)
743    {
744        char *mapped;
745        mapped = GB_map_file(path, 1);
746
747        if (mapped)
748        {
749            fileMappedTo[mappedFiles] = mapped;
750            fileLen[mappedFiles++] = GB_size_of_file(path);
751            gb_assert(mappedFiles<=GB_MAX_MAPPED_FILES);
752
753            return (GBDATA*)(mapped+mheader.main_data_offset);
754        }
755    }
756
757    return NULL;
758}
759
760int gb_isMappedMemory(void *mem)
761{
762    int file = 0;
763
764    while (file<mappedFiles)
765    {
766        if (mem>=fileMappedTo[file] &&
767            mem<(fileMappedTo[file]+fileLen[file])) return 1;
768        file++;
769    }
770
771    return 0;
772}
773
Note: See TracBrowser for help on using the repository browser.