/* * Split leaf, then insert to parent. * key: key to add after split (cursor will point leaf which is including key) * hint: hint for split * * return value: * 0 - success * < 0 - error */ static int btree_leaf_split(struct cursor *cursor, tuxkey_t key, tuxkey_t hint) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } trace("split leaf"); struct btree *btree = cursor->btree; struct buffer_head *newbuf; newbuf = new_leaf(btree); if (IS_ERR(newbuf)) return PTR_ERR(newbuf); log_balloc(btree->sb, bufindex(newbuf), 1); struct buffer_head *leafbuf = cursor_leafbuf(cursor); tuxkey_t newkey = btree->ops->leaf_split(btree, hint, bufdata(leafbuf), bufdata(newbuf)); assert(cursor_this_key(cursor) < newkey); assert(newkey < cursor_next_key(cursor)); if (key < newkey) mark_buffer_dirty_non(newbuf); else mark_buffer_dirty_non(leafbuf); return insert_leaf(cursor, newkey, newbuf, key < newkey); }
int btree_read(struct cursor *cursor, struct btree_key_range *key) { struct btree *btree = cursor->btree; struct btree_ops *ops = btree->ops; void *leaf = bufdata(cursor_leafbuf(cursor)); tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); /* FIXME: we might be better to support multiple leaves */ assert(bottom <= key->start && key->start < limit); assert(ops->leaf_sniff(btree, leaf)); return ops->leaf_read(btree, bottom, limit, leaf, key); }
int btree_read(struct cursor *cursor, struct btree_key_range *key) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct btree *btree = cursor->btree; struct btree_ops *ops = btree->ops; void *leaf = bufdata(cursor_leafbuf(cursor)); tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); /* FIXME: we might be better to support multiple leaves */ assert(bottom <= key->start && key->start < limit); assert(ops->leaf_sniff(btree, leaf)); return ops->leaf_read(btree, bottom, limit, leaf, key); }
int btree_write(struct cursor *cursor, struct btree_key_range *key) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct btree *btree = cursor->btree; struct btree_ops *ops = btree->ops; tuxkey_t split_hint; int err; /* FIXME: we might be better to support multiple leaves */ err = cursor_redirect(cursor); if (err) return err; while (key->len > 0) { tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); void *leaf = bufdata(cursor_leafbuf(cursor)); int need_split; assert(bottom <= key->start && key->start < limit); assert(ops->leaf_sniff(btree, leaf)); need_split = ops->leaf_write(btree, bottom, limit, leaf, key, &split_hint); if (need_split < 0) return need_split; else if (!need_split) { mark_buffer_dirty_non(cursor_leafbuf(cursor)); continue; } err = btree_leaf_split(cursor, key->start, split_hint); if (err) return err; /* FIXME: error handling */ } return 0; }
/* * Traverse btree for specified range * key: start to traverse (cursor should point leaf is including key) * len: length to traverse * * return value: * < 0 - error * 0 - traversed all range * 0 < - traverse was stopped by func, and return value of func */ int btree_traverse(struct cursor *cursor, tuxkey_t key, u64 len, btree_traverse_func_t func, void *data) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct btree *btree = cursor->btree; int ret; do { tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); void *leaf = bufdata(cursor_leafbuf(cursor)); assert(btree->ops->leaf_sniff(btree, leaf)); if (key < bottom) { len -= min_t(u64, len, bottom - key); if (len == 0) break; key = bottom; } ret = func(btree, bottom, limit, leaf, key, len, data); /* Stop traverse if ret >= 1, or error */ if (ret) goto out; /* If next key is out of range, done */ if (key + len <= limit) break; ret = cursor_advance(cursor); if (ret < 0) goto out; } while (ret); ret = 0; out: return ret; }
/* * Split leaf, then insert to parent. * key: key to add after split (cursor will point leaf which is including key) * hint: hint for split * * return value: * 0 - success * < 0 - error */ static int btree_leaf_split(struct cursor *cursor, tuxkey_t key, tuxkey_t hint) { trace("split leaf"); struct btree *btree = cursor->btree; struct buffer_head *newbuf; newbuf = new_leaf(btree); if (IS_ERR(newbuf)) return PTR_ERR(newbuf); log_balloc(btree->sb, bufindex(newbuf), 1); struct buffer_head *leafbuf = cursor_leafbuf(cursor); tuxkey_t newkey = btree->ops->leaf_split(btree, hint, bufdata(leafbuf), bufdata(newbuf)); assert(cursor_this_key(cursor) < newkey); assert(newkey < cursor_next_key(cursor)); if (key < newkey) mark_buffer_dirty_non(newbuf); else mark_buffer_dirty_non(leafbuf); return insert_leaf(cursor, newkey, newbuf, key < newkey); }
int btree_write(struct cursor *cursor, struct btree_key_range *key) { struct btree *btree = cursor->btree; struct btree_ops *ops = btree->ops; tuxkey_t split_hint; int err; /* FIXME: we might be better to support multiple leaves */ err = cursor_redirect(cursor); if (err) return err; while (key->len > 0) { tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); void *leaf = bufdata(cursor_leafbuf(cursor)); assert(bottom <= key->start && key->start < limit); assert(ops->leaf_sniff(btree, leaf)); err = ops->leaf_write(btree, bottom, limit, leaf, key, &split_hint); if (!err) { mark_buffer_dirty_non(cursor_leafbuf(cursor)); continue; } assert(err == -ENOSPC); err = btree_leaf_split(cursor, key->start, split_hint); if (err) break; /* FIXME: error handling */ } return err; }