1 | /* onode_index.c 2 | ------------- 3 | A casually demented B+Tree designed to stay balanced 4 | and be optimized for access from disk (and in-core cache) 5 | 6 | $Id: onode_index.c,v 1.15 2003/10/20 07:18:11 stewart Exp $ 7 | 8 | (C)2003 Stewart Smith 9 | Distributed under the GNU Public License 10 | */ 11 | #include <stdio.h> 12 | #include <stdlib.h> 13 | #include <string.h> 14 | #include "testkit/types.h" 15 | 16 | #include "disk.h" 17 | #include "super_block.h" 18 | #include "space_bitmap.h" 19 | #include "onode_index.h" 20 | 21 | extern u64 next_free; 22 | 23 | u64 onode_index_new_id(struct fcfs_onode_index *index) 24 | { 25 | 26 | } 27 | 28 | struct fcfs_onode_index* onode_index_read(struct fcfs_disk *disk) 29 | { 30 | struct fcfs_onode_index *index; 31 | struct fcfs_disk_block *block; 32 | 33 | index = (struct fcfs_onode_index*)malloc(sizeof(struct fcfs_onode_index)); 34 | if(index==NULL) 35 | {fprintf(stderr,"Cannot allocate onode index structure to read into\n"); 36 | abort();} 37 | block = disk_getblock(disk,disk->sb->onode_index_blocknr); 38 | index->root_block = block; 39 | index->root = (struct fcfs_onode_index_node*)block->data; 40 | 41 | index->disk = disk; 42 | 43 | return index; 44 | } 45 | 46 | struct fcfs_onode_index* onode_index_new(struct fcfs_disk *disk) 47 | { 48 | struct fcfs_onode_index *index; 49 | 50 | index = (struct fcfs_onode_index*)malloc(sizeof(struct fcfs_onode_index)); 51 | if(index==NULL) 52 | {fprintf(stderr,"Cannot allocate onode index structure\n"); abort();} 53 | 54 | index->root = NULL; 55 | index->disk = disk; 56 | 57 | return index; 58 | } 59 | 60 | int onode_index_write_leaf(struct fcfs_onode_index *index, struct fcfs_onode_index_leaf *leaf) 61 | { 62 | struct fcfs_disk_block *block; 63 | 64 | block = disk_getblock(index->disk,leaf->block); 65 | #ifdef DEBUG_ONODE_INDEX 66 | fprintf(stderr,"--WRITE LEAF--\n"); 67 | #endif 68 | disk_writeblock(block); 69 | disk_freeblock(block); 70 | 71 | return 1; 72 | } 73 | 74 | struct fcfs_onode_index_leaf *onode_index_leaf_new(struct fcfs_onode_index *index, struct fcfs_onode_index_node *parent, int position) 75 | { 76 | int i; 77 | struct fcfs_block_run *br; 78 | struct fcfs_onode_index_leaf *leaf; 79 | struct fcfs_disk_block *block; 80 | 81 | // printf("onode_index_leaf_new\n"); 82 | br = ag_allocate_block(index->disk, 83 | BLOCK_AG(index->disk,parent->block), 84 | parent->block%index->disk->sb->ag_blocksnr, 85 | 1); 86 | block = disk_newblock(index->disk,BR_SECTOR_T(index->disk,br)); 87 | leaf = (struct fcfs_onode_index_leaf*)block->data; 88 | 89 | #ifdef DEBUG_ONODE_INDEX 90 | fprintf(stderr,"LEAF: AG: %d, Start: %d, Len: %d\n",br->allocation_group,br->start,br->len); 91 | #endif 92 | 93 | leaf->magic1 = FCFS_ONODE_INDEX_LEAF_MAGIC1; 94 | leaf->id = index->disk->sb->onindex_next_id++; 95 | leaf->block = BR_SECTOR_T(index->disk,br); 96 | leaf->used = 0ULL; 97 | 98 | for(i=0;i<index->disk->sb->onindex_node_size;i++) 99 | { leaf->items[i].key = 0; leaf->items[i].onode_blocknr = 0; } 100 | 101 | onode_index_write_leaf(index,leaf); 102 | 103 | parent->items[position].node_blocknr = BR_SECTOR_T(index->disk,br); 104 | if(parent->used < position) 105 | parent->used = position; 106 | 107 | onode_index_write_node(index,parent); 108 | 109 | free(br); 110 | return leaf; 111 | } 112 | 113 | struct fcfs_onode_index_node* onode_index_read_node(struct fcfs_onode_index *index, u64 blocknr) 114 | { 115 | struct fcfs_onode_index_node* node; 116 | struct fcfs_disk_block *block; 117 | 118 | block = disk_getblock(index->disk, blocknr); 119 | 120 | node = (struct fcfs_onode_index_node*) block->data; 121 | 122 | return node; 123 | } 124 | 125 | int onode_index_free_node(struct fcfs_onode_index *index, struct fcfs_onode_index_node* node) 126 | { 127 | struct fcfs_disk_block *block; 128 | block = disk_getblock(index->disk,node->block); 129 | disk_freeblock(block); 130 | free(node); 131 | return 1; 132 | } 133 | 134 | int onode_index_write_node(struct fcfs_onode_index *index, struct fcfs_onode_index_node* node) 135 | { 136 | struct fcfs_disk_block *block; 137 | 138 | /* Write root to disk */ 139 | block = disk_getblock(index->disk,node->block); 140 | disk_writeblock(block); 141 | #ifdef DEBUG_ONODE_INDEX 142 | fprintf(stderr,"--WRITE NODE--\n"); 143 | #endif 144 | disk_freeblock(block); 145 | 146 | return 1; 147 | } 148 | 149 | /* Writes root back to disk */ 150 | static inline int onode_index_write_root(struct fcfs_onode_index *index) 151 | { 152 | return onode_index_write_node(index,index->root); 153 | } 154 | 155 | /* The ever belated onode_index_new_node */ 156 | struct fcfs_disk_block *onode_index_new_node(struct fcfs_onode_index *index) 157 | { 158 | struct fcfs_block_run *br; 159 | struct fcfs_disk_block *block; 160 | struct fcfs_onode_index_node *node; 161 | int i; 162 | 163 | br = ag_allocate_block(index->disk,0,1,1); 164 | if((br->len) < 1) 165 | { 166 | fprintf(stderr,"Unable to allocate Onode Index Node\n"); 167 | fprintf(stderr,"\tAG: %d, Start: %d, Len: %d\n",br->allocation_group,br->start,br->len); 168 | abort(); 169 | } 170 | 171 | fprintf(stderr,"Onode Index node created at: AG: %d, Start: %d, Len: %d\n",br->allocation_group,br->start,br->len); 172 | 173 | block = disk_newblock(index->disk,BR_SECTOR_T(index->disk,br)); 174 | node = (struct fcfs_onode_index_node*)block->data; 175 | 176 | node->magic1 = FCFS_ONODE_INDEX_NODE_MAGIC1; 177 | node->id = index->disk->sb->onindex_next_id++; 178 | node->used = 0ULL; 179 | node->block = br->start; 180 | 181 | for(i=0;i<index->disk->sb->onindex_node_size;i++) 182 | { node->items[i].key = 0; node->items[i].node_blocknr = 0;} 183 | 184 | return block; 185 | } 186 | 187 | /* Creates a new root node for an onode_index */ 188 | int onode_index_new_root(struct fcfs_onode_index *index) 189 | { 190 | struct fcfs_onode_index_node *node; 191 | struct fcfs_disk_block *block; 192 | 193 | block = onode_index_new_node(index); 194 | index->root = (struct fcfs_onode_index_node*)block->data; 195 | index->root_block = block; 196 | 197 | fprintf(stderr,"****ONODE INDEX**** %llu\n",block->blocknr); 198 | 199 | /* Move br to index structure */ 200 | /* Also copy into super block, and write to disk */ 201 | /* update the SB records */ 202 | index->disk->sb->onode_index_blocknr = block->blocknr; 203 | index->disk->sb->onindex_free = index->disk->sb->onindex_node_size; 204 | fcfs_write_sb(index->disk); 205 | onode_index_write_root(index); 206 | 207 | return 1; 208 | } 209 | 210 | int onode_index_leaf_insert(struct fcfs_disk *disk,struct fcfs_onode_index_leaf *leaf, u64 key, u64 value) 211 | { 212 | int pos; 213 | int i; 214 | 215 | if(leaf->used==disk->sb->onindex_node_size) 216 | { /* Need to split leaf */ 217 | fprintf(stderr,"onode_index_leaf_insert: full onode_index_leaf. Growing of leaves not yet implemented\n"); 218 | abort(); 219 | } 220 | 221 | if(key > leaf->items[leaf->used-1].key) 222 | { /* Append to end of leaf */ 223 | leaf->used++; /* FIXME: should be atomic */ 224 | leaf->items[leaf->used-1].key = key; 225 | leaf->items[leaf->used-1].onode_blocknr = value; 226 | return 1; 227 | } 228 | else 229 | { 230 | for(i=0;i<leaf->used && leaf->items[i].key < key;i++) 231 | ; /* FIXME: Make binary search */ 232 | pos = i; 233 | leaf->used++; 234 | for(i=leaf->used;i>pos;i--) /* Shuffle everything down */ 235 | { 236 | leaf->items[i].key = leaf->items[i-1].key; 237 | leaf->items[i].onode_blocknr = leaf->items[i-1].onode_blocknr; 238 | } 239 | leaf->items[pos].key = key; /* Add our key */ 240 | leaf->items[pos].onode_blocknr = value; /* Add our value */ 241 | return 1; /* Success! */ 242 | } 243 | 244 | return 1; 245 | } 246 | 247 | /* Insert an onode into an index */ 248 | struct fcfs_block_run* onode_index_insert(struct fcfs_onode_index *index, struct fcfs_onode1 *onode) 249 | { 250 | struct fcfs_block_run *onode_br; 251 | struct fcfs_disk_block *block; 252 | struct fcfs_onode_index_node *node; 253 | struct fcfs_onode_index_node *parent; 254 | struct fcfs_onode_index_leaf *leaf; 255 | int i,node_pos; 256 | 257 | if(index->root==NULL) 258 | onode_index_new_root(index); 259 | 260 | /* Determine ID for onode */ 261 | // onode->onode_num = ((~0ULL)/index->disk->sb->onindex_node_size) * (i+1); 262 | onode->onode_num = random(); 263 | //index->disk->sb->onindex_next_id++; 264 | fcfs_write_sb(index->disk); 265 | 266 | #ifdef DEBUG_ONODE_INDEX 267 | fprintf(stderr,"STORE ONODE ID: %llu\n",onode->onode_num); 268 | #endif 269 | 270 | /* Revision 1 now that we're going onto disk */ 271 | onode->onode_revision = 1; 272 | 273 | /* Use count = 1, in onode_index */ 274 | onode->use_count = 1; 275 | 276 | /* Allocate room for onode */ 277 | // printf("onode_index_insert\n"); 278 | onode_br = ag_allocate_block(index->disk,0,10,1); 279 | 280 | #ifdef DEBUG_ONODE_INDEX 281 | fprintf(stderr,"ONODE created at: AG: %d, Start: %d, Len: %d\n",onode_br->allocation_group,onode_br->start,onode_br->len); 282 | #endif 283 | 284 | /* Write onode to disk */ 285 | block = disk_newblock(index->disk,BR_SECTOR_T(index->disk,onode_br)); 286 | // memset(block->data,0,index->disk->bsize); 287 | memcpy(block->data,onode,sizeof(struct fcfs_onode1)); 288 | disk_writeblock(block); 289 | #ifdef DEBUG_ONODE_INDEX 290 | fprintf(stderr,"ONODE Written\n"); 291 | #endif 292 | disk_freeblock(block); 293 | 294 | /* Put it in the index properly */ 295 | node = index->root; 296 | parent = NULL; 297 | 298 | /* Check current node for free space/location */ 299 | for(i=0;i<node->used && node->items[i].key < onode->onode_num;i++) 300 | ; /* FIXME: This should be a binary search */ 301 | 302 | if(i==index->disk->sb->onindex_node_size) 303 | i = 0; 304 | 305 | node_pos = i; /* position in the node */ 306 | 307 | #ifdef DEBUG_ONODE_INDEX 308 | fprintf(stderr,"\n\n\ti = %d\n\n",i); 309 | #endif 310 | 311 | if(node->items[i].node_blocknr!=0) 312 | { 313 | /* Lookup subtree, see if node or leaf */ 314 | parent = node; 315 | // node = ; 316 | block = disk_getblock(index->disk,node->items[i].node_blocknr); 317 | if(*((u64*)block->data)== FCFS_ONODE_INDEX_LEAF_MAGIC1) 318 | { /* is a leaf */ 319 | #ifdef DEBUG_ONODE_INDEX 320 | fprintf(stderr,"FOUND A LEAF!\n\n"); 321 | #endif 322 | leaf = (struct fcfs_onode_index_leaf *)block->data; 323 | #ifdef DEBUG_ONODE_INDEX 324 | fprintf(stderr,"GOING TO ADD TO LEAF 0x%llu\n",leaf->id); 325 | fprintf(stderr,"\tblock %llu\n",leaf->block); 326 | fprintf(stderr,"\tused %llu\n",leaf->used); 327 | #endif 328 | 329 | onode_index_leaf_insert(index->disk,leaf, 330 | onode->onode_num, 331 | BR_SECTOR_T(index->disk, 332 | onode_br)); 333 | 334 | disk_writeblock(block); 335 | parent->items[node_pos].key = onode->onode_num; 336 | onode_index_write_node(index,parent); 337 | index->disk->sb->onindex_used++; 338 | index->disk->sb->onindex_free--; 339 | fcfs_write_sb(index->disk); 340 | } 341 | else if(*((u64*)block->data)== FCFS_ONODE_INDEX_NODE_MAGIC1) 342 | { 343 | fprintf(stderr,"FOUND A NODE!\n\n"); 344 | fprintf(stderr,"**FIXME** We don't handle nodes yet\n"); 345 | } 346 | else 347 | { 348 | fprintf(stderr,"WARNING-CORRUPT: node pointer points to corrupt node or leaf!\n"); 349 | fprintf(stderr,"\tCORRUPT node->items[%d].node_blocknr = %llu\n",i,node->items[i].node_blocknr); 350 | fprintf(stderr,"\tMAGIC is %llx\n",*((u64*)block->data)); 351 | abort(); 352 | } 353 | disk_freeblock(block); 354 | } 355 | else 356 | { 357 | /* Create leaf */ 358 | leaf = onode_index_leaf_new(index, node,i); 359 | leaf->items[0].key = onode->onode_num; 360 | leaf->items[0].onode_blocknr = BR_SECTOR_T(index->disk,onode_br); 361 | leaf->used = 1; 362 | 363 | #ifdef DEBUG_ONODE_INDEX 364 | fprintf(stderr,"LEAF: Should be writing with key=%lld, block=%lld\n",leaf->items[0].key,leaf->items[0].onode_blocknr); 365 | #endif 366 | 367 | node->items[i].node_blocknr = leaf->block; 368 | node->items[i].key = onode->onode_num; 369 | node->used = i+1; 370 | 371 | onode_index_write_root(index); 372 | onode_index_write_leaf(index,leaf); 373 | } 374 | 375 | return onode_br; 376 | } 377 | 378 | struct fcfs_disk_block *onode_index_lookup(struct fcfs_onode_index *index,struct fcfs_block_run *onode_br, u64 id) 379 | { 380 | struct fcfs_disk_block *block; 381 | struct fcfs_disk_block *onode_block; 382 | struct fcfs_onode_index_node *node; 383 | struct fcfs_onode_index_node *parent; 384 | struct fcfs_onode_index_leaf *leaf; 385 | 386 | int i; 387 | 388 | node = index->root; 389 | 390 | for(i=0;i<node->used && node->items[i].key < id ;i++) 391 | ; 392 | 393 | /* Lookup subtree, see if node or leaf */ 394 | parent = node; 395 | // node = ; 396 | block = disk_getblock(index->disk,node->items[i].node_blocknr); 397 | if(*((u64*)block->data)== FCFS_ONODE_INDEX_LEAF_MAGIC1) 398 | { /* is a leaf */ 399 | fprintf(stderr,"FOUND A LEAF!\n\n"); 400 | leaf = (struct fcfs_onode_index_leaf *)block->data; 401 | fprintf(stderr,"READ LEAF 0x%llu\n",leaf->id); 402 | fprintf(stderr,"\tblock %llu\n",leaf->block); 403 | fprintf(stderr,"\tused %llu\n",leaf->used); 404 | for(i=0;i<leaf->used && leaf->items[i].key < id;i++) 405 | ; 406 | fprintf(stderr,"leaf i = %d, %llu %llu\n",i,leaf->items[i].key,leaf->items[i].onode_blocknr); 407 | onode_block = disk_getblock(index->disk,leaf->items[i].onode_blocknr); 408 | onode_br->allocation_group = BLOCK_AG(index->disk,leaf->items[i].onode_blocknr); 409 | onode_br->start = leaf->items[i].onode_blocknr%index->disk->sb->ag_blocksnr; 410 | onode_br->len = 1; 411 | disk_freeblock(block); 412 | } 413 | else 414 | abort(); 415 | 416 | return onode_block; 417 | } 418 | 419 | struct fcfs_onode_index* onode_index_delete(struct fcfs_onode_index* index) 420 | { 421 | if(index->root) 422 | disk_freeblock(index->root_block); 423 | free(index); 424 | index = NULL; 425 | return index; 426 | }