source: tags/old_import_filter/PROBE/PT_prefixtree.cxx

Last change on this file was 9516, checked in by westram, 11 years ago
  • reintegrated branch 'cxx11'
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.7 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PT_prefixtree.cxx                                 //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "probe.h"
12#include "probe_tree.h"
13#include "pt_prototypes.h"
14
15#include <arb_file.h>
16
17#include <sys/types.h>
18#include <sys/mman.h>
19#include <climits>
20
21struct PTM_struct PTM;
22char PT_count_bits[PT_B_MAX+1][256]; // returns how many bits are set
23
24static void PT_init_count_bits() {
25    unsigned int base;
26    unsigned int count;
27    unsigned int i, h, j;
28    for (base = PT_QU; base <= PT_B_MAX; base++) {
29        for (i=0; i<256; i++) {
30            h = 0xff >> (8-base);
31            h &= i;
32            count = 0;
33            for (j=0; j<8; j++) {
34                if (h&1) count++;
35                h = h>>1;
36            }
37            PT_count_bits[base][i] = count;
38        }
39    }
40}
41
42static void PTM_add_alloc(void *ptr) {
43    if (PTM.alloc_counter == PTM.alloc_array_size) {
44        if (PTM.alloc_array_size == 0)
45            PTM.alloc_array_size = 1;
46
47        PTM.alloc_array_size = PTM.alloc_array_size * 2;
48        void **new_array = (void **) malloc(PTM.alloc_array_size
49                * sizeof(void*));
50
51        if (!new_array)
52            abort();
53
54        void *old_array = PTM.alloc_ptr;
55        memcpy(new_array, old_array, PTM.alloc_counter * sizeof(void*));
56        PTM.alloc_ptr = new_array;
57        free(old_array);
58    }
59    PTM.alloc_ptr[PTM.alloc_counter++] = ptr;
60}
61
62void PTM_finally_free_all_mem() {
63    for (unsigned long i = 0; i < PTM.alloc_counter; ++i)
64        free(PTM.alloc_ptr[i]);
65    PTM.alloc_counter = 0;
66    PTM.alloc_array_size = 0;
67    free(PTM.alloc_ptr);
68}
69
70static char *PTM_get_mem(int size) {
71    //! allocate 'size' bytes
72
73    int nsize = (size + (PTM_ALIGNED - 1)) & (-PTM_ALIGNED);
74    if (nsize > PTM_MAX_SIZE) {
75        void * ptr = calloc(1, size);
76        PTM_add_alloc(ptr);
77        return (char *) ptr;
78    }
79
80    int pos = nsize >> PTM_LD_ALIGNED;
81
82#ifdef PTM_DEBUG
83    PTM.debug[pos]++;
84#endif
85
86    char *erg = PTM.tables[pos];
87    if (erg) {
88        long i;
89        PT_READ_PNTR(((char *)PTM.tables[pos]), i);
90        PTM.tables[pos] = (char *)i;
91    }
92    else {
93        if (PTM.size < nsize) {
94            PTM.data         = (char *) calloc(1, PTM_TABLE_SIZE);
95            PTM.size         = PTM_TABLE_SIZE;
96            PTM.allsize     += PTM_TABLE_SIZE;
97#ifdef PTM_DEBUG
98            static int less  = 0;
99            if ((less%10) == 0) {
100                printf("Memory usage: %li byte\n", PTM.allsize);
101            }
102            ++less;
103#endif
104            PTM_add_alloc(PTM.data);
105        }
106        erg = PTM.data;
107        PTM.data += nsize;
108        PTM.size -= nsize;
109    }
110    memset(erg, 0, nsize);
111    return erg;
112}
113
114static void PTM_free_mem(char *data, int size) {
115    //! free memory allocated by PTM_get_mem()
116
117    pt_assert(size > 0);
118
119    int nsize = (size + (PTM_ALIGNED - 1)) & (-PTM_ALIGNED);
120    if (nsize > PTM_MAX_SIZE) {
121        free(data);
122    }
123    else {
124        // if (data[4] == PTM_magic) PT_CORE
125        int pos = nsize >> PTM_LD_ALIGNED;
126
127#ifdef PTM_DEBUG
128        PTM.debug[pos]--;
129#endif
130        long i = (long)PTM.tables[pos];
131        PT_WRITE_PNTR(data, i);
132        data[sizeof(PT_PNTR)] = PTM_magic;
133        PTM.tables[pos] = data;
134    }
135}
136
137PTM2 *PT_init() {
138    PTM2 *ptmain;
139    memset(&PTM, 0, sizeof(struct PTM_struct));
140    ptmain = (PTM2 *)calloc(1, sizeof(PTM2));
141    ptmain->mode = sizeof(PT_PNTR);
142    ptmain->stage1 = 1;
143    int i;
144    for (i=0; i<256; i++) {
145        if      ((i&0xe0) == 0x20) PTM.flag_2_type[i] = PT_NT_SAVED;
146        else if ((i&0xe0) == 0x00) PTM.flag_2_type[i] = PT_NT_LEAF;
147        else if ((i&0x80) == 0x80) PTM.flag_2_type[i] = PT_NT_NODE;
148        else if ((i&0xe0) == 0x40) PTM.flag_2_type[i] = PT_NT_CHAIN;
149        else                       PTM.flag_2_type[i] = PT_NT_UNDEF;
150    }
151    PT_init_count_bits();
152
153    PTM.alloc_ptr = NULL;
154    PTM.alloc_counter = 0;
155    PTM.alloc_array_size = 0;
156
157    return ptmain;
158}
159
160// ------------------------------
161//      functions for stage 1
162
163static void PT_change_father(POS_TREE *father, POS_TREE *source, POS_TREE *dest) { // stage 1
164    long i, j;
165    i = PT_count_bits[PT_B_MAX][father->flags];
166    for (; i>0; i--) {
167        PT_READ_PNTR((&father->data)+sizeof(PT_PNTR)*i, j);
168        if (j==(long)source) {
169            PT_WRITE_PNTR((&father->data)+sizeof(PT_PNTR)*i, (long)dest);
170            return;
171        }
172    }
173    PT_CORE;
174}
175
176POS_TREE *PT_add_to_chain(POS_TREE *node, const DataLoc& loc) { // stage1
177    // insert at the beginning of list
178
179    char *data  = (&node->data) + psg.ptmain->mode;
180    data       += (node->flags&1) ? 4 : 2;
181
182    unsigned long old_first;
183    PT_READ_PNTR(data, old_first);  // create a new list element
184
185    static char  buffer[100];
186    char        *p = buffer;
187
188    PT_WRITE_PNTR(p, old_first);
189    p += sizeof(PT_PNTR);
190
191    PT_WRITE_NAT(p, loc.name);
192    PT_WRITE_NAT(p, loc.rpos);
193    PT_WRITE_NAT(p, loc.apos);
194   
195    int size = p - buffer;
196    p        = (char *)PTM_get_mem(size);
197    memcpy(p, buffer, size);
198    PT_WRITE_PNTR(data, p);
199    psg.stat.cut_offs ++;
200    return NULL;
201}
202
203POS_TREE *PT_change_leaf_to_node(POS_TREE *node) { // stage 1
204    if (PT_GET_TYPE(node) != PT_NT_LEAF) PT_CORE;
205   
206    long i;
207    PT_READ_PNTR((&node->data), i);
208
209    POS_TREE *father   = (POS_TREE *)i;
210    POS_TREE *new_elem = (POS_TREE *)PTM_get_mem(PT_EMPTY_NODE_SIZE);
211    if (father) PT_change_father(father, node, new_elem);
212    PTM_free_mem((char *)node, PT_LEAF_SIZE(node));
213    PT_SET_TYPE(new_elem, PT_NT_NODE, 0);
214    PT_WRITE_PNTR((&(new_elem->data)), (long)father);
215
216    return new_elem;
217}
218
219POS_TREE *PT_leaf_to_chain(POS_TREE *node) { // stage 1
220    if (PT_GET_TYPE(node) != PT_NT_LEAF) PT_CORE;
221
222    long i;
223    PT_READ_PNTR((&node->data), i);
224
225    POS_TREE      *father = (POS_TREE *)i;
226    const DataLoc  loc(node);
227
228    int chain_size                          = PT_EMPTY_CHAIN_SIZE;
229    if (loc.apos>PT_SHORT_SIZE) chain_size += 2;
230
231    POS_TREE *new_elem = (POS_TREE *)PTM_get_mem(chain_size);
232    PT_change_father(father, node, new_elem);
233    PTM_free_mem((char *)node, PT_LEAF_SIZE(node));
234    PT_SET_TYPE(new_elem, PT_NT_CHAIN, 0);
235    PT_WRITE_PNTR((&new_elem->data), (long)father);
236   
237    char *data = (&new_elem->data)+sizeof(PT_PNTR);
238    if (loc.apos>PT_SHORT_SIZE) {                                   
239        PT_WRITE_INT(data, loc.apos);                               
240        data+=4;
241        new_elem->flags|=1;
242    }
243    else {                                                     
244        PT_WRITE_SHORT(data, loc.apos);
245        data+=2;
246    }
247    PT_WRITE_PNTR(data, NULL);
248    PT_add_to_chain(new_elem, loc);
249
250    return new_elem;
251}
252
253POS_TREE *PT_create_leaf(POS_TREE ** pfather, PT_BASES base, const DataLoc& loc) { // stage 1
254    POS_TREE *father, *node, *new_elemfather;
255    int       base2;
256    int       leafsize;
257    char     *dest;
258    leafsize = PT_EMPTY_LEAF_SIZE;
259
260    if (loc.rpos>PT_SHORT_SIZE) leafsize += 2;
261    if (loc.apos>PT_SHORT_SIZE) leafsize += 2;
262    if (loc.name>PT_SHORT_SIZE) leafsize += 2;
263    node                              = (POS_TREE *) PTM_get_mem(leafsize);
264    if (base >= PT_B_MAX)
265        *(int *) 0                    = 0;
266    if (pfather) {
267        int             oldfathersize;
268        POS_TREE       *gfather, *son;
269        long             i, j, sbase, dbase;
270        father = *pfather;
271        PT_NODE_SIZE(father, oldfathersize);
272        new_elemfather = (POS_TREE *)PTM_get_mem(oldfathersize + sizeof(PT_PNTR));
273        PT_READ_PNTR(&father->data, j);
274        gfather = (POS_TREE *)j;
275        if (gfather) {
276            PT_change_father(gfather, father, new_elemfather);
277            PT_WRITE_PNTR(&new_elemfather->data, gfather);
278        }
279        sbase = dbase = sizeof(PT_PNTR);
280        base2 = 1 << base;
281        for (i = 1; i < 0x40; i = i << 1) {
282            if (i & father->flags) {
283                PT_READ_PNTR(((char *) &father->data) + sbase, j);
284                son = (POS_TREE *)j;
285                int sontype = PT_GET_TYPE(son);
286                if (sontype != PT_NT_SAVED) {
287                    PT_WRITE_PNTR((char *) &son->data, new_elemfather);
288                }
289                PT_WRITE_PNTR(((char *) &new_elemfather->data) + dbase, son);
290                sbase += sizeof(PT_PNTR);
291                dbase += sizeof(PT_PNTR);
292                continue;
293            }
294            if (i & base2) {
295                PT_WRITE_PNTR(((char *) &new_elemfather->data) + dbase, node);
296                PT_WRITE_PNTR((&node->data), (PT_PNTR)new_elemfather);
297                dbase += sizeof(PT_PNTR);
298            }
299        }
300        new_elemfather->flags = father->flags | base2;
301        PTM_free_mem((char *)father, oldfathersize);
302        PT_SET_TYPE(node, PT_NT_LEAF, 0);
303        *pfather = new_elemfather;
304    }
305    PT_SET_TYPE(node, PT_NT_LEAF, 0);
306    dest = (&node->data) + sizeof(PT_PNTR);
307    if (loc.name>PT_SHORT_SIZE) {
308        PT_WRITE_INT(dest, loc.name);
309        node->flags |= 1;
310        dest += 4;
311    }
312    else {
313        PT_WRITE_SHORT(dest, loc.name);
314        dest += 2;
315    }
316    if (loc.rpos>PT_SHORT_SIZE) {
317        PT_WRITE_INT(dest, loc.rpos);
318        node->flags |= 2;
319        dest += 4;
320    }
321    else {
322        PT_WRITE_SHORT(dest, loc.rpos);
323        dest += 2;
324    }
325    if (loc.apos>PT_SHORT_SIZE) {
326        PT_WRITE_INT(dest, loc.apos);
327        node->flags |= 4;
328        dest += 4;
329    }
330    else {
331        PT_WRITE_SHORT(dest, loc.apos);
332        dest += 2;
333    }
334    if (base == PT_QU)
335        return PT_leaf_to_chain(node);
336    return node;
337}
338
339// ------------------------------------
340//      functions for stage 1: save
341
342void PTD_clear_fathers(POS_TREE * node) { // stage 1
343    PT_NODE_TYPE type = PT_read_type(node);
344    if (type != PT_NT_SAVED) {
345        PT_WRITE_PNTR((&node->data), NULL);
346        if (type == PT_NT_NODE) {
347            for (int i = PT_QU; i < PT_B_MAX; i++) {
348                POS_TREE *sons = PT_read_son(node, (PT_BASES)i);
349                if (sons) PTD_clear_fathers(sons);
350            }
351        }
352    }
353}
354
355#ifdef ARB_64
356void PTD_put_longlong(FILE * out, ULONG i)
357{
358    pt_assert(i == (unsigned long) i);
359    STATIC_ASSERT(sizeof(PT_PNTR) == 8);       // this function only work and only get called at 64-bit
360    int io;
361    static unsigned char buf[8];
362    PT_WRITE_PNTR(buf, i);
363
364    io = buf[0]; putc(io, out);             // TODO: replace with fwrite
365    io = buf[1]; putc(io, out);
366    io = buf[2]; putc(io, out);
367    io = buf[3]; putc(io, out);
368    io = buf[4]; putc(io, out);
369    io = buf[5]; putc(io, out);
370    io = buf[6]; putc(io, out);
371    io = buf[7]; putc(io, out);
372}
373#endif
374void PTD_put_int(FILE * out, ULONG i)
375{
376    pt_assert(i == (unsigned int) i);
377    int io;
378    static unsigned char buf[4];
379    PT_WRITE_INT(buf, i);
380    io = buf[0]; putc(io, out);             // TODO: replace with fwrite
381    io = buf[1]; putc(io, out);
382    io = buf[2]; putc(io, out);
383    io = buf[3]; putc(io, out);
384}
385
386void PTD_put_short(FILE * out, ULONG i)
387{
388    pt_assert(i == (unsigned short) i);
389    int io;
390    static unsigned char buf[2];
391    PT_WRITE_SHORT(buf, i);
392    io = buf[0]; putc(io, out);             // TODO: replace with fwrite
393    io = buf[1]; putc(io, out);
394}
395
396static void PTD_set_object_to_saved_status(POS_TREE * node, long pos, int size) {
397    node->flags = 0x20;
398    PT_WRITE_PNTR((&node->data), pos);
399    if (size < 20) {
400        node->flags |= size-sizeof(PT_PNTR);
401    }
402    else {
403        PT_WRITE_INT((&node->data)+sizeof(PT_PNTR), size);
404    }
405}
406
407static long PTD_write_tip_to_disk(FILE * out, POS_TREE * node, long pos)
408{
409    int size, cnt;
410    putc(node->flags, out);         // save type
411    size = PT_LEAF_SIZE(node);
412    // write 4 bytes when not in stage 2 save mode
413
414    cnt = size-sizeof(PT_PNTR)-1;               // no father; type already saved
415#ifdef ARB_64
416    fwrite(&node->data + sizeof(PT_PNTR), 0x01, cnt, out);   // write name rpos apos
417#else
418    for (char *data = (&node->data)+sizeof(PT_PNTR); cnt; cnt--) { // write apos rpos name
419        int i = (int)(*(data++));
420        putc(i, out);
421    }
422#endif
423    PTD_set_object_to_saved_status(node, pos, size);
424    pos += size-sizeof(PT_PNTR);                // no father
425    pt_assert(pos >= 0);
426    return pos;
427}
428
429static int ptd_count_chain_entries(char * entry) {
430    int counter   = 0;
431    long next;
432    while (entry) {
433        counter ++;
434        PT_READ_PNTR(entry, next);
435        entry = (char *)next;
436    }
437    pt_assert(counter >= 0);
438    return counter;
439}
440
441static void ptd_set_chain_references(char *entry, char **entry_tab) {
442    int counter   = 0;
443    long next;
444    while (entry) {
445        entry_tab[counter] = entry;
446        counter ++;
447        PT_READ_PNTR(entry, next);
448        entry = (char *)next;
449    }
450}
451
452static ARB_ERROR ptd_write_chain_entries(FILE * out, long *ppos, char ** entry_tab,  int n_entries, int mainapos) { // __ATTR__USERESULT
453    ARB_ERROR   error;
454    int         lastname = 0;
455   
456    while (n_entries>0 && !error) {
457        char *entry = entry_tab[n_entries-1];
458        n_entries --;
459        char *rp = entry;
460        rp += sizeof(PT_PNTR);
461
462        int name;
463        int rpos;
464        int apos;
465        PT_READ_NAT(rp, name);
466        PT_READ_NAT(rp, rpos);
467        PT_READ_NAT(rp, apos);
468        if (name < lastname) {
469            error = GBS_global_string("Chain Error: name order error %i < %i\n", name, lastname);
470        }
471        else {
472            static char  buffer[100];
473            char        *wp   = buffer;
474            wp                = PT_WRITE_CHAIN_ENTRY(wp, mainapos, name-lastname, apos, rpos);
475            int          size = wp -buffer;
476
477            if (1 != fwrite(buffer, size, 1, out)) {
478                error = GB_IO_error("writing chains to", "ptserver-index");
479            }
480            else {
481                *ppos    += size;
482                PTM_free_mem(entry, rp-entry);
483                lastname  = name;
484            }
485        }
486    }
487
488    return error;
489}
490
491
492static long PTD_write_chain_to_disk(FILE * out, POS_TREE * node, long pos, ARB_ERROR& error) {
493    char *data;
494    long oldpos = pos;
495    putc(node->flags, out);         // save type
496    pos++;
497    int mainapos;
498    data = (&node->data) + psg.ptmain->mode;
499
500    if (node->flags&1) {
501        PT_READ_INT(data, mainapos);
502        PTD_put_int(out, mainapos);
503        data += 4;
504        pos += 4;
505    }
506    else {
507        PT_READ_SHORT(data, mainapos);
508        PTD_put_short(out, mainapos);
509        data += 2;
510        pos += 2;
511    }
512    long first_entry;
513    PT_READ_PNTR(data, first_entry);
514    int n_entries = ptd_count_chain_entries((char *)first_entry);
515    {
516        char **entry_tab = (char **)GB_calloc(sizeof(char *), n_entries);
517        ptd_set_chain_references((char *)first_entry, entry_tab);
518        error = ptd_write_chain_entries(out, &pos, entry_tab, n_entries, mainapos);
519        free(entry_tab);
520    }
521    putc(PT_CHAIN_END, out);
522    pos++;
523    PTD_set_object_to_saved_status(node, oldpos, data+sizeof(PT_PNTR)-(char*)node);
524    pt_assert(pos >= 0);
525    return pos;
526}
527
528void PTD_debug_nodes() {
529#ifdef ARB_64
530    printf ("Inner Node Statistic:\n");
531    printf ("   Single Nodes:   %6i\n", psg.stat.single_node);
532    printf ("   Short  Nodes:   %6i\n", psg.stat.short_node);
533    printf ("       Chars:      %6i\n", psg.stat.chars);
534    printf ("       Shorts:     %6i\n", psg.stat.shorts2);
535    printf ("   Int    Nodes:   %6i\n", psg.stat.int_node);
536    printf ("       Shorts:     %6i\n", psg.stat.shorts);
537    printf ("       Ints:       %6i\n", psg.stat.ints2);
538    printf ("   Long   Nodes:   %6i\n", psg.stat.long_node);
539    printf ("       Ints:       %6i\n", psg.stat.ints);
540    printf ("       Longs:      %6i\n", psg.stat.longs);
541    printf ("   maxdiff:        %6li\n", psg.stat.maxdiff);
542#else
543    printf ("Inner Node Statistic:\n");
544    printf ("   Single Nodes:   %6i\n", psg.stat.single_node);
545    printf ("   Short  Nodes:   %6i\n", psg.stat.short_node);
546    printf ("       Chars:      %6i\n", psg.stat.chars);
547    printf ("       Shorts:     %6i\n", psg.stat.shorts2);
548    printf ("   Long   Nodes:   %6i\n", psg.stat.long_node);
549    printf ("       Shorts:     %6i\n", psg.stat.shorts);
550    printf ("       Longs:      %6i\n", psg.stat.longs);        // "longs" are actually 32 bit ints
551#endif
552}
553
554static long PTD_write_node_to_disk(FILE * out, POS_TREE * node, long *r_poss, long pos) {
555    int i, size;   // Save node after all descendends are already saved
556    POS_TREE *sons;
557
558    long max_diff = 0;
559    int  lasti = 0;
560    int  count = 0;
561    int  mysize;
562
563    size = PT_EMPTY_NODE_SIZE;
564    mysize = PT_EMPTY_NODE_SIZE;
565
566    for (i = PT_QU; i < PT_B_MAX; i++) {    // free all sons
567        sons = PT_read_son(node, (PT_BASES)i);
568        if (sons) {
569            int memsize;
570            long   diff = pos - r_poss[i];
571            pt_assert(diff >= 0);
572            if (diff>max_diff) {
573                max_diff = diff;
574                lasti = i;
575#ifdef ARB_64
576                if (max_diff > psg.stat.maxdiff) {
577                    psg.stat.maxdiff = max_diff;
578                }
579#endif
580            }
581            mysize += sizeof(PT_PNTR);
582            if (PT_GET_TYPE(sons) != PT_NT_SAVED) {
583                GBK_terminate("Internal Error: Son not saved");
584            }
585            if ((sons->flags & 0xf) == 0) {
586                PT_READ_INT((&sons->data)+sizeof(PT_PNTR), memsize);
587            }
588            else {
589                memsize = (sons->flags &0xf) + sizeof(PT_PNTR);
590            }
591            PTM_free_mem((char *)sons, memsize);
592            count ++;
593        }
594    }
595    if ((count == 1) && (max_diff<=9) && (max_diff != 2)) { // nodesingle
596        if (max_diff>2) max_diff -= 2; else max_diff -= 1;
597        long flags = 0xc0 | lasti | (max_diff << 3);
598        putc((int)flags, out);
599        psg.stat.single_node++;
600    }
601    else {                          // multinode
602        putc(node->flags, out);
603        int flags2 = 0;
604        int level;
605#ifdef ARB_64
606        if (max_diff > 0xffffffff) {        // long node
607            printf("Warning: max_diff > 0xffffffff is not tested.\n");
608            flags2 |= 0x40;
609            level = 0xffffffff;
610            psg.stat.long_node++;
611        }
612        else if (max_diff > 0xffff) {       // int node
613            flags2 |= 0x80;
614            level = 0xffff;
615            psg.stat.int_node++;
616        }
617        else {                              // short node
618            level = 0xff;
619            psg.stat.short_node++;
620        }
621#else
622        if (max_diff > 0xffff) {
623            flags2 |= 0x80;
624            level = 0xffff;
625            psg.stat.long_node++;
626        }
627        else {
628            max_diff = 0;
629            level = 0xff;
630            psg.stat.short_node++;
631        }
632#endif
633        for (i = PT_QU; i < PT_B_MAX; i++) {    // set the flag2
634            if (r_poss[i]) {
635                /* u */ long  diff = pos - r_poss[i];
636                pt_assert(diff >= 0);
637                if (diff>level) flags2 |= 1<<i;
638            }
639        }
640        putc(flags2, out);
641        size++;
642        for (i = PT_QU; i < PT_B_MAX; i++) {    // write the data
643            if (r_poss[i]) {
644                /* u */ long  diff = pos - r_poss[i];
645                pt_assert(diff >= 0);
646#ifdef ARB_64
647                if (max_diff > 0xffffffff) {        // long long / int  (bit[6] in flags2 is set; bit[7] is unset)
648                    printf("Warning: max_diff > 0xffffffff is not tested.\n");
649                    if (diff>level) {               // long long (64 bit)  (bit[i] in flags2 is set)
650                        PTD_put_longlong(out, diff);
651                        size += 8;
652                        psg.stat.longs++;
653                    }
654                    else {                          // int              (bit[i] in flags2 is unset)
655                        PTD_put_int(out, diff);
656                        size += 4;
657                        psg.stat.ints++;
658                    }
659                }
660                else if (max_diff > 0xffff) {       // int/short        (bit[6] in flags2 is unset; bit[7] is set)
661                    if (diff>level) {               // int              (bit[i] in flags2 is set)
662                        PTD_put_int(out, diff);
663                        size += 4;
664                        psg.stat.ints2++;
665                    }
666                    else {                          // short            (bit[i] in flags2 is unset)
667                        PTD_put_short(out, diff);
668                        size += 2;
669                        psg.stat.shorts++;
670                    }
671                }
672                else {                              // short/char       (bit[6] in flags2 is unset; bit[7] is unset)
673                    if (diff>level) {               // short            (bit[i] in flags2 is set)
674                        PTD_put_short(out, diff);
675                        size += 2;
676                        psg.stat.shorts2++;
677                    }
678                    else {                          // char             (bit[i] in flags2 is unset)
679                        putc((int)diff, out);
680                        size += 1;
681                        psg.stat.chars++;
682                    }
683                }
684#else
685                if (max_diff) {                     // int/short (bit[7] in flags2 set)
686                    if (diff>level) {               // int
687                        PTD_put_int(out, diff);
688                        size += 4;
689                        psg.stat.longs++;
690                    }
691                    else {                          // short
692                        PTD_put_short(out, diff);
693                        size += 2;
694                        psg.stat.shorts++;
695                    }
696                }
697                else {                              // short/char  (bit[7] in flags2 not set)
698                    if (diff>level) {               // short
699                        PTD_put_short(out, diff);
700                        size += 2;
701                        psg.stat.shorts2++;
702                    }
703                    else {                          // char
704                        putc((int)diff, out);
705                        size += 1;
706                        psg.stat.chars++;
707                    }
708                }
709#endif
710            }
711        }
712    }
713
714    PTD_set_object_to_saved_status(node, pos, mysize);
715    pos += size-sizeof(PT_PNTR);                // no father
716    pt_assert(pos >= 0);
717    return pos;
718}
719
720long PTD_write_leafs_to_disk(FILE * out, POS_TREE * node, long pos, long *pnodepos, int *pblock, ARB_ERROR& error) {
721    // returns new pos when son is written 0 otherwise
722    // pnodepos is set to last object
723
724    PT_NODE_TYPE type = PT_read_type(node);
725
726    if (type == PT_NT_SAVED) {          // already saved
727        long father;
728        PT_READ_PNTR((&node->data), father);
729        *pnodepos = father;
730        return 0;
731    }
732    else if (type == PT_NT_LEAF) {
733        *pnodepos = pos;
734        pos = PTD_write_tip_to_disk(out, node, pos);
735    }
736    else if (type == PT_NT_CHAIN) {
737        *pnodepos = pos;
738        pos = PTD_write_chain_to_disk(out, node, pos, error);
739    }
740    else if (type == PT_NT_NODE) {
741        int block[10]; // TODO: check why we allocate 10 ints when only block[0] is used
742        block[0] = 0;
743       
744        long o_pos = pos;
745        long r_poss[PT_B_MAX];
746        for (int i = PT_QU; i < PT_B_MAX && !error; i++) {    // save all sons
747            POS_TREE *sons = PT_read_son(node, (PT_BASES)i);
748            r_poss[i] = 0;
749            if (sons) {
750                long r_pos = PTD_write_leafs_to_disk(out, sons, pos, &(r_poss[i]), &(block[0]), error);
751                if (r_pos>pos) {        // really saved ????
752                    pos = r_pos;
753                }
754            }
755        }
756        if (block[0]) {     // son wrote a block
757            *pblock = 1;
758        }
759        else if (pos-o_pos > PT_BLOCK_SIZE) {
760            // a block is written
761            *pblock = 1;
762        }
763        else {          // now i can write my data
764            *pnodepos = pos;
765            if (!error) pos = PTD_write_node_to_disk(out, node, r_poss, pos);
766        }
767    }
768    pt_assert(pos >= 0 || error);
769    return pos;
770}
771
772// --------------------------------------
773//      functions for stage 2-3: load
774
775
776ARB_ERROR PTD_read_leafs_from_disk(const char *fname, POS_TREE **pnode) { // __ATTR__USERESULT
777    GB_ERROR  error  = NULL;
778    char     *buffer = GB_map_file(fname, 0);
779
780    if (!buffer) {
781        error = GBS_global_string("mmap failed (%s)", GB_await_error());
782    }
783    else {
784        long  size = GB_size_of_file(fname);
785        char *main = &(buffer[size-4]);
786
787        long i;
788        bool big_db = false;
789        PT_READ_INT(main, i);
790#ifdef ARB_64
791        if (i == 0xffffffff) {                      // 0xffffffff signalizes that "last_obj" is stored
792            main -= 8;                              // in the previous 8 byte (in a long long)
793            STATIC_ASSERT(sizeof(PT_PNTR) == 8);   // 0xffffffff is used to signalize to be compatible with older pt-servers
794            PT_READ_PNTR(main, i);                  // this search tree can only be loaded at 64 Bit
795
796            big_db = true;
797        }
798#else
799        if (i<0) {
800            pt_assert(i == -1);                     // aka 0xffffffff
801            big_db = true;                          // not usable in 32-bit version (fails below)
802        }
803        pt_assert(i <= INT_MAX);
804#endif
805
806        // try to find info_area
807        main -= 2;
808        short info_size;
809        PT_READ_SHORT(main, info_size);
810
811        bool info_detected = false;
812        if (info_size>0 && info_size<(main-buffer)) {   // otherwise impossible size
813            main -= info_size;
814
815            long magic;
816            int  version;
817
818            PT_READ_INT(main, magic); main += 4;
819            PT_READ_CHAR(main, version); main++;
820
821            pt_assert(PT_SERVER_MAGIC>0 && PT_SERVER_MAGIC<INT_MAX);
822
823            if (magic == PT_SERVER_MAGIC) {
824                info_detected = true;
825                if (version>PT_SERVER_VERSION) {
826                    error = "PT-server database was built with a newer version of PT-Server";
827                }
828            }
829        }
830
831#ifdef ARB_64
832        // 64bit version:
833        big_db        = big_db; // only used in 32bit
834        info_detected = info_detected;
835#else
836        // 32bit version:
837        if (!error && big_db) {
838            error = "PT-server database can only be used with 64bit-PT-Server";
839        }
840        if (!error && !info_detected) {
841            printf("Warning: ptserver DB has old format (no problem)\n");
842        }
843#endif
844
845        if (!error) {
846            pt_assert(i >= 0);
847
848            *pnode = (POS_TREE *)(i+buffer);
849
850            psg.ptmain->mode       = 0;
851            psg.ptmain->data_start = buffer;
852        }
853    }
854
855    return error;
856}
857
Note: See TracBrowser for help on using the repository browser.