Skip to Navigation

BTree code

  1. /* Complete B-tree implementation
  2.  *
  3.  * Author: Remigiusz 'lRem' Modrzejewski <http://lrem.net/>
  4.  * Distributed under the terms of GNU GPL version 2, as found on:  
  5.  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  6.  */
  7.  
  8. #include <cstdio>
  9. #include <cerrno>
  10. #include <cassert>
  11. #include <queue>
  12. #include <map>
  13.  
  14. using namespace std;
  15.  
  16. #define DATAFILE "data"
  17. #define TREEFILE "index"
  18. #define MISCFILE "misc"
  19. #define NODESIZE 64
  20. #define RECORD_SIZE 15
  21. #define T 31
  22. #define HELP "Possible actions: (h)elp, (a)dd, (s)earch, (d)elete, (e)dit, \
  23.    (p)rint all, (q)uit\n"
  24.  
  25. struct record/*{{{*/
  26. {
  27.    int numbers_count,
  28.        numbers[RECORD_SIZE];
  29.  
  30.    void dump (void);
  31. };
  32. /*}}}*/
  33. class node/*{{{*/
  34. {
  35.    // Internals {{{
  36.    int n;
  37.    bool leaf;
  38.    int keys[NODESIZE],
  39.        sons[NODESIZE],
  40.        data[NODESIZE];
  41.    // }}}
  42.    public:
  43.    int offset,
  44.        father;
  45.    //{{{Methods - this is actual B-Tree implementation
  46.    void create(); // This is _not_ a constructor
  47.    pair<node*, int> search (int key); // Returns the data offset
  48.    void split(int index); // Parent is a field in node
  49.    void merge(node &source);
  50.    void insert(int key, int data);
  51.    void overflow(int key);
  52.    void remove(int key);
  53.    void search_dump (int key);
  54.    int dump (void);
  55.    void debug (void);
  56.    int validate (int bound);
  57.    //}}}
  58. } *tree, dummy;
  59. /*}}}*/
  60. class cache/*{{{*/
  61. {
  62.    // Internals {{{
  63.    struct entry
  64.    {
  65.       node data;
  66.       bool dirty;
  67.    };
  68.  
  69.    FILE *index,
  70.         *data,
  71.         *misc;
  72.    int next_new_data,
  73.        next_new;
  74.    queue<int> free_data;
  75.    queue<int> free_nodes;
  76.    map<int, entry> storage;
  77.    int next_free();
  78.    //}}}
  79.    public:
  80.    // Methods - everything that touches files {{{
  81.    cache();
  82.    ~cache();
  83.    void flush (void);
  84.    node& allocate (void);
  85.    node& read (int offset, int parent);
  86.    void write (int offset);
  87.    void free (node &n);
  88.    int allocate_record (void);
  89.    record& read_record (int offset);
  90.    void write_record (int offset, record &r);
  91.    void free_record (int offset);
  92.    //}}}
  93. } disk;
  94. /*}}}*/
  95. int main (void)/*{{{*/
  96. {
  97.    char choice = 'h';
  98.    int key, data;
  99.    record tmp;
  100.  
  101.    while(choice != 'q')
  102.    {
  103.       switch(choice)
  104.       {
  105.          case 'h':/*{{{*/
  106.             printf(HELP);
  107.             break;/*}}}*/
  108.          case 'a':/*{{{*/
  109.             printf("Key: ");
  110.             scanf("%d", &key);
  111.             printf("Numbers count: ");
  112.             scanf("%d", &tmp.numbers_count);
  113.             for(int i = 0; i < tmp.numbers_count; i++)
  114.             {
  115.                printf("Number %d: ", i);
  116.                scanf("%d", &tmp.numbers[i]);
  117.             }
  118.             data = disk.allocate_record();
  119.             disk.write_record(data, tmp);
  120.             tree->insert(key, data);
  121.             break;/*}}}*/
  122.          case 'e':/*{{{*/
  123.             printf("Key: ");
  124.             scanf("%d", &key);
  125.             if(tree->search(key).second == -1)
  126.                break;
  127.             tree->remove(key);
  128.             scanf("%d", &key);
  129.             printf("Numbers count: ");
  130.             scanf("%d", &tmp.numbers_count);
  131.             for(int i = 0; i < tmp.numbers_count; i++)
  132.             {
  133.                printf("Number %d: ", i);
  134.                scanf("%d", &tmp.numbers[i]);
  135.             }
  136.             data = disk.allocate_record();
  137.             disk.write_record(data, tmp);
  138.             tree->insert(key, data);
  139.             break;/*}}}*/
  140.          case 'p':/*{{{*/
  141.             printf("Total records: %d\t",tree->dump());
  142.             break;/*}}}*/
  143.          case 's':/*{{{*/
  144.             printf("Key: ");
  145.             scanf("%d", &key);
  146.             tree->search_dump(key);
  147.             break;/*}}}*/
  148.          case 'd':/*{{{*/
  149.             printf("Key: ");
  150.             scanf("%d", &key);
  151.             tree->remove(key);
  152.             break;/*}}}*/
  153.          default:/*{{{*/
  154.             printf("Unknown choice\n");/*}}}*/
  155.       }
  156. #ifdef VERBOSE
  157.       printf("VALIDATION BEGIN{{{\n");
  158.       tree->validate(-1);
  159.       printf("VALIDATION END}}}\n");
  160. #else
  161. #ifdef DEBUG
  162.       tree->validate(-1);
  163. #endif
  164. #endif
  165.       disk.flush();
  166.       printf("> ");
  167.       do
  168.          scanf("%c", &choice);
  169.       while(isspace(choice));
  170.    }
  171.    return 0;
  172. }
  173. /*}}}*/
  174. //{{{ Global functions
  175. void swap (int &a, int &b)
  176. {
  177.    int tmp = a;
  178.    a = b;
  179.    b = tmp;
  180. }
  181. //}}}
  182. //{{{ Methods of node
  183. void node::create()/*{{{*/
  184. {
  185.    leaf = true;
  186.    father = -1;
  187.    n = 0;
  188.    disk.write(offset);
  189. }
  190. /*}}}*/
  191. pair<node*, int> node::search (int key)/*{{{*/
  192. {
  193.    int i = 0;
  194.    while(i < n && keys[i] < key)
  195.       i++;
  196.    if(i <= n && keys[i] == key)
  197.       return make_pair(this, i);
  198.    if(leaf)
  199.       return make_pair(this, -1);
  200.    node &son = disk.read(sons[i], offset);
  201.    return son.search(key);
  202. }
  203. /*}}}*/
  204. void node::split(int index)/*{{{*/
  205. {
  206.    assert(n == 2*T-1);
  207.    // Make the new one similar to the old one
  208.    node &z = disk.allocate();
  209.    z.father = father;
  210.    z.leaf = leaf;
  211.    z.n = T-1;
  212.    // Move half of the keys to the new one
  213.    for(int j = T; j--; )
  214.    {
  215.       z.keys[j] = keys[j+T];
  216.       z.data[j] = data[j+T];
  217.    }
  218.    // If not leaf, move the subtrees
  219.    if(!leaf)
  220.       for(int j = T+1; j--; )
  221.          z.sons[j] = sons[j+T];
  222.    n = T-1;
  223.  
  224.    // Move the last key from old son to father
  225.    // Note that the subtree stays where it was - it will be new post-n
  226.    node &x = disk.read(father, -1);
  227.    for(int j = x.n; j > index; j--)
  228.    {
  229.       x.sons[j+1] = x.sons[j];
  230.       x.keys[j+1] = x.keys[j];
  231.       x.data[j+1] = x.data[j];
  232.    }
  233.    x.keys[index+1] = x.keys[index];
  234.    x.data[index+1] = x.data[index];
  235.    x.sons[index+1] = z.offset;
  236.    x.keys[index] = keys[T-1];
  237.    x.data[index] = data[T-1];
  238.    x.n++;
  239.  
  240.    disk.write(offset);
  241.    disk.write(x.offset);
  242.    disk.write(z.offset);
  243. }
  244. /*}}}*/
  245. void node::merge(node &source)/*{{{*/
  246. {
  247.    assert(source.n == T-1 && n == T);
  248.    assert(offset != source.offset);
  249.    assert(father == source.father);
  250.    assert(leaf == source.leaf);
  251.    //Unasserted assumption - we lack rightmost son
  252.    for(int i = 0; i < n; i++)
  253.    {
  254.       keys[n+i] = source.keys[i];
  255.       data[n+i] = source.data[i];
  256.       sons[n+i] = source.sons[i];
  257.    }
  258.    n=2*T-1;
  259. }
  260. /*}}}*/
  261. void node::insert(int key, int new_data)/*{{{*/
  262. {
  263. #ifdef DEBUG
  264.    printf("node::insert(%d, %d)\n", key, new_data);
  265. #endif
  266.    pair<node*, int> x = search(key);
  267.    if(x.second == -1)
  268.    {
  269.       assert(x.first->leaf);
  270.       int i = x.first->n;
  271.       for(; i && x.first->keys[i-1] > key; i--)
  272.       {
  273.          x.first->keys[i] = x.first->keys[i-1];
  274.          x.first->data[i] = x.first->data[i-1];
  275.       }
  276.       x.first->keys[i] = key;
  277.       x.first->data[i] = new_data;
  278.       x.first->n++;
  279.       disk.write(x.first->offset);
  280.       if(x.first->n==2*T-1)
  281.          x.first->overflow(key);
  282.    }
  283.    else
  284.    {
  285.       disk.free_record(new_data);
  286.    }
  287.  
  288. }
  289. /*}}}*/
  290. void node::overflow(int key)/*{{{*/
  291. {
  292.    if(this == tree)
  293.    {
  294. #ifdef DEBUG
  295.       printf("node::overflow(%d) - root\n", key);
  296. #endif
  297.       node &s = disk.allocate();
  298.       s.leaf = false;
  299.       s.n = 0;
  300.       s.father = -1;
  301.       s.sons[0] = tree->offset;
  302.       tree->father = s.offset;
  303.       tree->split(0);
  304.       disk.write(tree->offset);
  305.       disk.write(s.offset);
  306.       tree = &s;
  307.    }
  308.    else
  309.    {
  310. #ifdef DEBUG
  311.       printf("node::overflow(%d) - nonroot\n", key);
  312. #endif
  313.       node &parent = disk.read(father, -1);
  314.       int i = parent.n-1;
  315.       while(i>=0 && parent.keys[i] > key)
  316.          i--;
  317.       i++;
  318.       node &y = i > 0 ? disk.read(parent.sons[i-1], -1) : dummy;
  319.       node &z = i < parent.n ? disk.read(parent.sons[i+1], -1): dummy;
  320.       if((y.n != dummy.n) && (y.n < 2*(T-1)))
  321.       {
  322.          // Append a key to y
  323.          y.keys[y.n] = parent.keys[i-1];
  324.          y.data[y.n] = parent.data[i-1];
  325.          // Move the orphaned subtree where it belongs
  326.          y.sons[y.n] = sons[0];
  327.          // Move a key from this into that place
  328.          parent.keys[i-1] = keys[0];
  329.          parent.data[i-1] = data[0];
  330.          for(int j = 0; j < n; j++)
  331.          {
  332.             keys[j] = keys[j+1];
  333.             data[j] = data[j+1];
  334.             sons[j] = sons[j+1];
  335.          }
  336.          n--;
  337.          // Write changes
  338.          disk.write(offset);
  339.          disk.write(y.offset);
  340.          disk.write(parent.offset);
  341.       }
  342.       else if((z.n != dummy.n) && (z.n < 2*(T-1)))
  343.       {
  344.          // Preppend a key to z
  345.          z.n++;
  346.          for(int j = z.n; j; j--)
  347.          {
  348.             z.keys[j] = z.keys[j-1];
  349.             z.data[j] = z.data[j-1];
  350.             z.sons[j] = z.sons[j-1];
  351.          }
  352.          z.keys[0] = parent.keys[i];
  353.          z.data[0] = parent.data[i];
  354.          // Move a key from this into that place
  355.          n--;
  356.          parent.keys[i] = keys[n];
  357.          parent.data[i] = data[n];
  358.          // Move the orphaned subtree where it belongs
  359.          z.sons[0] = sons[n+1];
  360.          // Write changes
  361.          disk.write(offset);
  362.          disk.write(z.offset);
  363.          disk.write(parent.offset);
  364.       }
  365.       else
  366.          split(i);
  367.       if(parent.n == 2*T-1)
  368.          parent.overflow(key);
  369.    }
  370. }
  371. /*}}}*/
  372. #define checkroot()/*{{{*/\
  373. {\
  374.    if(n == 0)\
  375.    {\
  376.       printf("Root going down\n");\
  377.       assert(this == tree);\
  378.       node &son = disk.read(sons[0], offset);\
  379.       son.father = -1;\
  380.       tree = &son;\
  381.       disk.free(*this);\
  382.       disk.write(son.offset);\
  383.       need_write = false;\
  384.    }\
  385. }
  386. /*}}}*/
  387. void node::remove(int key)/*{{{*/
  388. {
  389.    int index = 0;
  390.    bool need_write = true;
  391.    while(index < n && keys[index] < key)
  392.       index++;
  393.    if(leaf)
  394.    { // 1. Leaf/*{{{*/
  395. #ifdef DEBUG
  396.       printf("node::remove 1 (%d)\n", key);
  397. #endif
  398.       // Simply delete k from x
  399.       if(index < n && keys[index] == key)
  400.       {
  401.          n--;
  402.          while(index < n)
  403.          {
  404.             disk.free_record(data[index]);
  405.             keys[index] = keys[index+1];
  406.             data[index] = data[index+1];
  407.             index++;
  408.          }      
  409.       }
  410.    }/*}}}*/
  411.    else if(index < n && keys[index] == key)
  412.    { // 2. Internal and k is in x/*{{{*/
  413.       node &y = disk.read(sons[index], offset);
  414.       node &z = disk.read(sons[index+1], offset);
  415.       if(y.n >= T)
  416.       { // 2a/*{{{*/
  417. #ifdef DEBUG
  418.          printf("node::remove 2a\n");
  419. #endif
  420.          // Swap with predecesor
  421.          node *current = &y;
  422.          while(!current->leaf)
  423.             current = &disk.read(current->sons[current->n],
  424.                   offset);
  425.          swap(keys[index], current->keys[current->n - 1]);
  426.          swap(data[index], current->data[current->n - 1]);
  427.          // Note this does not hurt reads count nor asymptotical
  428.          // computing time, as _all_ nodes just iterated will be
  429.          // subject to recursion.
  430.  
  431.          // Recursively delete
  432.          checkroot();
  433.          y.remove(key);
  434.       }/*}}}*/
  435.       else if(z.n >= T)
  436.       { // 2b/*{{{*/
  437. #ifdef DEBUG
  438.          printf("node::remove 2b\n");
  439. #endif
  440.          // 2a turned around
  441.          node *current = &z;
  442.          while(!current->leaf)
  443.             current = &disk.read(current->sons[0], offset);
  444.          swap(keys[index], current->keys[0]);
  445.          swap(data[index], current->data[0]);
  446.  
  447.          checkroot();
  448.          z.remove(key);
  449.       }/*}}}*/
  450.       else
  451.       { // 2c - both sons have T-1 keys/*{{{*/
  452. #ifdef DEBUG
  453.          printf("node::remove 2c\n");
  454. #endif
  455.          // Append k to y
  456.          y.keys[y.n] = keys[index];
  457.          y.data[y.n] = data[index];
  458.          y.n++;
  459.          // Remove k from x
  460.          n--;
  461.          while(index <= n)
  462.          {
  463.             keys[index] = keys[index+1];
  464.             data[index] = data[index+1];
  465.             sons[index] = sons[index+1];
  466.             index++;
  467.          }
  468.          // Append z to y
  469.          y.merge(z);
  470.          // Get rid of z
  471.          disk.free(z);
  472.          // Recurse
  473.          checkroot();
  474.          y.remove(key);
  475.       }/*}}}*/
  476.    }/*}}}*/
  477.    else
  478.    { // 3. Internal and k is not in x/*{{{*/
  479.       node &son = disk.read(sons[index], offset);
  480.       if(son.n >= T)
  481.       {
  482. #ifdef DEBUG
  483.          printf("node::remove 3 void\n");
  484. #endif
  485.          need_write = false;
  486.          checkroot();
  487.          son.remove(key);
  488.       }
  489.       else
  490.       {
  491.          node &y = index > 0 ? disk.read(sons[index-1], offset)
  492.             : dummy;
  493.          node &z = index < n ? disk.read(sons[index+1], offset)
  494.             : dummy;
  495.          if(y.n >= T)
  496.          { // 3a - borrow from left sibling/*{{{*/
  497. #ifdef DEBUG
  498.             printf("node::remove 3a\n");
  499. #endif
  500.             // Preppend a key to the son
  501.             son.n++;
  502.             for(int j = son.n; j; j--)
  503.             {
  504.                son.keys[j] = son.keys[j-1];
  505.                son.data[j] = son.data[j-1];
  506.                son.sons[j] = son.sons[j-1];
  507.             }
  508.             son.keys[0] = keys[index-1];
  509.             son.data[0] = data[index-1];
  510.             // Move a key from sibling into that place
  511.             y.n--;
  512.             keys[index-1] = y.keys[y.n];
  513.             data[index-1] = y.data[y.n];
  514.             // Write changes
  515.             disk.write(son.offset);
  516.             disk.write(y.offset);
  517.             // Move the orphaned subtree where it belongs
  518.             son.sons[0] = y.sons[y.n+1];
  519.             checkroot();
  520.             son.remove(key);
  521.          }/*}}}*/
  522.          else if(z.n >= T)
  523.          { // 3a - borrow from right sibling/*{{{*/
  524. #ifdef DEBUG
  525.             printf("node::remove 3ar\n");
  526. #endif
  527.             // Append a key to the son
  528.             son.keys[son.n] = keys[index];
  529.             son.data[son.n] = data[index];
  530.             son.n++;
  531.             // Move the orphaned subtree where it belongs
  532.             son.sons[son.n] = z.sons[0];
  533.             // Move a key from sibling into that place
  534.             keys[index] = z.keys[0];
  535.             data[index] = z.data[0];
  536.             for(int j = 0; j < z.n; j++)
  537.             {
  538.                z.keys[j] = z.keys[j+1];
  539.                z.data[j] = z.data[j+1];
  540.                z.sons[j] = z.sons[j+1];
  541.             }
  542.             z.n--;
  543.             // Write changes
  544.             disk.write(son.offset);
  545.             disk.write(z.offset);
  546.             checkroot();
  547.             son.remove(key);
  548.          }/*}}}*/
  549.          else if (index > 0)
  550.          { // 3b - merge with left sibling/*{{{*/
  551. #ifdef DEBUG
  552.             printf("node::remove 3b\n");
  553. #endif
  554.             // Append i-1 to y
  555.             y.keys[y.n] = keys[index-1];
  556.             y.data[y.n] = data[index-1];
  557.             y.n++;
  558.             // Append son to y
  559.             y.merge(son);
  560.             // Get rid of son
  561.             disk.write(y.offset);
  562.             disk.free(son);
  563.             // Remove i-1 from x
  564.             n--;
  565.             keys[index-1] = keys[index];
  566.             data[index-1] = data[index];
  567.             while(index <= n)
  568.             {
  569.                keys[index] = keys[index+1];
  570.                sons[index] = sons[index+1];
  571.                data[index] = data[index+1];
  572.                index++;
  573.             }
  574.             // Recurse
  575.             checkroot();
  576.             y.remove(key);
  577.          }/*}}}*/
  578.          else
  579.          { // 3b - merge with right sibling/*{{{*/
  580. #ifdef DEBUG
  581.             printf("node::remove 3br\n");
  582. #endif
  583.             // Append i to son
  584.             son.keys[son.n] = keys[index];
  585.             son.data[son.n] = data[index];
  586.             son.n++;
  587.             // Append z to son
  588.             son.merge(z);
  589.             // Get rid of z
  590.             disk.write(son.offset);
  591.             disk.free(z);
  592.             // Remove i from x
  593.             n--;
  594.             //We've removed the right son...
  595.             sons[index+1] = sons[index];
  596.             while(index <= n)
  597.             {
  598.                keys[index] = keys[index+1];
  599.                sons[index] = sons[index+1];
  600.                data[index] = data[index+1];
  601.                index++;
  602.             }
  603.             // Recurse
  604.             checkroot();
  605.             son.remove(key);
  606.          }/*}}}*/
  607.       }
  608.    }/*}}}*/
  609.    if(need_write)
  610.       disk.write(offset);
  611. }
  612. /*}}}*/
  613. void node::search_dump (int key)/*{{{*/
  614. {
  615.    pair<node*, int> x = search(key);
  616.    if(x.second >= 0)
  617.    {
  618.       record &r = disk.read_record(x.first->data[x.second]);
  619.       r.dump();
  620.    }
  621.    else
  622.    {
  623.       printf("NOT FOUND\n");
  624.    }
  625. }
  626. /*}}}*/
  627. int node::dump (void)/*{{{*/
  628. {
  629.    int count = 0;
  630.    for(int i = 0; i <= n; i++)
  631.    {
  632.       if(!leaf)
  633.       {
  634.          node &n = disk.read(sons[i], offset);
  635.          count += n.dump();
  636.       }
  637.       printf("%d: ", keys[i]);
  638.       record &r = disk.read_record(data[i]);
  639.       r.dump();
  640.    }
  641.    if(!leaf)
  642.    {
  643.       node &last = disk.read(sons[n], offset);
  644.       count += last.dump();
  645.    }
  646.    return count + n;
  647. }
  648. /*}}}*/
  649. void node::debug (void)/*{{{*/
  650. {
  651.    printf("offset: %d\tfather: %d\tleaf: %s\tn: %d\n",
  652.          offset, father, leaf ? "true" : "false", n);
  653.    printf("keys:\t");
  654.    for(int i = 0; i < n; i++)
  655.       printf("%d\t", keys[i]);
  656.    printf("\n");
  657.    printf("data:\t");
  658.    for(int i = 0; i < n; i++)
  659.       printf("%d\t", data[i]);
  660.    printf("\n");
  661.    if(!leaf)
  662.    {
  663.       printf("sons:\t");
  664.       for(int i = 0; i < n; i++)
  665.          printf("%d\t", sons[i]);
  666.       printf("%d", sons[n]);
  667.       printf("\n");
  668.    }
  669. }
  670. /*}}}*/
  671. int node::validate (int bound)/*{{{*/
  672. {
  673. #ifdef VERBOSE
  674.    debug();
  675. #endif
  676.    assert(n < 2*T);
  677.    if(leaf)
  678.    {
  679.       for(int i = 0; i < n; i++)
  680.       {
  681.          assert(bound < keys[i]);
  682.          bound = keys[i];
  683.       }
  684.    }
  685.    else
  686.    {
  687.       for(int i = 0; i < n; i++)
  688.       {
  689.          node &son = disk.read(sons[i], offset);
  690.          assert(son.offset == sons[i]);
  691.          assert(son.father == offset);
  692.          bound = son.validate(bound);
  693.          assert(bound < keys[i]);
  694.          bound = keys[i];
  695.       }
  696.       node &son = disk.read(sons[n], offset);
  697.       assert(son.offset == sons[n]);
  698.       assert(son.father == offset);
  699.       bound = son.validate(bound);
  700.    }
  701.    return bound;
  702. }
  703. /*}}}*/
  704. //}}}
  705. //{{{ Methods of cache
  706. cache::cache()/*{{{*/
  707. {
  708.    misc = fopen(MISCFILE, "rb+");
  709.    if(!misc)
  710.    {
  711.       assert(errno == ENOENT);
  712.       printf("Files not found, creating empty structures!\n");
  713.       misc = fopen(MISCFILE, "wb+");
  714.       data = fopen(DATAFILE, "wb+");
  715.       index = fopen(TREEFILE, "wb+");
  716.       //Tadam...
  717.       tree = &(allocate());
  718.       tree->create();
  719.    }
  720.    else
  721.    {
  722.       data = fopen(DATAFILE, "rb+");
  723.       assert(data);
  724.       index = fopen(TREEFILE, "rb+");
  725.       assert(index);
  726.       // Read metadata
  727.       int root;
  728.       fread(&root, sizeof(int), 1, misc);
  729.       fread(&next_new, sizeof(int), 1, misc);
  730.       fread(&next_new_data, sizeof(int), 1, misc);
  731.       int tmp = 0;
  732.       fread(&tmp, sizeof(int), 1, misc);
  733.       while(tmp>=0)
  734.       {
  735.          free_nodes.push(tmp);
  736.          fread(&tmp, sizeof(int), 1, misc);
  737.       }
  738.       fread(&tmp, sizeof(int), 1, misc);
  739.       while(tmp>=0)
  740.       {
  741.          free_data.push(tmp);
  742.          fread(&tmp, sizeof(int), 1, misc);
  743.       }
  744.       // Read the root
  745.       tree = &(read(root, -1));
  746.    }
  747. }
  748. /*}}}*/
  749. cache::~cache()/*{{{*//*{{{*/
  750. {
  751.    // Just in case, flush the index
  752.    flush();
  753.    fclose(index);
  754.    // Records are not cached for writing
  755.    fclose(data);
  756.    // Metadata is flushed only in here
  757.    rewind(misc);
  758.    fwrite(&tree->offset, sizeof(int), 1, misc);
  759.    fwrite(&next_new, sizeof(int), 1, misc);
  760.    fwrite(&next_new_data, sizeof(int), 1, misc);
  761.    int tmp;
  762.    while(!free_nodes.empty())
  763.    {
  764.       tmp = free_nodes.front();
  765.       free_nodes.pop();
  766.       fwrite(&tmp, sizeof(int), 1, misc);
  767.    }
  768.    tmp = -1;
  769.    fwrite(&tmp, sizeof(int), 1, misc);
  770.    while(!free_data.empty())
  771.    {
  772.       tmp = free_data.front();
  773.       free_data.pop();
  774.       fwrite(&tmp, sizeof(int), 1, misc);
  775.    }
  776.    tmp = -1;
  777.    fwrite(&tmp, sizeof(int), 1, misc);
  778.    fclose(misc);
  779. }
  780. /*}}}*/
  781. void cache::flush (void)/*{{{*/
  782. {
  783.    int writes = 0;
  784.    for(map<int, entry>::iterator it = storage.begin(); it!=storage.end();
  785.          it++)
  786.       if(it->second.dirty)
  787.       {
  788.          assert(it->second.data.offset == it->first);
  789.          fseek(index, it->second.data.offset * sizeof(node),
  790.                SEEK_SET);
  791.          fwrite(&(it->second.data), sizeof(node), 1, index);
  792.          writes++;
  793.       }
  794.    printf("Total reads: %lu\tTotal writes: %d\n",storage.size()-1, writes);
  795.    // Keep the root
  796.    entry tmp;
  797.    tmp.data = *tree;
  798.    tmp.dirty = false;
  799.    storage.clear();
  800.    tree = &(storage.insert(make_pair(tmp.data.offset, tmp)).first//Iterator
  801.          ->second.data);
  802.  
  803. }
  804. /*}}}*/
  805. int cache::next_free (void)/*{{{*/
  806. {
  807.    if(free_nodes.empty())
  808.       return next_new++;
  809.    else
  810.    {
  811.       int tmp = free_nodes.front();
  812.       free_nodes.pop();
  813.       return tmp;
  814.    }
  815. }
  816. /*}}}*/
  817. node& cache::allocate ()/*{{{*/
  818. {
  819.    entry tmp;
  820.    tmp.dirty = true;
  821.    tmp.data.offset = next_free();
  822.    map<int, entry>::iterator it =
  823.       storage.insert(make_pair(tmp.data.offset, tmp)).first;
  824.    return it->second.data;
  825. }
  826. /*}}}*//*}}}*/
  827. node& cache::read (int offset, int parent)/*{{{*/
  828. {
  829.    map<int, entry>::iterator it = storage.find(offset);
  830.    if(it != storage.end())
  831.    {
  832.       if(parent >= 0)
  833.          it->second.data.father = parent;
  834.       return it->second.data;
  835.    }
  836.    entry tmp;
  837.    tmp.dirty = false;
  838.    fseek(index, offset * sizeof(node), SEEK_SET);
  839.    fread(&tmp.data, sizeof(node), 1, index);
  840.    if(parent >= 0)
  841.       tmp.data.father = parent;
  842.    assert(offset == tmp.data.offset);
  843.    it = storage.insert(make_pair(tmp.data.offset, tmp)).first;
  844.    return it->second.data;
  845. }
  846. /*}}}*/
  847. void cache::write (int offset)/*{{{*/
  848. {
  849.    assert(storage.count(offset));
  850. #ifdef DEBUG
  851.    if(offset == tree->offset)
  852.    {
  853.       printf("Writing root node, contents:\n");
  854.       tree->debug();
  855.    }
  856.    else
  857.    {
  858.       printf("Writing non-root node, contents:\n");
  859.       storage[offset].data.debug();
  860.    }
  861. #endif
  862.    storage[offset].dirty = true;
  863. }
  864. /*}}}*/
  865. void cache::free (node &n)/*{{{*/
  866. {
  867.    free_nodes.push(n.offset);
  868. }
  869. /*}}}*/
  870. int cache::allocate_record (void)/*{{{*/
  871. {
  872.    if(free_data.empty())
  873.       return next_new_data++;
  874.    else
  875.    {
  876.       int tmp = free_data.front();
  877.       free_data.pop();
  878.       return tmp;
  879.    }
  880. }
  881. /*}}}*/
  882. record& cache::read_record (int offset)/*{{{*/
  883. {
  884.    //Unasserted assumption - there is only one record in use at any time
  885.    static record r;
  886.    fseek(data, offset * sizeof(record), SEEK_SET);
  887.    fread(&r, sizeof(record), 1, data);
  888.    return r;
  889. }
  890. /*}}}*/
  891. void cache::write_record (int offset, record &r)/*{{{*/
  892. {
  893.    fseek(data, offset * sizeof(record), SEEK_SET);
  894.    fwrite(&r, sizeof(record), 1, data);
  895. }
  896. /*}}}*/
  897. void cache::free_record (int offset)/*{{{*/
  898. {
  899.    free_data.push(offset);
  900. }
  901. /*}}}*/
  902. //}}}
  903. //{{{ Methods of record
  904. void record::dump (void)
  905. {
  906.    for(int i = 0; i < numbers_count; i++)
  907.       printf("%d ", numbers[i]);
  908.    printf("\n");
  909. }
  910. //}}}