source: branches/port5/PROBE/PT_prefixtree.cxx

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