source: tags/svn.1.5.4/PROBE/PT_prefixtree.cxx

Last change on this file was 8313, checked in by westram, 12 years ago
  • removed dead code

(partly reverted by [8316])

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