/[MITgcm]/mitgcm.org/devel/buildweb/pkg/swish-e/src/btree.c
ViewVC logotype

Annotation of /mitgcm.org/devel/buildweb/pkg/swish-e/src/btree.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1.1.1 - (hide annotations) (download) (vendor branch)
Fri Sep 20 19:47:29 2002 UTC (22 years, 10 months ago) by adcroft
Branch: Import, MAIN
CVS Tags: baseline, HEAD
Changes since 1.1: +0 -0 lines
File MIME type: text/plain
Importing web-site building process.

1 adcroft 1.1 #include <stdio.h>
2     #include <stdlib.h>
3     #include <string.h>
4    
5     #include "swish.h"
6     #include "string.h"
7     #include "compress.h"
8    
9     /*
10     #define STANDALONE
11     #define DEBUG
12     */
13    
14     #ifdef STANDALONE
15     /* Compress a number and writes it to a buffer */
16     /* buffer must be previously allocated */
17     /* returns the incrmented buffer pointer after storing the compressed number in it */
18     unsigned char *compress3(int num, unsigned char *buffer)
19     {
20     int _i = 0,
21     _r = num;
22     unsigned char _s[MAXINTCOMPSIZE];
23    
24     while (_r)
25     {
26     _s[_i++] = _r & 127;
27     _r >>= 7;
28     }
29     while (--_i >= 0)
30     *buffer++ = (_s[_i] | (_i ? 128 : 0));
31    
32     return buffer;
33     }
34    
35     /* same routine but this works with a memory forward buffer instead of file */
36     /* it also increases the buffer pointer */
37     int uncompress2(unsigned char **buffer)
38     {
39     int _c;
40     int num = 0;
41     unsigned char *p = *buffer;
42    
43     do
44     {
45     _c = (int) ((unsigned char) *p++);
46     num <<= 7;
47     num |= _c & 127;
48     if (!num)
49     break;
50     }
51     while (_c & 128);
52    
53     *buffer = p;
54     return num;
55     }
56    
57    
58     /* Rourtines to make long integers portable */
59     unsigned long PACKLONG(unsigned long num)
60     {
61     unsigned long _i = 0L;
62     unsigned char *_s;
63    
64     if (num)
65     {
66     _s = (unsigned char *) &_i;
67     _s[0] = (unsigned char) ((num >> 24) & 0xFF);
68     _s[1] = (unsigned char) ((num >> 16) & 0xFF);
69     _s[2] = (unsigned char) ((num >> 8) & 0xFF);
70     _s[3] = (unsigned char) (num & 0xFF);
71     return _i;
72     }
73     return num;
74     }
75    
76    
77     unsigned long UNPACKLONG(unsigned long num)
78     {
79     unsigned char *_s = (unsigned char *) &num;
80    
81     return (_s[0] << 24) + (_s[1] << 16) + (_s[2] << 8) + _s[3];
82     }
83    
84    
85     char *emalloc(unsigned int size)
86     {
87     return malloc(size);
88     }
89    
90     void efree(void *p)
91     {
92     free(p);
93     }
94    
95    
96     #else
97    
98     #include "mem.h"
99    
100     unsigned long PACKLONG(unsigned long num);
101     unsigned long UNPACKLONG(unsigned long num);
102     unsigned char *compress3(int num, unsigned char *buffer);
103     int uncompress2(unsigned char **buffer);
104    
105     #endif /* STANDALONE */
106    
107    
108     #include "btree.h"
109    
110    
111     /* A BTREE page cannot be smaller than BTREE_MinPageSize */
112     #define BTREE_MinPageSize 4096
113    
114     /* A BTREE page can be greater than BTREE_MaxPageSize */
115     #define BTREE_MaxPageSize 65536
116    
117     #define SizeInt32 4
118     #define SizeInt16 2
119    
120    
121     /* Round in BTREE_MinPageSize */
122     #define BTREE_RoundPageSize(n) (((n) + BTREE_MinPageSize - 1) & (~(BTREE_MinPageSize - 1)))
123    
124     #define BTREE_PageHeaderSize (6 * SizeInt32)
125    
126     #define BTREE_PageData(pg) ((pg)->data + BTREE_PageHeaderSize)
127     #define BTREE_EndData(pg) ((pg)->data + (pg)->data_end)
128     #define BTREE_KeyIndexOffset(data,i) (data + BTREE_PageHeaderSize + (i) * SizeInt16)
129     #define BTREE_KeyDataOffset(pg,i) ((*(BTREE_KeyIndexOffset((pg->data),(i))) <<8) + *(BTREE_KeyIndexOffset((pg->data),(i)) + 1))
130     #define BTREE_KeyData(pg,i) ((pg)->data + BTREE_KeyDataOffset((pg),(i)))
131    
132     #define BTREE_SetNextPage(pg,num) ( *(int *)((pg)->data + 0 * SizeInt32) = PACKLONG(num))
133     #define BTREE_SetPrevPage(pg,num) ( *(int *)((pg)->data + 1 * SizeInt32) = PACKLONG(num))
134     #define BTREE_SetSize(pg,num) ( *(int *)((pg)->data + 2 * SizeInt32) = PACKLONG(num))
135     #define BTREE_SetNumKeys(pg,num) ( *(int *)((pg)->data + 3 * SizeInt32) = PACKLONG(num))
136     #define BTREE_SetFlags(pg,num) ( *(int *)((pg)->data + 4 * SizeInt32) = PACKLONG(num))
137     #define BTREE_SetDataEnd(pg,num) ( *(int *)((pg)->data + 5 * SizeInt32) = PACKLONG(num))
138    
139     #define BTREE_GetNextPage(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 0 * SizeInt32)))
140     #define BTREE_GetPrevPage(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 1 * SizeInt32)))
141     #define BTREE_GetSize(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 2 * SizeInt32)))
142     #define BTREE_GetNumKeys(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 3 * SizeInt32)))
143     #define BTREE_GetFlags(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 4 * SizeInt32)))
144     #define BTREE_GetDataEnd(pg,num) ( (num) = UNPACKLONG(*(int *)((pg)->data + 5 * SizeInt32)))
145    
146     /* Flags */
147     #define BTREE_ROOT_NODE 0x1
148     #define BTREE_LEAF_NODE 0x2
149    
150    
151     int BTREE_WritePageToDisk(FILE *fp, BTREE_Page *pg)
152     {
153     BTREE_SetNextPage(pg,pg->next);
154     BTREE_SetPrevPage(pg,pg->prev);
155     BTREE_SetSize(pg,pg->size);
156     BTREE_SetNumKeys(pg,pg->n);
157     BTREE_SetFlags(pg,pg->flags);
158     BTREE_SetDataEnd(pg,pg->data_end);
159     fseek(fp,pg->page_number * BTREE_MinPageSize,SEEK_SET);
160     return fwrite(pg->data,pg->size,1,fp);
161     }
162    
163     int BTREE_WritePage(BTREE *b, BTREE_Page *pg)
164     {
165     int hash = pg->page_number % BTREE_CACHE_SIZE;
166     BTREE_Page *tmp;
167     pg->modified =1;
168     if((tmp = b->cache[hash]))
169     {
170     while(tmp)
171     {
172     if(tmp->page_number == pg->page_number)
173     {
174     return 0;
175     }
176     tmp = tmp->next_cache;
177     }
178     }
179     pg->next_cache = b->cache[hash];
180     b->cache[hash] = pg;
181     return 0;
182     }
183    
184     int BTREE_FlushCache(BTREE *b)
185     {
186     int i;
187     BTREE_Page *tmp, *next;
188     for(i = 0; i < BTREE_CACHE_SIZE; i++)
189     {
190     if((tmp = b->cache[i]))
191     {
192     while(tmp)
193     {
194     #ifdef DEBUG
195     if(tmp->in_use)
196     {
197     printf("DEBUG Error in FlushCache: Page in use\n");
198     exit(0);
199     }
200     #endif
201     next = tmp->next_cache;
202     if(tmp->modified)
203     {
204     BTREE_WritePageToDisk(b->fp, tmp);
205     tmp->modified = 0;
206     }
207     if(tmp != b->cache[i])
208     efree(tmp);
209     tmp = next;
210     }
211     b->cache[i]->next_cache = NULL;
212     }
213     }
214     return 0;
215     }
216    
217     int BTREE_CleanCache(BTREE *b)
218     {
219     int i;
220     BTREE_Page *tmp,*next;
221     for(i = 0; i < BTREE_CACHE_SIZE; i++)
222     {
223     if((tmp = b->cache[i]))
224     {
225     while(tmp)
226     {
227     next = tmp->next_cache;
228     efree(tmp);
229     tmp = next;
230     }
231     b->cache[i] = NULL;
232     }
233     }
234     return 0;
235     }
236    
237     BTREE_Page *BTREE_ReadPageFromDisk(FILE *fp, unsigned long page_number)
238     {
239     BTREE_Page *pg = (BTREE_Page *)emalloc(sizeof(BTREE_Page) + BTREE_MinPageSize);
240    
241     fseek(fp,page_number * BTREE_MinPageSize,SEEK_SET);
242     fread(pg->data,BTREE_MinPageSize, 1, fp);
243    
244     BTREE_GetNextPage(pg,pg->next);
245     BTREE_GetPrevPage(pg,pg->prev);
246     BTREE_GetSize(pg,pg->size);
247     BTREE_GetNumKeys(pg,pg->n);
248     BTREE_GetFlags(pg,pg->flags);
249     BTREE_GetDataEnd(pg,pg->data_end);
250    
251     pg->page_number = page_number;
252     pg->modified = 0;
253     return pg;
254     }
255    
256     BTREE_Page *BTREE_ReadPage(BTREE *b, unsigned long page_number)
257     {
258     int hash = page_number % BTREE_CACHE_SIZE;
259     BTREE_Page *tmp;
260     if((tmp = b->cache[hash]))
261     {
262     while(tmp)
263     {
264     if(tmp->page_number == page_number)
265     {
266     return tmp;
267     }
268     tmp = tmp->next_cache;
269     }
270     }
271    
272     tmp = BTREE_ReadPageFromDisk(b->fp, page_number);
273     tmp->modified = 0;
274     tmp->in_use = 1;
275     tmp->next_cache = b->cache[hash];
276     b->cache[hash] = tmp;
277     return tmp;
278     }
279    
280     BTREE_Page *BTREE_NewPage(BTREE *b, unsigned int size, unsigned int flags)
281     {
282     BTREE_Page *pg;
283     long offset;
284     FILE *fp = b->fp;
285     int hash;
286     /* Round up size */
287     size = BTREE_RoundPageSize(size);
288    
289     if(size > BTREE_MaxPageSize)
290     return NULL;
291    
292     /* Get file pointer */
293     if(fseek(fp,0,SEEK_END) !=0)
294     {
295     printf("mal\n");
296     }
297     offset = ftell(fp);
298     /* Round up file pointer */
299     offset = BTREE_RoundPageSize(offset);
300    
301     /* Set new file pointer - data will be aligned */
302     if(fseek(fp,offset, SEEK_SET)!=0 || offset != ftell(fp))
303     {
304     printf("mal\n");
305     }
306    
307     pg = (BTREE_Page *)emalloc(sizeof(BTREE_Page) + size);
308     memset(pg,0,sizeof(BTREE_Page) + size);
309     /* Reserve space in file */
310     if(fwrite(pg->data,1,size,fp)!=size || ((long)size + offset) != ftell(fp))
311     {
312     printf("mal\n");
313     }
314    
315     pg->next = 0;
316     pg->prev = 0;
317     pg->size = size;
318     pg->flags = flags;
319     pg->data_end = BTREE_PageHeaderSize;
320     pg->n = 0;
321    
322     pg->page_number = offset/BTREE_MinPageSize;
323    
324     /* add to cache */
325     pg->modified = 1;
326     pg->in_use = 1;
327     hash = pg->page_number % BTREE_CACHE_SIZE;
328     pg->next_cache = b->cache[hash];
329     b->cache[hash] = pg;
330     return pg;
331     }
332    
333     void BTREE_FreePage(BTREE *b, BTREE_Page *pg)
334     {
335     int hash = pg->page_number % BTREE_CACHE_SIZE;
336     BTREE_Page *tmp;
337    
338     tmp = b->cache[hash];
339    
340     #ifdef DEBUG
341     if(!(tmp = b->cache[hash]))
342     {
343     /* This should never happen!!!! */
344     printf("Error in FreePage\n");
345     exit(0);
346     }
347     #endif
348    
349     while(tmp)
350     {
351     if (tmp->page_number != pg->page_number)
352     tmp = tmp->next_cache;
353     else
354     {
355     tmp->in_use = 0;
356     break;
357     }
358     }
359     }
360    
361     int BTREE_CompareKeys(unsigned char *key1, int key_len1, unsigned char *key2, int key_len2)
362     {
363     int rc;
364    
365     if(key_len1 > key_len2)
366     rc = memcmp(key1,key2,key_len2);
367     else
368     rc = memcmp(key1,key2,key_len1);
369    
370     if(!rc)
371     rc = key_len1 - key_len2;
372    
373     return rc;
374     }
375    
376    
377     int BTREE_GetPositionForKey(BTREE_Page *pg, unsigned char *key, int key_len, int *comp)
378     {
379     int i,j,k,isbigger=-1;
380     int key_len_k;
381     unsigned char *key_k;
382     /* Use binary search for adding key */
383     /* Look for the position to insert using a binary search */
384     i = pg->n - 1;
385     j = k = 0;
386     while (i >= j)
387     {
388     k = j + (i - j) / 2;
389     key_k = BTREE_KeyData(pg,k);
390     key_len_k = uncompress2(&key_k);
391     isbigger = BTREE_CompareKeys(key,key_len,key_k,key_len_k);
392     if (!isbigger)
393     break;
394     else if (isbigger > 0)
395     j = k + 1;
396     else
397     i = k - 1;
398     }
399    
400     *comp = isbigger;
401    
402     return k;
403     }
404    
405     unsigned int BTREE_GetKeyFromPage(BTREE *b, BTREE_Page *pg, unsigned char *key, int key_len, unsigned char **found, int *found_len)
406     {
407     int k,comp = 0;
408    
409     k = BTREE_GetPositionForKey(pg, key, key_len, &comp);
410    
411     if(comp > 0 && k == (int) pg->n && k)
412     k--;
413    
414     if(comp < 0 && k)
415     k--;
416    
417     b->current_page = pg->page_number;
418     b->current_position = k;
419    
420     *found = BTREE_KeyData(pg,k);
421     *found_len = uncompress2(found);
422     return UNPACKLONG(*(unsigned long *) (*found + *found_len));
423     }
424    
425     int BTREE_AddKeyToPage(BTREE_Page *pg, int position, unsigned char *key, int key_len, unsigned long data_pointer)
426     {
427     unsigned char buffer[BTREE_MaxPageSize];
428     int j,k;
429     unsigned char *p;
430     unsigned char *new_key_start, *new_key_end;
431     int new_entry_len , tmp;
432    
433     data_pointer = PACKLONG(data_pointer);
434    
435     k = position;
436    
437     /* Write key */
438     /* Write from Page header upto the key being inserted */
439     p = buffer;
440     memcpy(p,pg->data,BTREE_KeyIndexOffset(pg->data,k) - pg->data);
441     p += BTREE_KeyIndexOffset(pg->data,k) - pg->data;
442    
443     p += (pg->n - k + 1) * SizeInt16;
444    
445     if(k == (int)pg->n)
446     {
447     if(k)
448     {
449     memcpy(p,BTREE_KeyData(pg,0),BTREE_EndData(pg) - BTREE_KeyData(pg,0));
450     p += BTREE_EndData(pg) - BTREE_KeyData(pg,0);
451     }
452     }
453     else
454     {
455     if(k)
456     {
457     memcpy(p,BTREE_KeyData(pg,0),BTREE_KeyData(pg,k) - BTREE_KeyData(pg,0));
458     p += BTREE_KeyData(pg,k) - BTREE_KeyData(pg,0);
459     }
460     }
461    
462     new_key_start = p;
463     p = compress3(key_len, p);
464     memcpy(p , key, key_len);
465     p += key_len;
466     memcpy(p, &data_pointer, SizeInt32);
467     p += SizeInt32;
468     new_key_end = p;
469     new_entry_len = new_key_end - new_key_start;
470    
471     if(k < (int) pg->n)
472     {
473     memcpy(p,BTREE_KeyData(pg,k), BTREE_EndData(pg) - BTREE_KeyData(pg,k));
474     p += BTREE_EndData(pg) - BTREE_KeyData(pg,k);
475     }
476    
477     for(j = 0; j < k; j++)
478     {
479     tmp = BTREE_KeyDataOffset(pg,j) + SizeInt16;
480     *(BTREE_KeyIndexOffset(buffer,j)) = (unsigned char)((tmp & 0xff00) >>8);
481     *(BTREE_KeyIndexOffset(buffer,j) + 1) = (unsigned char) (tmp & 0xff);
482     }
483    
484     for(j = (int)(pg->n - 1) ; j >=k; j--)
485     {
486     tmp = BTREE_KeyDataOffset(pg,j) + new_entry_len + SizeInt16;
487     *(BTREE_KeyIndexOffset(buffer,j + 1)) = (unsigned char)((tmp & 0xff00) >>8);
488     *(BTREE_KeyIndexOffset(buffer,j + 1) + 1) = (unsigned char) (tmp & 0xff);
489     }
490    
491     tmp = new_key_start - buffer;
492     *(BTREE_KeyIndexOffset(buffer,k)) = (unsigned char)((tmp & 0xff00) >>8);
493     *(BTREE_KeyIndexOffset(buffer,k) + 1) = (unsigned char) (tmp & 0xff);
494    
495     memcpy(pg->data, buffer, p - buffer);
496     pg->n++;
497     pg->data_end = p - buffer;
498    
499     return k;
500     }
501    
502     int BTREE_DelKeyInPage(BTREE_Page *pg, int pos)
503     {
504     unsigned char buffer[BTREE_MaxPageSize];
505     unsigned char *p, *q;
506     unsigned char *del_key_start, *del_key_end;
507     int del_entry_len , tmp;
508     int j, k = pos;
509    
510    
511    
512     /* Write key */
513     /* Write from Page header upto the key being deleted */
514     p = buffer;
515    
516     memcpy(p,pg->data,BTREE_KeyIndexOffset(pg->data,k) - pg->data);
517     p += BTREE_KeyIndexOffset(pg->data,k) - pg->data;
518    
519     if((k + 1) < (int)pg->n)
520     {
521     memcpy(p,BTREE_KeyIndexOffset(pg->data,k + 1), BTREE_KeyIndexOffset(pg->data,pg->n) - BTREE_KeyIndexOffset(pg->data,k + 1));
522     p += BTREE_KeyIndexOffset(pg->data,pg->n) - BTREE_KeyIndexOffset(pg->data,k + 1);
523     }
524    
525    
526     if(k)
527     {
528     memcpy(p,BTREE_KeyData(pg,0),BTREE_KeyData(pg,k) - BTREE_KeyData(pg,0));
529     p += BTREE_KeyData(pg,k) - BTREE_KeyData(pg,0);
530     }
531     if((k + 1) < (int)pg->n)
532     {
533     memcpy(p,BTREE_KeyData(pg,k + 1),BTREE_EndData(pg) - BTREE_KeyData(pg,k + 1));
534     p += BTREE_EndData(pg) - BTREE_KeyData(pg,k + 1);
535     }
536    
537     /* Compute length of deleted key */
538     del_key_start = q = BTREE_KeyData(pg,k);
539     q += uncompress2(&q);
540     q += SizeInt32;
541     del_key_end = q;
542     del_entry_len = del_key_end - del_key_start;
543    
544     for(j = 0; j < k; j++)
545     {
546     tmp = BTREE_KeyDataOffset(pg,j) - SizeInt16;
547     *(BTREE_KeyIndexOffset(buffer,j)) = (unsigned char)((tmp & 0xff00) >>8);
548     *(BTREE_KeyIndexOffset(buffer,j) + 1) = (unsigned char) (tmp & 0xff);
549     }
550    
551     for(j = (int)(pg->n - 1) ; j >k; j--)
552     {
553     tmp = BTREE_KeyDataOffset(pg,j) - del_entry_len - SizeInt16;
554     *(BTREE_KeyIndexOffset(buffer,j - 1)) = (unsigned char)((tmp & 0xff00) >>8);
555     *(BTREE_KeyIndexOffset(buffer,j - 1) + 1) = (unsigned char) (tmp & 0xff);
556     }
557    
558     memcpy(pg->data, buffer, p - buffer);
559     pg->n--;
560     pg->data_end = p - buffer;
561    
562     return k;
563     }
564    
565     BTREE *BTREE_New(FILE *fp, unsigned int size)
566     {
567     BTREE *b;
568     int i;
569     b = (BTREE *) emalloc(sizeof(BTREE));
570     b->page_size = size;
571     b->fp = fp;
572     for(i = 0; i < BTREE_CACHE_SIZE; i++)
573     b->cache[i] = NULL;
574    
575     return b;
576     }
577    
578     BTREE *BTREE_Create(FILE *fp, unsigned int size)
579     {
580     BTREE *b;
581     BTREE_Page *root;
582     /* Round up size */
583     size = BTREE_RoundPageSize(size);
584    
585     if(size > BTREE_MaxPageSize)
586     return NULL;
587    
588     b = BTREE_New(fp , size);
589     root = BTREE_NewPage(b, size, BTREE_ROOT_NODE | BTREE_LEAF_NODE);
590    
591     b->root_page = root->page_number;
592    
593     BTREE_WritePage(b, root);
594     BTREE_FreePage(b, root);
595    
596     return b;
597     }
598    
599    
600     BTREE *BTREE_Open(FILE *fp, int size, unsigned long root_page)
601     {
602     BTREE *b;
603     /* Round up size */
604     size = BTREE_RoundPageSize(size);
605    
606     if(size > BTREE_MaxPageSize)
607     return NULL;
608    
609     b = BTREE_New(fp , size);
610    
611     b->root_page = root_page;
612    
613     return b;
614     }
615    
616     unsigned long BTREE_Close(BTREE *bt)
617     {
618     unsigned long root_page = bt->root_page;
619     BTREE_FlushCache(bt);
620     BTREE_CleanCache(bt);
621     efree(bt);
622     return root_page;
623     }
624    
625    
626     BTREE_Page *BTREE_Walk(BTREE *b, unsigned char *key, int key_len)
627     {
628     BTREE_Page *pg = BTREE_ReadPage(b, b->root_page);
629     unsigned int i = 0;
630     unsigned long next_page;
631     unsigned char *found;
632     unsigned int found_len;
633     unsigned long father_page;
634    
635     b->tree[i++] = 0; /* No father for root */
636    
637     father_page = pg->page_number;
638     while(!(pg->flags & BTREE_LEAF_NODE))
639     {
640     next_page = BTREE_GetKeyFromPage(b, pg, key, key_len, &found, &found_len);
641     BTREE_FreePage(b, pg);
642     pg = BTREE_ReadPage(b, next_page);
643     b->tree[i++] = father_page;
644     father_page = pg->page_number;
645     }
646     b->levels = i;
647     return pg;
648     }
649    
650     BTREE_Page *BTREE_SplitPage(BTREE *b, BTREE_Page *pg)
651     {
652     BTREE_Page *new_pg = BTREE_NewPage(b, pg->size, pg->flags);
653     int i,n;
654     unsigned char *key_data, *p, *q, *start;
655     int key_len;
656     int tmp;
657    
658     n=pg->n / 2;
659    
660     /* Key data of new page starts here */
661     p = q = BTREE_KeyIndexOffset(new_pg->data, n);
662    
663     for(i = 0; i < n; i++)
664     {
665     key_data = start = BTREE_KeyData(pg, pg->n - n + i);
666     key_len = uncompress2(&key_data);
667    
668     memcpy(p, start, (key_data - start) + key_len + SizeInt32);
669     tmp = p - new_pg->data;
670     p += (key_data - start) + key_len + SizeInt32;
671    
672     *(BTREE_KeyIndexOffset(new_pg->data,i)) = (unsigned char)((tmp & 0xff00) >>8);
673     *(BTREE_KeyIndexOffset(new_pg->data,i) + 1) = (unsigned char) (tmp & 0xff);
674     }
675    
676     new_pg->n = n;
677     new_pg->data_end = p - new_pg->data;
678    
679     pg->n -= n;
680     p = BTREE_KeyIndexOffset(pg->data, pg->n);
681     for(i = 0; i < (int)pg->n ; i++)
682     {
683     key_data = start = BTREE_KeyData(pg,i);
684     key_len = uncompress2(&key_data);
685    
686     memmove(p, start, (key_data - start) + key_len + SizeInt32);
687     tmp = p - pg->data;
688     p += (key_data - start) + key_len + SizeInt32;
689    
690     *(BTREE_KeyIndexOffset(pg->data,i)) = (unsigned char)((tmp & 0xff00) >>8);
691     *(BTREE_KeyIndexOffset(pg->data,i) + 1) = (unsigned char) (tmp & 0xff);
692     }
693     pg->data_end = p - pg->data;;
694    
695     return new_pg;
696     }
697    
698    
699     int BTREE_InsertInPage(BTREE *b, BTREE_Page *pg, unsigned char *key, int key_len, unsigned long data_pointer, int level, int update)
700     {
701     BTREE_Page *new_pg, *next_pg, *root_page, *father_pg, *tmp_pg;
702     unsigned int free_space, required_space;
703     int key_pos, key_len0;
704     unsigned char *key_data0;
705     int comp;
706    
707     required_space = MAXINTCOMPSIZE + key_len + SizeInt32;
708    
709     /* Check for Duplicate key if we are in a leaf page */
710     key_pos = BTREE_GetPositionForKey(pg, key, key_len, &comp);
711    
712     if(comp == 0 && (pg->flags & BTREE_LEAF_NODE))
713     {
714     BTREE_FreePage(b, pg); /* Dup Key */
715     return -1;
716     }
717    
718     free_space = pg->size - pg->data_end;
719     if(required_space <= free_space)
720     {
721     if (comp > 0)
722     key_pos++;
723     else if(comp == 0 && (pg->flags & BTREE_LEAF_NODE))
724     {
725     BTREE_FreePage(b, pg); /* Dup Key */
726     return -1;
727     }
728    
729     if(!(pg->flags & BTREE_LEAF_NODE) && update)
730     {
731     BTREE_DelKeyInPage(pg, key_pos);
732     }
733    
734     BTREE_AddKeyToPage(pg, key_pos, key, key_len, data_pointer);
735    
736     if(key_pos == 0)
737     {
738    
739     if(!(pg->flags & BTREE_ROOT_NODE))
740     {
741     key_data0 = BTREE_KeyData(pg,0);
742     key_len0 = uncompress2(&key_data0);
743     father_pg = BTREE_ReadPage(b,b->tree[level]);
744     BTREE_InsertInPage(b,father_pg, key_data0, key_len0, pg->page_number, level - 1, 1);
745     }
746     }
747     BTREE_WritePage(b, pg);
748     BTREE_FreePage(b, pg);
749     return 0;
750     }
751    
752     /* There is not enough free space - Split page */
753     new_pg = BTREE_SplitPage(b, pg);
754     if(pg->next)
755     {
756     next_pg = BTREE_ReadPage(b, pg->next);
757     next_pg->prev = new_pg->page_number;
758     BTREE_WritePage(b, next_pg);
759     BTREE_FreePage(b, next_pg);
760     }
761     new_pg->next = pg->next;
762     new_pg->prev = pg->page_number;
763     pg->next = new_pg->page_number;
764    
765     key_data0 = BTREE_KeyData(new_pg,0);
766     key_len0 = uncompress2(&key_data0);
767    
768     /* Let's see where to put the key */
769     if(BTREE_CompareKeys(key, key_len, key_data0, key_len0) > 0)
770     {
771     tmp_pg = new_pg;
772     }
773     else
774     {
775     tmp_pg = pg;
776     }
777    
778     key_pos = BTREE_GetPositionForKey(tmp_pg, key, key_len, &comp);
779     if(comp>0)
780     key_pos++;
781    
782     if(!(tmp_pg->flags & BTREE_LEAF_NODE) && update)
783     {
784     BTREE_DelKeyInPage(tmp_pg, key_pos);
785     }
786     BTREE_AddKeyToPage(tmp_pg, key_pos, key, key_len, data_pointer);
787    
788     if(pg->flags & BTREE_ROOT_NODE)
789     {
790     pg->flags &= ~BTREE_ROOT_NODE;
791     new_pg->flags &= ~BTREE_ROOT_NODE;
792     root_page = BTREE_NewPage(b,b->page_size, BTREE_ROOT_NODE);
793    
794     key_data0 = BTREE_KeyData(pg,0);
795     key_len0 = uncompress2(&key_data0);
796     BTREE_AddKeyToPage(root_page, 0, key_data0, key_len0 , pg->page_number);
797    
798     key_data0 = BTREE_KeyData(new_pg,0);
799     key_len0 = uncompress2(&key_data0);
800     BTREE_AddKeyToPage(root_page, 1, key_data0, key_len0, new_pg->page_number);
801    
802     b->root_page = root_page->page_number;
803     BTREE_WritePage(b, pg);
804     BTREE_FreePage(b, pg);
805     BTREE_WritePage(b, new_pg);
806     BTREE_FreePage(b, new_pg);
807     BTREE_WritePage(b, root_page);
808     BTREE_FreePage(b, root_page);
809    
810     return 0;
811     }
812    
813     if(key_pos == 0 && tmp_pg == pg)
814     {
815     if(!(pg->flags & BTREE_ROOT_NODE))
816     {
817     father_pg = BTREE_ReadPage(b,b->tree[level]);
818     BTREE_InsertInPage(b,father_pg, key, key_len, pg->page_number, level - 1, 1);
819     }
820    
821     BTREE_WritePage(b, pg);
822     BTREE_FreePage(b, pg);
823    
824     key_data0 = BTREE_KeyData(new_pg,0);
825     key_len0 = uncompress2(&key_data0);
826     BTREE_FreePage(b, BTREE_Walk(b,key_data0,key_len0));
827     }
828     else
829     {
830     BTREE_WritePage(b, pg);
831     BTREE_FreePage(b, pg);
832    
833     key_data0 = BTREE_KeyData(new_pg,0);
834     key_len0 = uncompress2(&key_data0);
835     }
836    
837     father_pg = BTREE_ReadPage(b,b->tree[level]);
838     BTREE_InsertInPage(b,father_pg, key_data0, key_len0, new_pg->page_number, level - 1, 0);
839    
840    
841     BTREE_WritePage(b, new_pg);
842     BTREE_FreePage(b, new_pg);
843    
844     return 0;
845     }
846    
847    
848     int BTREE_Insert(BTREE *b, unsigned char *key, int key_len, unsigned long data_pointer)
849     {
850     BTREE_Page *pg = BTREE_Walk(b,key,key_len);
851     return BTREE_InsertInPage(b, pg, key, key_len, data_pointer, b->levels - 1, 0);
852     }
853    
854     int BTREE_Update(BTREE *b, unsigned char *key, int key_len, unsigned long new_data_pointer)
855     {
856     int comp, k, key_len_k;
857     unsigned char *key_k;
858     BTREE_Page *pg = BTREE_Walk(b,key,key_len);
859    
860    
861     /* Pack pointer */
862     new_data_pointer = PACKLONG(new_data_pointer);
863    
864     /* Get key position */
865     k = BTREE_GetPositionForKey(pg, key, key_len, &comp);
866    
867     if(comp)
868     {
869     return -1; /*Key not found */
870     }
871    
872     key_k = BTREE_KeyData(pg,k);
873    
874     key_len_k = uncompress2(&key_k);
875    
876     if ( key_len_k != key_len)
877     return -1; /* Error - Should never happen */
878    
879     key_k += key_len_k;
880    
881     memcpy(key_k, &new_data_pointer, SizeInt32);
882    
883     BTREE_WritePage(b, pg);
884     BTREE_FreePage(b, pg);
885    
886     return 0;
887     }
888    
889    
890     long BTREE_Search(BTREE *b, unsigned char *key, int key_len, unsigned char **found, int *found_len, int exact_match)
891     {
892     BTREE_Page *pg = BTREE_ReadPage(b, b->root_page);
893     unsigned int i = 0;
894     unsigned long next_page;
895     unsigned char *key_k;
896     unsigned int key_len_k;
897     unsigned long father_page;
898     unsigned long data_pointer;
899    
900     b->tree[i++] = 0; /* No father for root */
901    
902     father_page = pg->page_number;
903     while(!(pg->flags & BTREE_LEAF_NODE))
904     {
905     next_page = BTREE_GetKeyFromPage(b, pg, key, key_len, &key_k, &key_len_k);
906     BTREE_FreePage(b, pg);
907     pg = BTREE_ReadPage(b, next_page);
908     b->tree[i++] = father_page;
909     father_page = pg->page_number;
910     }
911     b->levels = i;
912     data_pointer = BTREE_GetKeyFromPage(b, pg, key, key_len, &key_k, &key_len_k);
913    
914     if(exact_match)
915     {
916     if(BTREE_CompareKeys(key,key_len,key_k,key_len_k)!=0)
917     return -1L;
918     }
919    
920     *found_len = key_len_k;
921     *found = emalloc(key_len_k);
922     memcpy(*found,key_k,key_len_k);
923    
924     BTREE_FreePage(b,pg);
925     return data_pointer;
926     }
927    
928     long BTREE_Next(BTREE *b, unsigned char **found, int *found_len)
929     {
930     BTREE_Page *pg = BTREE_ReadPage(b, b->current_page);
931     unsigned long next_page;
932     long data_pointer;
933     unsigned char *key_k;
934     int key_len_k;
935     b->current_position++;
936     if(pg->n == b->current_position)
937     {
938     next_page = pg->next;
939     BTREE_FreePage(b,pg);
940     if(!next_page)
941     return -1;
942     pg = BTREE_ReadPage(b, next_page);
943     b->current_page = next_page;
944     b->current_position = 0;
945     }
946     key_k = BTREE_KeyData(pg,b->current_position);
947     *found_len = key_len_k = uncompress2(&key_k);
948     *found = emalloc(key_len_k);
949     memcpy(*found,key_k,key_len_k);
950     data_pointer = UNPACKLONG(*(unsigned long *) (key_k + key_len_k));
951    
952     BTREE_FreePage(b,pg);
953    
954     return data_pointer;
955     }
956    
957     #ifdef DEBUG
958    
959     #include <time.h>
960    
961     #define N_TEST 300000
962    
963     #define F_READ_BINARY "rb"
964     #define F_WRITE_BINARY "wb"
965     #define F_READWRITE_BINARY "rb+"
966    
967     #define F_READ_TEXT "r"
968     #define F_WRITE_TEXT "w"
969     #define F_READWRITE_TEXT "r+"
970    
971     int main()
972     {
973     FILE *fp;
974     BTREE *bt;
975     unsigned char buffer[20];
976     int i;
977     static int nums[N_TEST];
978     unsigned long root_page;
979     unsigned char *found;
980     int found_len;
981     srand(time(NULL));
982    
983     goto test2;
984    
985     fp = fopen("kkkkk",F_WRITE_BINARY);
986     fwrite("asjhd",1,5,fp);
987     fclose(fp);
988     fp = fopen("kkkkk",F_READWRITE_BINARY);
989    
990     printf("\n\nIndexing\n\n");
991    
992     bt = BTREE_Create(fp, 15);
993     for(i=N_TEST - 1;i>=0;i--)
994     {
995     // nums[i] = rand();
996     nums[i]=i;
997    
998    
999     sprintf(buffer,"%d",nums[i]);
1000     // sprintf(buffer,"%.12d",nums[i]);
1001     BTREE_Insert(bt,buffer,strlen(buffer),nums[i]);
1002     if(nums[i]!= BTREE_Search(bt,buffer,strlen(buffer),&found,&found_len,1))
1003     printf("\n\nmal %s\n\n",buffer);
1004     if(!(i%1000))
1005     {
1006     BTREE_FlushCache(bt);
1007     printf("%d \r",i);
1008     }
1009     }
1010    
1011     root_page = BTREE_Close(bt);
1012     fclose(fp);
1013    
1014     search:;
1015     printf("\n\nSearching\n\n");
1016    
1017     fp = fopen("kkkkk",F_READ_BINARY);
1018     bt = BTREE_Open(fp,15,root_page);
1019    
1020     for(i=0;i<N_TEST;i++)
1021     {
1022     sprintf(buffer,"%d",nums[i]);
1023     // sprintf(buffer,"%.12d",nums[i]);
1024    
1025     if(nums[i] != BTREE_Search(bt,buffer,strlen(buffer),&found,&found_len,1))
1026     printf("\n\nmal %s\n\n",buffer);
1027     if(!(i%1000))
1028     printf("%d \r",i);
1029     }
1030    
1031     fclose(fp);
1032    
1033     test2:;
1034    
1035    
1036     fp = fopen("kkkkk",F_WRITE_BINARY);
1037     fclose(fp);
1038     fp = fopen("kkkkk",F_READWRITE_BINARY);
1039    
1040     fwrite("aaa",1,3,fp);
1041    
1042     printf("\n\nIndexing\n\n");
1043    
1044     bt = BTREE_Create(fp, 15);
1045     for(i=0;i<N_TEST;i++)
1046     {
1047     // nums[i] = rand();
1048     nums[i]=i;
1049     sprintf(buffer,"%d",nums[i]);
1050     // sprintf(buffer,"%.12d",nums[i]);
1051     BTREE_Insert(bt,buffer,strlen(buffer),nums[i]);
1052     if(nums[i]!= BTREE_Search(bt,buffer,strlen(buffer),&found,&found_len,1))
1053     printf("\n\nmal %s\n\n",buffer);
1054     if(!(i%1000))
1055     {
1056     BTREE_FlushCache(bt);
1057     printf("%d \r",i);
1058     }
1059     }
1060    
1061     root_page = BTREE_Close(bt);
1062     fclose(fp);
1063    
1064     printf("\n\nSearching\n\n");
1065    
1066     fp = fopen("kkkkk",F_READ_BINARY);
1067     bt = BTREE_Open(fp,15,root_page);
1068    
1069     for(i=0;i<N_TEST;i++)
1070     {
1071     sprintf(buffer,"%d",nums[i]);
1072     if(nums[i] != BTREE_Search(bt,buffer,strlen(buffer),&found,&found_len,1))
1073     printf("\n\nmal %s\n\n",buffer);
1074     if(!(i%1000))
1075     printf("%d \r",i);
1076     }
1077    
1078    
1079     fclose(fp);
1080     }
1081    
1082     #endif

  ViewVC Help
Powered by ViewVC 1.1.22