-
Notifications
You must be signed in to change notification settings - Fork 0
01_Analysis B Tree
Every insertion is starting with insert function in main.c file.
// 'insert funtion' located in 'bpt.c'
node * insert( node * root, int key, int value ) {...}In each cases below, the insert function does different operation.
If a duplicate value exists, ignore its insertion.
Duplicate value is checked by find function.
find function gets node which has proper range for the value by find_leaf function.
If there is no record having the value, find function returns NULL else it returns record having the value.
Summary for call path in this case.

First, it checks for the duplicate value, even though it is empty tree. (Case 1)
From now on Case 2's unique function call.
When tree does not exist yet, first it makes a new record for the value by make_record function and it builds a new tree by start_new_tree function with new record.
In start_new_tree function, it makes leaf node by make_leaf and make_node function.
Summary for call path in this case.

Suppose tree is not empty. It means we don't have to call functions to make new tree like Case 2.
First, do the duplicate value check. (Case 1)
Second, make a new record for the value. (Case 2)
From now on Case 3's unique function call.
It gets node which has appropriate position for the value by find_leaf function.
Node's num_keys is less than order - 1 means there is room for new record. So, just insert new record into node without splitting by insert_into_leaf function.
Summary for call path in this case.

Suppose tree is not empty. It means we don't have to call functions to make new tree like Case 2.
First, check the duplicate value. (Case 1)
Second, make a new record for the value. (Case 2)
Third, find appropriate leaf node for new record. (Case 3)
From now on Case 4's unique function call.
Node's num_key is not less then order - 1 means there is no room for new record. So, split node into two (original node + new node) and insert new record into appropriate node among them by insert_into_leaf_after_splitting function.
Make a new leaf node for splitting by make_leaf function.
We can know where to split in original node for splitting by cut function.
After split into two nodes, to add new node's key to parent node, call insert_into_parent function.
Summary for call path until now.

In Case 4, there are 3 different cases.
It means that tree needs new root. So, make a new root, insert new node's key into new root and let root's pointer points new children by insert_into_new_root function.
Summary for call path in this case.

Find original node's index in parent by get_left_index function to insert new node into right position of parent.
Parent's num_keys is less than order - 1 means there is room for new key. So, insert new key into parent without splitting by insert_into_node function.
Summary for call path in this case.

Find original node's index in parent by get_left_index function to insert new node into right position of parent.
Parent's num_keys is not less than order - 1 means there is no room for new key. So, split parent node and insert new key into right parent node by insert_into_node_after_splitting function.
In this case, we need recursive function call between insert_into_parent and insert_into_node_after_splitting. Because, split parents's parent can be split because of k_prime (no room for new key). If parents's parent has room for k_prime, we call insert_into_node function and recursive call ends.
Summary for call path in this case.

Every deletion is starting with delete and destroy_tree function in main.c file.
// 'deletion funtion' located in 'bpt.c'
node * delete(node * root, int key) {...}
node * destroy_tree(node * root) {...}destroy_tree function calls destroy_tree_nodes function and destroy_tree_nodes calls itself recursively until leaf node appears.
Summary for call path in this case.

It calls find and find_leaf functions to find key_record and key_leaf. If both of them are not NULL, call delete_entry function.
Remove record by remove_entry_from_node function.
Summary for call path until now.

Because it is root, we don't have to modify structure. Just call adjust_root function.
Summary for call path in this case.

min_keys is the value that limits the minimum value of num_keys in node. It is determined by cut function. If num_keys is equal or more than this, just return root in delete_entry function.
Summary for call path in this case.

Get neighbor_index by get_neighbor_index function. neighbor_index is nearest neighbor (sibling) index of parameter node. If neighbor is not exist, it returns -1 for special case.
Assume that just one coalesce_nodes function call can modify tree well.
If sum of neighbor node and me is less than capacity, do the merge by coalesce_nodes function. We should delete node which key is deleted from, because its all keys move to neighbor node, there is no keys. This can be dealt by delete_entry function.
In delete_entry function, deletion will end with Case 1 or 2.
Summary for call path in this case.
- Ends with Case 1

- Ends with Case 2

If sum of neighbor node and me is equal or more than capacity, do the split by redistribute_nodes function.
Summary for call path in this case.

In Case 3 - 1, if parent node's num_keys is less than min_keys, parent node needs adjust too by coalesce_nodes or redistribute_nodes function.
This case is terminated by 1, 2, 3 and be recursive by 4.
adjust_root- num_keys โฅ min_keys
- redistribute_nodes
- coalesce_nodes โ recursion
Summary for call path in this case.

insertion์ด ๋ฐ์ํ๋ฉด ์ ์ผ ๋จผ์ , find_leaf ํจ์๋ฅผ ์ด์ฉํด insert๋๋ record๊ฐ ๋ค์ด๊ฐ์ผ ํ๋ ์ ์ ํ leaf node๋ฅผ ์ฐพ์ต๋๋ค.
๋ง์ฝ ํด๋น leaf node๊ฐ ๊ฐ๋ ์ฐจ ์๋ค๋ฉด leaf node๋ฅผ ๋๊ฐ๋ก ๋ถํ ํด์ผ ํฉ๋๋ค.
leaf node๋ฅผ ๋ถํ ํ๊ณ record๋ฅผ insertํ๊ธฐ ์ํด์ insert_into_leaf_after_splitting ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
์ ํจ์์์ ์๋ก์ด leaf node๋ฅผ ์์ฑํ๊ณ record๊ฐ ๋ค์ด๊ฐ์ผ ํ๋ ์์น์ธ insertion_index๋ฅผ ์ฐพ์ต๋๋ค. insertion_index๋ record์ key ๋์๊ด๊ณ ๋น๊ต๋ฅผ ํตํด ์ฐพ์ ์ง๋๋ค.
temp_node์ ๊ธฐ์กด leaf node์ record๋ค๊ณผ insert๋ record๋ฅผ insertion_index๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ๋ง๊ฒ ๋ชจ๋ ์ฝ์ ํ ๋ค ๊ธฐ์กด leaf node์ record๋ค์ ๋ชจ๋ ์ญ์ ํฉ๋๋ค.
์ดํ cut ํจ์๋ฅผ ์ด์ฉํด temp_node ์์ record๋ค์ ๊ธฐ์กด์ leaf node์ ์๋ก ๋ง๋ leaf node์ ์ ์ ํ ๋ถ๋ฐฐํ๊ณ ์๋ก์ด leaf node์ parent๋ฅผ ๊ธฐ์กด์ leaf node์ parent์ ๊ฐ๊ฒ ๋ง๋ญ๋๋ค. ์์ ์ ์ ํ ๋ถ๋ฐฐ๋ cut ํจ์๋ก ์ป์ด์ง split ์์น ์ด์ ์ temp node record๋ค์ ๊ธฐ์กด์ leaf node์ ์ฝ์
ํ๊ณ split ์์น๋ถํฐ๋ ์๋ก์ด leaf node์ ์ฝ์
ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์์ ๊ณผ์ ์ ๊ฑฐ์น๋ฉด ์๋ก์ด key์ธ new_key๊ฐ ๋ง๋ค์ด ์ง๋๋ค.
์ด ๊ฒฝ์ฐ๋ ๊ธฐ์กด์ leaf node๊ฐ root node์ธ ๊ฒ์ ๋งํฉ๋๋ค. ๋ฐ๋ผ์ insert_into_new_root ํจ์๋ฅผ ์ด์ฉํด ์๋ก์ด root node๋ฅผ ์์ฑํ ๋ค ๊ธฐ์กด์ leaf node์ ์๋ก์ด leaf node๋ฅผ parent node์ ์ฐ๊ฒฐํฉ๋๋ค. ์์์ ์ธ๊ธํ new_key๋ root node์์ ๊ธฐ์กด์ leaf node์ ์๋ก์ด leaf node๋ฅผ ๊ฐ๋ฆฌํค๋ pointer ์ฌ์ด์ key๊ฐ ๋ฉ๋๋ค. ์ดํ split์ด ์ข
๋ฃ ๋ฉ๋๋ค.
Case 1์ ์กฐ๊ฑด์์ leaf node์์ split์ด ํ๋ฒ๋ง ๋ฐ์ํ๋ค๊ณ ๊ฐ์ ํ์๊ธฐ ๋๋ฌธ์ insert_into_node ํจ์๋ฅผ ์ฌ์ฉํด new_key๋ฅผ parent ๋
ธ๋์ ์ฝ์
ํ๊ณ parent์ pointer์ ์๋ก์ด leaf node๋ฅผ ์ฐ๊ฒฐํ ๋ค split์ด ์ข
๋ฃ ๋ฉ๋๋ค.
Case 1 - 2์์ ๊ธฐ์กด leaf node์ parent์ key์ ์๋ก์ด leaf node๊ฐ ๋ค์ด๊ฐ ๊ณต๊ฐ์ด ์๋ค๋ฉด (= parent node๊ฐ ๊ฐ๋ ์ฐจ ์๋ค๋ฉด), parent node๋ฅผ splitํ ๋ค new_key๊ฐ parent node์ ์ฝ์
๋์ด์ผ ํฉ๋๋ค. ์ด๋ insert_into_node_after_splitting ํจ์๋ฅผ ํตํด ์ด๋ฃจ์ด ์ง๋๋ค.
์ฌ๊ธฐ์ ๋ถํฐ ์์ parent node๋ฅผ old node, ๊ธฐ์กด์ leaf node๋ฅผ left node, ์ฝ์ ๋์ด์ผ ํ๋ new_key๋ฅผ key, ์๋ก์ด leaf node๋ฅผ right node๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค.
insert_into_node_after_splitting ํจ์์์ split๋ old node์ record๋ค์ด ๋ค์ด๊ฐ new_node๋ฅผ ๋ง๋ค๊ณ temp_keys, temp_pointers๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
old node์ key, pointer๋ค๊ณผ new_key, right node๋ฅผ temp_keys์ temp_pointers๋ก ์์์ ๋ง๊ฒ ์ฎ๊ฒจ ์ค๋๋ค. ์ฌ๊ธฐ์ ์์์ ๋ง๊ฒ๋ old node์ left node๋ฅผ ๊ฐ๋ฆฌํค๋ pointer์ ๋ฐ๋ก ๋ค์ pointer ์์น์ right node๋ฅผ ๊ฐ๋ฆฌํค๋ pointer๊ฐ, left node์ right node๋ฅผ ๊ฐ๋ฆฌํค๋ pointer ์ฌ์ด์ key๊ฐ ์ค๋๋ก (= temp_keys์์ key๊ฐ left node pointer index ์์น์ ์ค๋๋ก) ๋ฐฐ์นํ๋ ๊ฒ์ ๋งํฉ๋๋ค.
cut ํจ์๋ฅผ ํตํด split ์์น๋ฅผ ์ป์ต๋๋ค.
temp_keys์ split - 1 ์์น์ key๋ k_prime์ด ๋๊ณ k_prime ๊ธฐ์ค ์ผ์ชฝ์ old node๋ก ์ค๋ฅธ์ชฝ์ new node๋ก ์ฝ์ ํ ๋ค new node์ child๋ค์ parent๋ฅผ new node๋ก ๊ฐฑ์ ํ์ฌ ์ค๋๋ค. (k_prime์ ๊ธฐ์ค์ผ๋ก ์ก์ ๊ทผ๊ฑฐ๋, pointer์ key๋ค์ ๋ฐฐ์น๋ฅผ pointer[0] - key[0], pointer[1] - key[1], ... , pointer[x] - key[x] (=k_prime), ... , pointer[n-1] - key[n-1], pointer[n] ์ผ๋ก ๋ณด์์ ๋ ๊ธฐ์ค ์ ๋๋ค)
์์ ๊ณผ์ ์ด ์ข
๋ฃ๋๋ฉด insert_into_parent ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
๋ง์ฝ old node๊ฐ root๋ผ๋ฉด insert_into_new_root ํจ์๋ฅผ ํธ์ถํ์ฌ insertion์ด ์ข
๋ฃ๋ฉ๋๋ค.
๋ง์ฝ old node์ parent์ k_prime๊ณผ new node๊ฐ ์ฝ์
๋ ์๋ฆฌ๊ฐ ์๋ค๋ฉด insert_into_node ํจ์๋ฅผ ํตํด insertion์ด ์ข
๋ฃ๋ฉ๋๋ค.
๋ง์ฝ old node์ parent๊ฐ ๊ฐ๋ ์ฐฌ ์ํ๋ผ๋ฉด insert_into_node_after_splitting ํจ์๋ฅผ ํธ์ถํ์ฌ ์์ ๊ณผ์ ์ ๋ฐ๋ณต ์คํํฉ๋๋ค.
key๋ฅผ node์์ ์ญ์ ํ node์ key ๊ฐ์์ neighbor์ key ๊ฐ์์ ํฉ์ด capacity๋ณด๋ค ์ปค์ง๋ ๊ฒฝ์ฐ Redistribution์ ์คํํฉ๋๋ค.
Redistribution์ 2๊ฐ์ง ๊ฒฝ์ฐ๋ก ๋๋์ด ์ง๋๋ค.
์ด ๊ฒฝ์ฐ node์ neighbor๋ node์ ์ค๋ฅธ์ชฝ sibling์ด ๋ฉ๋๋ค.
2๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์กด์ฌํฉ๋๋ค
node์ ๋ง์ง๋ง key์ pointer์ ๋ค์ ์์น์ neighbor์ 0๋ฒ์งธ key์ pointer๋ฅผ ๊ฐ์ ธ์จ ๋ค node์ parent์ k_prime_index ์์น์ key์ neighbor์ 1๋ฒ์งธ key ๊ฐ์ ๋ณต์ฌ ํฉ๋๋ค.
neighbor๋ 0๋ฒ์งธ key์ pointer๋ฅผ node์๊ฒ ์ฃผ์๊ธฐ ๋๋ฌธ์ ์์ ์ key์ pointer๋ค์ ์์ผ๋ก ํ ์นธ์ฉ ์ ์ง ์ํต๋๋ค.
node์ ๋ง์ง๋ง key ๋ค์ ์์น์ k_prime์ ๊ฐ์ ธ์ค๊ณ , ๋ง์ง๋ง pointer์ ๋ค์ ์์น์ neighbor์ 0๋ฒ์งธ ํฌ์ธํฐ๋ฅผ ๊ฐ์ ธ์จ ๋ค ๊ฐ์ ธ์จ ํฌ์ธํฐ์ ๋ถ๋ชจ๋ฅผ node๋ก ๋ณ๊ฒฝํฉ๋๋ค. node์ parent์ k_prime_index ์์น์ key ๊ฐ์ neighbor์ 0๋ฒ์งธ key ๊ฐ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
neighbor๋ 0๋ฒ์งธ pointer๋ฅผ node์๊ฒ, 0๋ฒ์งธ key๋ฅผ parent์๊ฒ ์ฃผ์์ผ๋ฏ๋ก ์์ ์ key์ pointer๋ค์ ์์ผ๋ก ํ์นธ์ฉ ์ ์ง์ํต๋๋ค.
์ด ๊ฒฝ์ฐ node์ neighbor๋ node์ ์ผ์ชฝ sibling์ด ๋ฉ๋๋ค.
2๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์กด์ฌํฉ๋๋ค.
node์ key์ pointer๋ค์ ํ ์นธ์ฉ ๋ค๋ก ์ฎ๊ธด ๋ค neighbor์ ๋ง์ง๋ง key์ pointer๋ฅผ node์ 0๋ฒ์งธ key์ pointer๋ก ๊ฐ์ ธ์ต๋๋ค.
์ดํ node์ parent์ k_prime_index์ key ๊ฐ์ node์ 0๋ฒ์งธ key ๊ฐ์ผ๋ก ๋ณต์ฌํฉ๋๋ค.
node์ key์ pointer๋ค์ ํ ์นธ์ฉ ๋ค๋ก ์ฎ๊ธด ๋ค neighbor์ ๋ง์ง๋ง pointer๋ฅผ node์ 0๋ฒ์งธ pointer๋ก ๊ฐ์ ธ์ค๊ณ k_prime ๊ฐ์ node์ 0๋ฒ์งธ key๋ก ๊ฐ์ ธ์ต๋๋ค. ๊ฐ์ ธ์จ pointer์ parent๋ฅผ node๋ก ๋ณ๊ฒฝํฉ๋๋ค.
์ดํ parent์ k_prime_index ์์น์ key์ neighbor์ ๋ง์ง๋ง key๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
key๋ฅผ node์์ ์ญ์ ํ node์ key ๊ฐ์์ neighbor์ key ๊ฐ์์ ํฉ์ด capacity๋ณด๋ค ์์์ง๋ ๊ฒฝ์ฐ Coalesce์ ์คํํฉ๋๋ค.
๋ง์ฝ node์ neighbor๊ฐ node์ ์ค๋ฅธ์ชฝ sibling์ธ ๊ฒฝ์ฐ, node๊ฐ neighbor๋ฅผ ๊ฐ๋ฆฌํค๊ฒ neighbor๊ฐ node๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฐ๊พธ์ด ์ค๋๋ค.
Coalesce๋ 2๊ฐ์ง ๊ฒฝ์ฐ๋ก ๋๋์ด ์ง๋๋ค.
neighbor ๋ง์ง๋ง key์ pointer ๋ค์ node์ key์ pointer๋ฅผ ์์๋๋ก ์ฎ๊ธฐ๊ณ neighbor์ right sibling์ ๊ฐ๋ฆฌํค๋ pointer๋ฅผ node๊ฐ ๊ธฐ๋ฆฌํค๊ณ ์๋ right sibling์ผ๋ก ๋ณ๊ฒฝํด ์ค๋๋ค.
์ดํ delete_entry ๋ฅผ ํธ์ถํ์ฌ node์ parent์์ k_prime ์ญ์ ๋ฅผ ์งํํฉ๋๋ค.
neighbor์ ๋ง์ง๋ง key ๋ค์ ์์น์ k_prime์ ์ฝ์ ํฉ๋๋ค.
neighbor์ ๋ง์ง๋ง key์ pointer ๋ค์ ์์น์ node์ key์ pointer๋ฅผ ์์๋๋ก ์ฎ๊ธด ๋ค ์ฎ๊ธด pointer๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋ node๋ค์ parent๋ฅผ neighbor๋ก ๋ณ๊ฒฝํ์ฌ ์ค๋๋ค.
์ดํ delete_entry ๋ฅผ ํธ์ถํ์ฌ node์ parent์์ k_prime ์ญ์ ๋ฅผ ์งํํฉ๋๋ค.
Case 1, 2์์ delete_entry ํจ์๋ฅผ ํธ์ถํ๋ฉด 4๊ฐ์ง์ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๊ทธ ์ค 3๊ฐ์ง๋ deletion์ด ์ข
๋ฃ๋๊ฒ ๋๊ณ , 1๊ฐ์ง๋ ๋ค์ ์์ Coalesce๋ฅผ ๋ฐ์ ์ํต๋๋ค.
deletion์ด ์ข ๋ฃ๋๋ 3๊ฐ์ง ๊ฒฝ์ฐ
-
adjust_rootํจ์ ํธ์ถโ node์ parent๊ฐ root์ธ ๊ฒฝ์ฐ์ ๋๋ค. ์ฌ๊ธฐ์๋
adjust_rootํจ์ ๋ด๋ถ์์ root๋ฅผ ์ฌ์กฐ์ ํ ๋ค deletion์ด ์ข ๋ฃ ๋ฉ๋๋ค -
node์ parent์ num_keys๊ฐ min_keys๋ณด๋ค ํฐ ๊ฒฝ์ฐ
โ ์ด ๊ฒฝ์ฐ๋ tree๊ฐ modify๋ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ deletion์ด ์ข ๋ฃ ๋ฉ๋๋ค.
-
redistribute_nodesํจ์ ํธ์ถโ
redistribute_nodesํจ์ ๋ด๋ถ์์ ์ฌ๋ถ๋ฐฐ ํ deletion์ด ์ข ๋ฃ๋ฉ๋๋ค.
Coalesce๊ฐ ๋ค์ ๋ฐ์ํ๋ 1๊ฐ์ง ๊ฒฝ์ฐ
-
coalesce_nodesํจ์ ํธ์ถโ ์ด ๊ฒฝ์ฐ node์ parent์์ k_prime์ ์ญ์ ํ๋ฉด, parent์ num_keys์ parent ์ด์์ num_keys๊ฐ capacity ์ดํ๋ก ๋จ์ด์ง๋ค๋ ์๋ฏธ์ ๋๋ค. ๋ฐ๋ผ์ ์์ coalesce ๊ณผ์ ์ด ๋ฐ๋ณต๋ฉ๋๋ค.
๊ธฐ์กด์ b+ tree์์ ์ฌ์ฉ๋์๋ node๋ฅผ page๋ผ๋ ์๋ก์ด ๊ตฌ์กฐ์ฒด๋ก ๋ณ๊ฒฝํ์ฌ ์ฌ์ฉํ ๊ฒ ์ ๋๋ค.
page struct๋ 4096 bytes์ ๊ณ ์ ๋ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๋ฉฐ, 4๊ฐ์ง ์ข ๋ฅ์ ํ์ด์ง๊ฐ ์กด์ฌ ํฉ๋๋ค.
-
Header page
โ 8 bytes ํฌ๊ธฐ์ Free page number, Root page number, Number of pages๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ฐ๊ฐ ์ฒซ๋ฒ์งธ Free page number, Root page number, Page ๊ฐ์๋ฅผ ์๋ฏธํฉ๋๋ค.
-
Free page
โ 8 bytes ํฌ๊ธฐ์ Next free page number๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค. ์ด๋ ์์ ์ ๋ค์ free page number๋ฅผ ์๋ฏธํฉ๋๋ค.
-
Internal page
โ 128 bytes ํฌ๊ธฐ์ page header 1๊ฐ, 16 bytes์ leaf record 248๊ฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
-
Leaf page
โ 128 bytes ํฌ๊ธฐ์ page header 1๊ฐ, 128 bytes์ leaf record 31๊ฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
Internal page์ Leaf page์๋ ๊ฐ๊ฐ page header์ record๊ฐ ์กด์ฌํฉ๋๋ค.
-
Page header
โ 128 bytes์ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
โ 8 bytes ํฌ๊ธฐ์ Parent page number, Number of keys, 4 bytes์ is leaf ๊ฐ ์กด์ฌ ํฉ๋๋ค. ๊ฐ๊ฐ ์์ ์ parent page number, ๊ฐ์ง๊ณ ์๋ key์ ๊ฐ์, ์์ ์ด leaf page์ธ์ง ์๋์ง๋ฅผ ์๋ฏธํฉ๋๋ค.
โ Internal page์ ๊ฒฝ์ฐ 8 bytes ํฌ๊ธฐ์ One more page number๋ฅผ ๊ฐ์ง๋ฉฐ, ์ด๋ ์์ ์ record๊ฐ ๋ชจ๋ ์ฑ์์ก์ ๋ ๋ง์ง๋ง key๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ key๋ฅผ ๊ฐ์ง๋ page์ page number๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ์ํจ ์ ๋๋ค.
โ Leaf page์ ๊ฒฝ์ฐ 8 bytes ํฌ๊ธฐ์ Right sibling page number๋ฅผ ๊ฐ์ง๋ฉฐ, ์ด๋ ์์ ์ ์ค๋ฅธ์ชฝ ํ์ ์ page number๋ฅผ ์๋ฏธํฉ๋๋ค. ์ด๋ ๊ฒ ์ฌ์ฉํ๋ ์ด์ ๋ scan์ ํจ์จ์ฑ์ ๋์ด๊ธฐ ์ํจ ์ ๋๋ค.
-
Internal record
โ 8 bytes ํฌ๊ธฐ์ key์ page number๋ฅผ ๋ด๊ณ ์๋ ๊ตฌ์กฐ์ฒด ์ ๋๋ค.
-
Leaf record
โ 8 bytes ํฌ๊ธฐ์ key์ 120 bytes ํฌ๊ธฐ์ value๋ฅผ ๋ด๊ณ ์๋ ๊ตฌ์กฐ์ฒด ์ ๋๋ค.
๊ฐ๊ฐ์ page๋ ๋ชจ๋ 4096 bytes์ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๋๋ค.
4๊ฐ์ง ์ข ๋ฅ์ page๋ฅผ ๊ฐ๊ฐ struct๋ก ๊ตฌํ ํ struct page_t ๋ด๋ถ์์ union์ ์ฌ์ฉํ์ฌ 4๊ฐ์ง page๋ค์ page_t ํ์ ์ผ๋ก ํ๋ฒ์ ์ฌ์ฉ ํ ๊ฒ์ ๋๋ค.
internal page์ leaf page๋ ๋์ผํ struct page๋ก ๊ตฌํ ํ ๋ด๋ถ์ ์ผ๋ก ๋ค๋ฅธ ๋ถ๋ถ๋ง union์ ์ฌ์ฉํ์ฌ ๋์ page ํ์ ์ผ๋ก ํ๋ฒ์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ๋ด๋ถ์ ์ผ๋ก ๋ค๋ฅธ ๋ถ๋ถ์ด๋ one_more_pagenum๊ณผ right_sibling_pagenum, internal record์ leaf record๋ฅผ ๋งํฉ๋๋ค.
record์ ๊ฒฝ์ฐ internal record์ leaf record์ struct๋ฅผ ๊ฐ๊ฐ ๋ง๋ค์ด์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
์์ฝ : ์๋์ ๊ฐ์ ์ฝ๋๋ก page layout์ด ๋ง๋ค์ด ์ง๋๋ค.
/* struct which represents all kind of pages
* (header, free, internal, leaf)
*/
typedef struct page_t {
union {
// header page struct
headerPage h;
// free page struct
freePage f;
// struct for internal page and leaf page
page p;
};
} page_t;page๊ฐ ์์ ์ page number์ ๋ง๋ Disk file ์์น์ ์๋๋ก ๊ตฌ์ฑํ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ disk file์ ์์ ์์น๋ก ๋ถํฐ Page size (4096) * page number ๋งํผ ๋จ์ด์ง ์์น์ page๊ฐ ์กด์ฌํ๊ฒ ๊ตฌ์ฑํ๋ ๊ฒ์ ๋๋ค.
ํน๋ณํ header page๋ ํญ์ disk file์ offset 0๋ฒ ์์น์์ ์์ํ๋๋ก ๊ตฌ์ฑ ํ ๊ฒ์ ๋๋ค.
๊ฐ๊ฐ์ I/O๋ Disk Manager APIs๋ฅผ ํตํด ์ํ ๋๋ฉฐ, File APIs ๋ด๋ถ์์ page๋ฅผ ์ฝ์ด ์ค๊ฑฐ๋, ์ฝ์ด ์จ page์ ๋ด์ฉ์ ๋ณ๊ฒฝ์ด ์๊ธฐ๋ ์ฆ์ Disk Manager APIs ํธ์ถํ ๊ฒ์ ๋๋ค.
์ฆ, page๋ฅผ ์ฝ์ด ์์ page ๋ด๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ด์ผํ๋ ๊ฒฝ์ฐ, ์ฝ์ด ์จ page ๋ด๋ถ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ disk์ in-memory ์์ ๋ฐ์ดํฐ๊ฐ ๊ฐ์ง ์์ ๊ฒฝ์ฐ I/O๋ฅผ ์ํ ํ ๊ฒ์ ๋๋ค.
DB APIs๋ user์ db๊ฐ์ interaction์ ์ํ ํจ์๋ค์ ์ค๊ณํ ๊ฒ์ ๋๋ค.
int open_table(char* pathname);
int db_insert(int64_t key, char* value);
int db_delete(int64_t key);
int db_find(int64_t key, char* ret_val);์์ ํจ์๋ค์ ํตํด์ file API๋ฅผ ํธ์ถํ์ฌ db์ ์ ๊ทผ ํ ์ ์๋๋ก ํ ๊ฒ ์ ๋๋ค.
DB_API ์ฌ์ฉ์์ ๋ช ๋ น์ ๋ฐ์์ค๋ API ์ ๋๋ค.
File APIs๋ file์ ์๋ db ๋ด์ฉ์ ๋ด์ ์ค๊ธฐ ์ํ page์ ๋ํ ๊ตฌ์กฐ์ฒด๊ฐ ์ ์๋์ด ์์ผ๋ฉฐ, in-memory ์์์ DB APIs์ ์์ฒญ์ ์๋ง๋ ์์ ์ ์ํํ๋ ํจ์๊ฐ ์ ์๋์ด ์์ต๋๋ค.
๋ํ file์์ page๋ก ๊ฐ์ ์ฝ์ด ์ค๊ฑฐ๋, page์์ file๋ก ๊ฐ์ ์ธ ๋์ ๊ฐ์ด file๊ณผ page ๊ฐ์ ์ํธ์์ฉ์ด ํ์ํ ๋ ์ฌ์ฉ ๋๋ ํจ์๋ค์ด ์ค๊ณ๋ ๊ฒ ์ ๋๋ค.
์ฌ๊ธฐ์ Disk Manager APIs๋ฅผ ํธ์ถํ์ฌ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ฐ๊ฑฐ๋, ์ฝ์ด์ผ ํ ๊ฐ์ ์ฝ์ด ์ค๋ ์์ ์ ์ํํฉ๋๋ค.
File API๋ DB APIs์ ์์ฒญ์ ๋ฐ์ ์์ ์ ์ํํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ํ๊ธฐ ์ํด Disk Manager APIs๋ฅผ ํธ์ถํ๋ API ์ ๋๋ค.
Disk Manager APIs๋ memory ์์์ ์์ ๋ ์ ๋ณด๋ค์ ์ค์ disk์ ์จ์ฃผ๋ ์์ ์ ํ๋ ํจ์๋ค์ ์ค๊ณํ ๊ฒ ์ ๋๋ค.
์ค์ง Disk Manager APIs๋ฅผ ํตํด์๋ง disk์ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ๋ถ๋ฆฌํ๊ธฐ ์ํด์ ์ ๋๋ค.
Disk Manager APIs๋ File APIs๋ก ๋ถํฐ ์ฝ๊ธฐ ์ฐ๊ธฐ ์์ ์ ์์ฒญ ๋ฐ์ disk์ ์ง์ ์ ๊ทผํ์ฌ ์์ ์ ์งํํ๋ API ์ ๋๋ค.
๋ฐ๋ผ์ User โ DB APIs โ File APIs โ Disk Manager APIs โ Disk์ ๊ตฌ์กฐ๋ก top-down operation์ด ์ผ์ด๋๊ฒ ๋ ๋์์ธ ํ ๊ณํ์ ๋๋ค.