source: tags/svn.1.5.4/PROBE/probe_tree.h

Last change on this file was 8041, checked in by westram, 13 years ago

merge from dev [7990] [7991] [7992] [7993] [7994] [7995] [7996] [7998] [8001] [8003] [8005] [8006] [8007] [8008] [8009] [8011] [8012] [8019]

  • added a faked ecoli to ptserver test-db
  • added unit-tests for gene-ptserver
  • rename ptserver testdb
  • ptserver db-cleanup
    • size of mapfile for SSUREF108 is reduced by 85% (3,4Gb → 519Mb)
  • ptserver
    • refactored
      • prefix tree builders
      • probe_input_data
    • removed ptnd_new_match (dead code)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : probe_tree.h                                    //
4//   Purpose   :                                                 //
5//                                                               //
6//   Institute of Microbiology (Technical University Munich)     //
7//   http://www.arb-home.de/                                     //
8//                                                               //
9// ============================================================= //
10
11#ifndef PROBE_TREE_H
12#define PROBE_TREE_H
13
14#if defined(DARWIN)
15#include <krb5.h>
16#else
17#include <bits/wordsize.h>
18#endif // DARWIN
19
20#ifndef STATIC_ASSERT_H
21#include <static_assert.h>
22#endif
23#ifndef PROBE_H
24#include "probe.h"
25#endif
26
27#define PTM_magic             0xf4
28#define PTM_TABLE_SIZE        (1024*256)
29#define PTM_ALIGNED           1
30#define PTM_LD_ALIGNED        0
31#define PTM_MAX_TABLES        256 // -- ralf testing
32#define PTM_MAX_SIZE          (PTM_MAX_TABLES*PTM_ALIGNED)
33#define PT_CHAIN_END          0xff
34#define PT_CHAIN_NTERM        250
35#define PT_SHORT_SIZE         0xffff
36#define PT_BLOCK_SIZE         0x800
37#define PT_INIT_CHAIN_SIZE    20
38
39typedef void * PT_PNTR;
40
41extern struct PTM_struct {
42    char         *data;
43    int           size;
44    long          allsize;
45    char         *tables[PTM_MAX_TABLES+1];
46#ifdef PTM_DEBUG
47    long          debug[PTM_MAX_TABLES+1];
48#endif
49    PT_NODE_TYPE  flag_2_type[256];
50    //
51    void **alloc_ptr;
52    unsigned long alloc_counter;
53    unsigned long alloc_array_size;
54} PTM;
55
56extern char PT_count_bits[PT_B_MAX+1][256]; // returns how many bits are set
57        // e.g. PT_count_bits[3][n] is the number of the 3 lsb bits
58
59#if 0
60/*
61
62/ ****************
63    Their are 3 stages of data format:
64        1st:        Creation of the tree
65        2nd:        find equal or nearly equal subtrees
66        3rd:        minimum sized tree
67
68    The generic pointer (father):
69        1st create:     Pointer to the father
70        1st save:
71        2nd load        rel ptr of 'this' in the output file
72                    (==0 indicates not saved)
73
74**************** /
75/ * data format: * /
76
77/ ********************* Written object *********************** /
78    byte    =32         bit[7] = bit[6] = 0; bit[5] = 1
79                    bit[4] free
80                    bit[0-3] size of former entry -4
81                    if ==0 then size follows
82    PT_PNTR     rel start of the real object       // actually it's a pointer to the objects father
83    [int        size]       if bit[0-3] == 0;
84
85/ ********************* tip / leaf (7-13   +4)  *********************** /
86    byte    <32         bit[7] = bit[6] = bit[5] = 0
87                        bit[3-4] free
88    [PT_PNTR    father]     if main->mode
89    short/int   name        int if bit[0]
90    short/int   rel pos     int if bit[1]
91    short/int   abs pos     int if bit[2]
92
93/ ********************* inner node (1 + 4*[1-6] +4) (stage 1 + 2) *********************** /
94    byte    >128        bit[7] = 1  bit[6] = 0
95    [PT_PNTR father]        if main->mode
96    [PT_PNTR son0]          if bit[0]
97...
98    [PT_PNTR son5]          if bit[5]
99
100/ ********************* inner node (3-22    +4) (stage 3 only) *********************** /
101    byte                bit[7] = 1  bit[6] = 0
102    byte2               bit2[7] = 0  bit2[6] = 0  -->  short/char
103                        bit2[7] = 1  bit2[6] = 0  -->  int/short
104                        bit2[7] = 0  bit2[6] = 1  -->  long/int         // atm only if ARB_64 is set
105                        bit2[7] = 1  bit2[6] = 1  -->  undefined        // atm only if ARB_64 is set
106    [char/short/int/long son0]  if bit[0]   left (bigger) type if bit2[0] else right (smaller) type
107    [char/short/int/long son1]  if bit[1]   left (bigger) type if bit2[1] else right (smaller) type
108    ...
109    [char/short/int/long son5]  if bit[5]   left (bigger) type if bit2[5] else right (smaller) type
110
111    example1:   byte  = 0x8d    --> inner node; son0, son2 and son3 are available
112                byte2 = 0x05    --> son0 and son2 are shorts; son3 is a char
113
114    example2:   byte  = 0x8d    --> inner node; son0, son2 and son3 are available
115                byte2 = 0x81    --> son0 is a int; son2 and son3 are shorts
116
117// example3 atm only if ARB_64 is set
118    example3:   byte  = 0x8d    --> inner node; son0, son2 and son3 are available
119                byte2 = 0x44    --> son2 is a long; son0 and son3 are ints
120
121/ ********************* inner nodesingle (1)    (stage3 only) *********************** /
122    byte                bit[7] = 1  bit[6] = 1
123                    bit[0-2]    base
124                    bit[3-5]    offset 0->1 1->3 2->4 3->5 ....
125
126
127/ ********************* chain (8-n +4) stage 1 *********************** /
128    byte =64/65         bit[7] = 0, bit[6] = 1  bit[5] = 0
129    [PT_PNTR    father]     if main->mode
130    short/int   ref abs pos int if bit[0]
131    PT_PNTR     firstelem
132
133    / **** chain elems *** /
134        PT_PNTR     next element
135        short/int   name
136                if bit[15] then integer
137                -1 not allowed
138        short/int   rel pos
139                if bit[15] then integer
140        short/int   apos short if bit[15] = 0]
141]
142
143
144/ ********************* chain (8-n +4) stage 2/3 *********************** /
145
146    byte =64/65         bit[7] = 0, bit[6] = 1  bit[5] = 0
147    [PT_PNTR    father]     if main->mode
148    short/int   ref abs pos int if bit[0]
149[   char/short/int      rel name [ to last name eg. rel names 10 30 20 50 -> abs names = 10 40 60 110
150                if bit[7] then short
151                if bit[7] and bit[6] then integer
152                -1 not allowed
153    short/int       rel pos
154                if bit[15] -> the next bytes are the apos else use ref_abs_pos
155                if bit[14] -> this(==rel_pos) is integer
156    [short/int]     [apos short if bit[15] = 0]
157]
158    char -1         end flag
159
160only few functions can be used, when the tree is reloaded (stage 3):
161    PT_read_type
162    PT_read_son
163    PT_read_xpos
164    PT_read_name
165    PT_forwhole_chain
166*/
167#endif
168
169#define IS_SINGLE_BRANCH_NODE 0x40
170#ifdef ARB_64
171# define INT_SONS              0x80
172# define LONG_SONS             0x40
173#else
174# define LONG_SONS             0x80
175#endif
176
177// -----------------------------------------------
178//      Get the size of entries (stage 1) only
179
180#define PT_EMPTY_LEAF_SIZE       (1+sizeof(PT_PNTR)+6) // tag father name rel apos
181#define PT_LEAF_SIZE(leaf)       (1+sizeof(PT_PNTR)+6+2*PT_count_bits[3][leaf->flags])
182#define PT_EMPTY_CHAIN_SIZE      (1+sizeof(PT_PNTR)+2+sizeof(PT_PNTR)) // tag father apos first_elem
183#define PT_EMPTY_NODE_SIZE       (1+sizeof(PT_PNTR)) // tag father
184#define PT_NODE_COUNT_SONS(leaf) PT_count_bits[3][leaf->flags];
185#define PT_NODE_SIZE(node, size) size = PT_EMPTY_NODE_SIZE + sizeof(PT_PNTR)*PT_count_bits[PT_B_MAX][node->flags]
186
187// ----------------------------
188//      Read and write type
189
190#define PT_GET_TYPE(pt)     (PTM.flag_2_type[pt->flags])
191#define PT_SET_TYPE(pt, i, j) (pt->flags = (i<<6)+j)
192
193// ----------------------
194//      bswap for OSX
195
196#if defined(DARWIN)
197
198static inline unsigned short bswap_16(unsigned short x) {
199    return (x>>8) | (x<<8);
200}
201
202static inline unsigned int bswap_32(unsigned int x) {
203    return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16));
204}
205
206static inline unsigned long long bswap_64(unsigned long long x) {
207    return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32));
208}
209
210#else
211#include <byteswap.h>
212#endif // DARWIN
213
214// ------------------------------------------------------------
215// Note about bswap as used here:
216//
217// * MSB has to be at start of written byte-chain, cause the most significant bit is used to separate
218//   between INT and SHORT
219//
220// * To use PT-server on a big-endian system it has to be skipped
221
222// ---------------------------------
223//      Read and write to memory
224
225#define PT_READ_INT(ptr, my_int_i)                                      \
226    do {                                                                \
227        unsigned int *uiptr = (unsigned int*)(ptr);                     \
228        (my_int_i)=(unsigned int)bswap_32(*uiptr);                      \
229    } while (0)
230
231#define PT_WRITE_INT(ptr, my_int_i)                                     \
232    do {                                                                \
233        unsigned int *uiptr = (unsigned int*)(ptr);                     \
234        *uiptr              = bswap_32((unsigned int)(my_int_i));       \
235    } while (0)
236
237#define PT_READ_SHORT(ptr, my_int_i)                    \
238    do {                                                \
239        (my_int_i) = bswap_16(*(unsigned short*)(ptr)); \
240    } while (0)
241
242#define PT_WRITE_SHORT(ptr, my_int_i)                                   \
243    do {                                                                \
244        unsigned short *usptr = (unsigned short*)(ptr);                 \
245        *usptr                = bswap_16((unsigned short)(my_int_i));   \
246    } while (0)
247
248#define PT_WRITE_CHAR(ptr, my_int_i) do { *(unsigned char *)(ptr) = my_int_i; } while (0)
249
250#define PT_READ_CHAR(ptr, my_int_i) do { my_int_i = *(unsigned char *)(ptr); } while (0)
251
252
253
254#ifdef ARB_64
255
256COMPILE_ASSERT(sizeof(void*) == sizeof(unsigned long));
257
258# define PT_READ_PNTR(ptr, my_int_i)                            \
259    do {                                                        \
260        pt_assert(sizeof(my_int_i) == 8);                       \
261        unsigned long *ulptr = (unsigned long*)(ptr);           \
262        (my_int_i)           = (unsigned long)bswap_64(*ulptr); \
263    } while (0)
264
265
266# define PT_WRITE_PNTR(ptr, my_int_i)                                   \
267    do {                                                                \
268        unsigned long *ulptr = (unsigned long*)(ptr);                   \
269        *ulptr               = bswap_64((unsigned long)(my_int_i));     \
270    } while (0)
271
272
273#else
274// not ARB_64
275
276COMPILE_ASSERT(sizeof(void*) == sizeof(unsigned int));
277
278# define PT_READ_PNTR(ptr, my_int_i) PT_READ_INT(ptr, my_int_i)
279# define PT_WRITE_PNTR(ptr, my_int_i) PT_WRITE_INT(ptr, my_int_i)
280
281#endif
282
283
284
285#define PT_WRITE_NAT(ptr, i)                    \
286    do {                                        \
287        pt_assert(i >= 0);                      \
288        if (i >= 0x7FFE)                        \
289        {                                       \
290            PT_WRITE_INT(ptr, i|0x80000000);    \
291            ptr += sizeof(int);                 \
292        }                                       \
293        else                                    \
294        {                                       \
295            PT_WRITE_SHORT(ptr, i);             \
296            ptr += sizeof(short);               \
297        }                                       \
298    } while (0)
299
300#define PT_READ_NAT(ptr, i)                                             \
301    do {                                                                \
302        if (*ptr & 0x80) {                                              \
303            PT_READ_INT(ptr, i); ptr += sizeof(int); i &= 0x7fffffff;   \
304        }                                                               \
305        else {                                                          \
306            PT_READ_SHORT(ptr, i); ptr += sizeof(short);                \
307        }                                                               \
308    } while (0)
309
310
311inline const char *PT_READ_CHAIN_ENTRY(const char* ptr, int mainapos, int *name, int *apos, int *rpos) {
312    // Caution: 'name' has to be initialized before first call and shall not be modified between calls
313 
314    *apos = 0;
315    *rpos = 0;
316   
317    unsigned char *rcep = (unsigned char*)ptr;
318    unsigned int   rcei = (*rcep);
319
320    if (rcei==PT_CHAIN_END) {
321        *name = -1;
322        ptr++;
323    }
324    else {
325        if (rcei&0x80) {
326            if (rcei&0x40) {
327                PT_READ_INT(rcep, rcei); rcep+=4; rcei &= 0x3fffffff;
328            }
329            else {
330                PT_READ_SHORT(rcep, rcei); rcep+=2; rcei &= 0x3fff;
331            }
332        }
333        else {
334            rcei &= 0x7f; rcep++;
335        }
336        *name += rcei;
337        rcei   = (*rcep);
338
339        bool isapos = rcei&0x80;
340
341        if (rcei&0x40) {
342            PT_READ_INT(rcep, rcei); rcep+=4; rcei &= 0x3fffffff;
343        }
344        else {
345            PT_READ_SHORT(rcep, rcei); rcep+=2; rcei &= 0x3fff;
346        }
347        *rpos = (int)rcei;
348        if (isapos) {
349            rcei = (*rcep);
350            if (rcei&0x80) {
351                PT_READ_INT(rcep, rcei); rcep+=4; rcei &= 0x7fffffff;
352            }
353            else {
354                PT_READ_SHORT(rcep, rcei); rcep+=2; rcei &= 0x7fff;
355            }
356            *apos = (int)rcei;
357        }
358        else {
359            *apos = (int)mainapos;
360        }
361        ptr = (char *)rcep;
362    }
363
364    return ptr;
365}
366
367
368inline char *PT_WRITE_CHAIN_ENTRY(const char * const ptr, const int mainapos, int name, const int apos, const int rpos) { // stage 1
369    unsigned char *wcep = (unsigned char *)ptr;
370    int  isapos;
371    if (name < 0x7f) {      // write the name
372        *(wcep++) = name;
373    }
374    else if (name <0x3fff) {
375        name |= 0x8000;
376        PT_WRITE_SHORT(wcep, name);
377        wcep += 2;
378    }
379    else {
380        name |= 0xc0000000;
381        PT_WRITE_INT(wcep, name);
382        wcep += 4;
383    }
384
385    if (apos == mainapos) isapos = 0; else isapos = 0x80;
386
387    if (rpos < 0x3fff) {        // write the rpos
388           // 0x7fff, mit der rpos vorher verglichen wurde war zu gross
389        PT_WRITE_SHORT(wcep, rpos);
390        *wcep |= isapos;
391        wcep += 2;
392    }
393    else {
394        PT_WRITE_INT(wcep, rpos);
395        *wcep |= 0x40+isapos;
396        wcep += 4;
397    }
398    if (isapos) {           // write the apos
399        if (apos < 0x7fff) {
400            PT_WRITE_SHORT(wcep, apos);
401            wcep += 2;
402        }
403        else {
404            PT_WRITE_INT(wcep, apos);
405            *wcep |= 0x80;
406            wcep += 4;
407        }
408    }
409    return (char *)wcep;
410}
411// calculate the index of the pointer in a node
412
413inline POS_TREE *PT_read_son(POS_TREE *node, PT_BASES base)
414{
415    long  i;
416    UINT  sec;
417    UINT  offset;
418    PTM2 *ptmain = psg.ptmain;
419    if (ptmain->stage3) {       // stage 3  no father
420        if (node->flags & IS_SINGLE_BRANCH_NODE) {
421            if (base != (node->flags & 0x7)) return NULL;  // no son
422            i = (node->flags >> 3)&0x7;         // this son
423            if (!i) i = 1; else i+=2;           // offset mapping
424            pt_assert(i >= 0);
425            return (POS_TREE *)(((char *)node)-i);
426        }
427        if (!((1<<base) & node->flags)) return NULL;   // bit not set
428        sec = (uchar)node->data;    // read second byte for charshort/shortlong info
429        i = PT_count_bits[base][node->flags];
430        i += PT_count_bits[base][sec];
431#ifdef ARB_64
432        if (sec & LONG_SONS) {
433            if (sec & INT_SONS) {                                   // undefined -> error
434                GBK_terminate("Your pt-server search tree is corrupt! You can not use it anymore.\n"
435                              "Error: ((sec & LONG_SON) && (sec & INT_SONS)) == true\n"
436                              "       this combination of both flags is not implemented\n");
437            }
438            else {                                                // long/int
439#ifdef DEBUG
440                printf("Warning: A search tree of this size is not tested.\n");
441                printf("         (sec & LONG_SON) == true\n");
442#endif
443                offset = 4 * i;
444                if ((1<<base) & sec) {              // long
445                    COMPILE_ASSERT(sizeof(PT_PNTR) == 8); // 64-bit necessary
446                    PT_READ_PNTR((&node->data+1)+offset, i);
447                }
448                else {                                              // int
449                    PT_READ_INT((&node->data+1)+offset, i);
450                }
451            }
452
453        }
454        else {
455            if (sec & INT_SONS) {                                   // int/short
456                offset = i+i;
457                if ((1<<base) & sec) {                              // int
458                    PT_READ_INT((&node->data+1)+offset, i);
459                }
460                else {                                              // short
461                    PT_READ_SHORT((&node->data+1)+offset, i);
462                }
463            }
464            else {                                                  // short/char
465                offset = i;
466                if ((1<<base) & sec) {                              // short
467                    PT_READ_SHORT((&node->data+1)+offset, i);
468                }
469                else {                                              // char
470                    PT_READ_CHAR((&node->data+1)+offset, i);
471                }
472            }
473        }
474#else
475        if (sec & LONG_SONS) {
476            offset = i+i;
477            if ((1<<base) & sec) {
478                PT_READ_INT((&node->data+1)+offset, i);
479            }
480            else {
481                PT_READ_SHORT((&node->data+1)+offset, i);
482            }
483        }
484        else {
485            offset = i;
486            if ((1<<base) & sec) {
487                PT_READ_SHORT((&node->data+1)+offset, i);
488            }
489            else {
490                PT_READ_CHAR((&node->data+1)+offset, i);
491            }
492        }
493#endif
494        pt_assert(i >= 0);
495        return (POS_TREE *)(((char*)node)-i);
496
497    }
498    else {          // stage 1 or 2 ->father
499        if (!((1<<base) & node->flags)) return NULL;   // bit not set
500        base = (PT_BASES)PT_count_bits[base][node->flags];
501        PT_READ_PNTR((&node->data)+sizeof(PT_PNTR)*base+ptmain->mode, i);
502        return (POS_TREE *)(i+ptmain->data_start); // ptmain->data_start == 0x00 in stage 1
503    }
504}
505
506inline POS_TREE *PT_read_son_stage_1(POS_TREE *node, PT_BASES base) {
507    if (!((1<<base) & node->flags)) return NULL;   // bit not set
508    base = (PT_BASES)PT_count_bits[base][node->flags];
509    long i;
510    PT_READ_PNTR((&node->data)+sizeof(PT_PNTR)*base+psg.ptmain->mode, i);
511    return (POS_TREE *)(i+psg.ptmain->data_start); // psg.ptmain->data_start == 0x00 in stage 1
512}
513
514inline PT_NODE_TYPE PT_read_type(POS_TREE *node)
515{
516    return (PT_NODE_TYPE)PT_GET_TYPE(node);
517}
518
519struct DataLoc {
520    int name; // index into psg.data[], aka as species id
521    int apos;
522    int rpos; // position in data
523
524    void init(const char ** data, int pos) {
525        *data = PT_READ_CHAIN_ENTRY(*data, pos, &name, &apos, &rpos);
526    }
527    void init(POS_TREE *node) {
528        pt_assert(PT_read_type(node) == PT_NT_LEAF);
529        char *data = (&node->data)+psg.ptmain->mode;
530        if (node->flags&1) { PT_READ_INT(data, name); data += 4; } else { PT_READ_SHORT(data, name); data += 2; }
531        if (node->flags&2) { PT_READ_INT(data, rpos); data += 4; } else { PT_READ_SHORT(data, rpos); data += 2; }
532        if (node->flags&4) { PT_READ_INT(data, apos); data += 4; } else { PT_READ_SHORT(data, apos); data += 2; }
533
534        pt_assert(name >= 0);
535        pt_assert(apos >= 0);
536        pt_assert(rpos >= 0);
537    }
538
539    DataLoc(int name_, int apos_, int rpos_) : name(name_), apos(apos_), rpos(rpos_) {}
540    DataLoc(POS_TREE *pt) { init(pt); }
541    DataLoc(const char ** data, int pos) { name = 0; init(data, pos); }
542
543    const probe_input_data& get_pid() const { pt_assert(name >= 0 && name<psg.data_count); return psg.data[name]; }
544    const char *get_data() const { return get_pid().get_data(); }
545    PT_BASES operator[](int offset) const { return PT_BASES(get_data()[rpos+offset]); }
546
547    int restlength() const { return get_pid().get_size()-rpos; }
548    bool is_shorther_than(int offset) const { return offset >= restlength(); }
549
550#if defined(DEBUG)
551    void dump(FILE *fp) const {
552        fprintf(fp, "          apos=%6i  rpos=%6i  name=%6i='%s'\n", apos, rpos, name, psg.data[name].get_name());
553        fflush(fp);
554    }
555#endif
556};
557
558template<typename T>
559int PT_forwhole_chain(POS_TREE *node, T func) {
560    pt_assert(PT_read_type(node) == PT_NT_CHAIN);
561
562    const char *data = (&node->data) + psg.ptmain->mode;
563    int         pos;
564
565    if (node->flags&1) {
566        PT_READ_INT(data, pos);
567        data += 4;
568    }
569    else {
570        PT_READ_SHORT(data, pos);
571        data += 2;
572    }
573
574    int     error = 0;
575    DataLoc location(&data, pos);
576    while (location.name>=0) {
577        error = func(location);
578        if (error) break;
579        location.init(&data, pos);
580    }
581    return error;
582}
583
584template<typename T>
585int PT_withall_tips(POS_TREE *node, T func) {
586    // like PT_forwhole_chain, but also can handle leafs
587    PT_NODE_TYPE type = PT_read_type(node);
588    if (type == PT_NT_LEAF) {
589        return func(DataLoc(node));
590    }
591
592    pt_assert(type == PT_NT_CHAIN);
593    return PT_forwhole_chain(node, func);
594}
595
596#if defined(DEBUG)
597struct PTD_chain_print { int operator()(const DataLoc& loc) { loc.dump(stdout); return 0; } };
598#endif
599
600#else
601#error probe_tree.h included twice
602#endif // PROBE_TREE_H
Note: See TracBrowser for help on using the repository browser.