<commit_before>#include "node.h"
#include "../debug.h"
#include "../extent.h"


void node_dump(uint32_t node_addr) {
	struct node_hdr *hdr = fs_map_blk(node_addr, node_size_blk());
	
	if (hdr->leaf) {
		leaf_dump((leaf_ptr)hdr);
	} else {
		branch_dump((branch_ptr)hdr);
	}
	
	fs_unmap_blk(hdr, node_addr, node_size_blk());
}

uint32_t node_alloc(void) {
	/* allocating a block should be okay because the ext tree does not insert
	 * items on allocations; otherwise, we could deadlock, since extent
	 * allocation depends on a tree and tree insertion can depend on extent
	 * allocation */
	return ext_alloc(node_size_blk());
}

node_ptr node_map(uint32_t node_addr) {
	return (node_ptr)fs_map_blk(node_addr, node_size_blk());
}

void node_unmap(const node_ptr node) {
	const struct node_hdr *hdr = (const struct node_hdr *)node;
	
	fs_unmap_blk(node, hdr->this, node_size_blk());
}

bool node_is_root(uint32_t node_addr) {
	const node_ptr node = node_map(node_addr);
	bool is_root = (node->hdr.parent == 0);
	node_unmap(node);
	
	return is_root;
}

void node_zero_data(node_ptr node) {
	uint8_t *zero_ptr = (uint8_t *)node + sizeof(struct node_hdr);
	size_t   zero_len = node_size_usable();
	
	memset(zero_ptr, 0, zero_len);
}

void node_copy_data(node_ptr dst, const node_ptr src) {
	uint8_t       *copy_dst = (uint8_t *)dst + sizeof(struct node_hdr);
	const uint8_t *copy_src = (const uint8_t *)src + sizeof(struct node_hdr);
	size_t         copy_len = node_size_usable();
	
	memcpy(copy_dst, copy_src, copy_len);
}

void node_split(uint32_t this_addr) {
	node_ptr this = node_map(this_addr);
	
	uint32_t parent_addr = this->hdr.parent;
	branch_ptr parent;
	
	uint32_t new_addr = node_alloc();
	node_ptr new;
	
	bool was_root = node_is_root(this);
	
	/* if we are root, allocate *two* new nodes to be children of root, leaving
	 * this as the new root, so the addr of the tree's root doesn't change;
	 * if we are not the root node, try to allocate a node_ref in the parent
	 * node, and if that fails, recurse!
	 */
	if (was_root) {
		parent_addr = this_addr;
		parent      = (branch_ptr)this;
		
		this_addr = node_alloc();
		
		if (this->hdr.leaf) {
			this = (node_ptr)leaf_init(this_addr, parent_addr,
				parent->hdr.prev, new_addr);
		} else {
			this = (node_ptr)branch_init(this_addr, parent_addr);
		}
		
		node_copy_data(this, (node_ptr)parent);
		this->hdr.cnt = parent->hdr.cnt;
		
		parent->hdr.parent = 0;<commit_msg>lib/tree: fix usage of node_is_root in node_split<commit_after>#include "node.h"
#include "../debug.h"
#include "../extent.h"


void node_dump(uint32_t node_addr) {
	struct node_hdr *hdr = fs_map_blk(node_addr, node_size_blk());
	
	if (hdr->leaf) {
		leaf_dump((leaf_ptr)hdr);
	} else {
		branch_dump((branch_ptr)hdr);
	}
	
	fs_unmap_blk(hdr, node_addr, node_size_blk());
}

uint32_t node_alloc(void) {
	/* allocating a block should be okay because the ext tree does not insert
	 * items on allocations; otherwise, we could deadlock, since extent
	 * allocation depends on a tree and tree insertion can depend on extent
	 * allocation */
	return ext_alloc(node_size_blk());
}

node_ptr node_map(uint32_t node_addr) {
	return (node_ptr)fs_map_blk(node_addr, node_size_blk());
}

void node_unmap(const node_ptr node) {
	const struct node_hdr *hdr = (const struct node_hdr *)node;
	
	fs_unmap_blk(node, hdr->this, node_size_blk());
}

bool node_is_root(uint32_t node_addr) {
	const node_ptr node = node_map(node_addr);
	bool is_root = (node->hdr.parent == 0);
	node_unmap(node);
	
	return is_root;
}

void node_zero_data(node_ptr node) {
	uint8_t *zero_ptr = (uint8_t *)node + sizeof(struct node_hdr);
	size_t   zero_len = node_size_usable();
	
	memset(zero_ptr, 0, zero_len);
}

void node_copy_data(node_ptr dst, const node_ptr src) {
	uint8_t       *copy_dst = (uint8_t *)dst + sizeof(struct node_hdr);
	const uint8_t *copy_src = (const uint8_t *)src + sizeof(struct node_hdr);
	size_t         copy_len = node_size_usable();
	
	memcpy(copy_dst, copy_src, copy_len);
}

void node_split(uint32_t this_addr) {
	node_ptr this = node_map(this_addr);
	
	uint32_t parent_addr = this->hdr.parent;
	branch_ptr parent;
	
	uint32_t new_addr = node_alloc();
	node_ptr new;
	
	bool was_root = node_is_root(this_addr);
	
	/* if we are root, allocate *two* new nodes to be children of root, leaving
	 * this as the new root, so the addr of the tree's root doesn't change;
	 * if we are not the root node, try to allocate a node_ref in the parent
	 * node, and if that fails, recurse!
	 */
	if (was_root) {
		parent_addr = this_addr;
		parent      = (branch_ptr)this;
		
		this_addr = node_alloc();
		
		if (this->hdr.leaf) {
			this = (node_ptr)leaf_init(this_addr, parent_addr,
				parent->hdr.prev, new_addr);
		} else {
			this = (node_ptr)branch_init(this_addr, parent_addr);
		}
		
		node_copy_data(this, (node_ptr)parent);
		this->hdr.cnt = parent->hdr.cnt;
		
		parent->hdr.parent = 0;
{'fraction_non_alphanumeric': 0.11606597434331094, 'fraction_numerical': 0.009366727754021585, 'mean_word_length': 4.37417943107221, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2589718', 'n_tokens_mistral': 1942, 'n_tokens_neox': 1796, 'n_words': 465}