int main(int argc, char *argv[]) { if (argc > 1) { unsigned i; const unsigned nbArgs = argc; for (i = 1; i < nbArgs; ++i) { if (!strncmp(argv[i],"-debug",6)) /* FLAW */ { debug = true; printf("Move to debugging mode\n"); // for debugging code and process, let's say you need root rights if (strlen(argv[i]) >= 11 && !strncmp(argv[i]+6,":root",5)) { promote_root(); } } } } else { printf("No args...\n"); } return 0; }
// internal function to write keys static void write_key(btree * btree, search_result * insert_info, btree_key_t key, btree_data_t datum) { // check to see if page is full if (insert_info->m_page->m_key_count == btree->m_order) { // temporary arrays btree_key_t * temp_keys = (btree_key_t *)malloc(sizeof(btree_key_t) * (btree->m_order + 1)); btree_data_t * temp_data = (btree_data_t *)malloc(sizeof(btree_data_t) * (btree->m_order + 1)); // store new item temp_keys[insert_info->m_index] = key; temp_data[insert_info->m_index] = datum; // copy entries from insertion page to temps // TODO: change these to use pointers instead of indexes? int nt = 0; // index for temp arrays int ni = 0; // index for insertion page while (ni < btree->m_order) { // skip over inserted data if (ni == insert_info->m_index) ++nt; // copy data temp_keys[nt] = insert_info->m_page->m_keys[ni]; temp_data[nt] = insert_info->m_page->m_data[ni]; // next one ++ni; ++nt; } // create a new leaf btree_page * page_sibling = alloc_page(btree); // assign parent page_sibling->m_parent = insert_info->m_page->m_parent; // clear key counts insert_info->m_page->m_key_count = 0; page_sibling->m_key_count = 0; // copy keys from temp to pages for (ni = 0; ni < btree->m_min_keys; ++ni) { insert_info->m_page->m_keys[ni] = temp_keys[ni]; insert_info->m_page->m_data[ni] = temp_data[ni]; ++insert_info->m_page->m_key_count; } for (ni = btree->m_min_keys + 1; ni <= btree->m_order; ++ni) { page_sibling->m_keys[ni - 1 - btree->m_min_keys] = temp_keys[ni]; page_sibling->m_data[ni - 1 - btree->m_min_keys] = temp_data[ni]; ++page_sibling->m_key_count; } // replace remaining entries with null for (ni = btree->m_min_keys; ni < btree->m_order; ++ni) { insert_info->m_page->m_keys[ni] = NULL_KEY; insert_info->m_page->m_data[ni] = NULL_DATA; } // promote key and its pointer if (insert_info->m_page->m_parent == NULL) { // creating a new root page promote_root(btree, temp_keys[btree->m_min_keys], temp_data[btree->m_min_keys], insert_info->m_page, page_sibling); } else { // read parent btree_page * page_parent = insert_info->m_page->m_parent; // promote key into parent page promote_internal(btree, page_parent, temp_keys[btree->m_min_keys], temp_data[btree->m_min_keys], page_sibling); } // release sibling page free(temp_keys); free(temp_data); } else { // move keys to make room for new one for (int n = insert_info->m_page->m_key_count; n > insert_info->m_index; --n) { insert_info->m_page->m_keys[n] = insert_info->m_page->m_keys[n - 1]; insert_info->m_page->m_data[n] = insert_info->m_page->m_data[n - 1]; } insert_info->m_page->m_keys[insert_info->m_index] = key; insert_info->m_page->m_data[insert_info->m_index] = datum; ++insert_info->m_page->m_key_count; } }
// promote key into parent static void promote_internal(btree * btree, btree_page * page_insert, btree_key_t key, btree_data_t datum, btree_page * link) { if (page_insert->m_key_count == btree->m_order) { // temporary array btree_key_t * temp_keys = (btree_key_t *)malloc(sizeof(btree_key_t) * (btree->m_order + 1)); btree_data_t * temp_data = (btree_data_t *)malloc(sizeof(btree_data_t) * (btree->m_order + 1)); btree_page ** temp_links = (btree_page **)malloc(sizeof(btree_page *) * (btree->m_order + 2)); temp_links[0] = page_insert->m_links[0]; // copy entries from inapage to temps int nt = 0; int ni = 0; int insert_index = 0; // find insertion point while ((insert_index < page_insert->m_key_count) && (page_insert->m_keys[insert_index] < key)) ++insert_index; // store new info temp_keys[insert_index] = key; temp_data[insert_index] = datum; temp_links[insert_index + 1] = link; // copy existing keys while (ni < btree->m_order) { if (ni == insert_index) ++nt; temp_keys[nt] = page_insert->m_keys[ni]; temp_data[nt] = page_insert->m_data[ni]; temp_links[nt + 1] = page_insert->m_links[ni + 1]; ++ni; ++nt; } // generate a new leaf node btree_page * page_sibling = alloc_page(btree); page_sibling->m_parent = page_insert->m_parent; // clear key counts page_insert->m_key_count = 0; page_sibling->m_key_count = 0; page_insert->m_links[0] = temp_links[0]; // copy keys from temp to pages for (ni = 0; ni < btree->m_min_keys; ++ni) { page_insert->m_keys[ni] = temp_keys[ni]; page_insert->m_data[ni] = temp_data[ni]; page_insert->m_links[ni + 1] = temp_links[ni + 1]; ++page_insert->m_key_count; } page_sibling->m_links[0] = temp_links[btree->m_min_keys + 1]; for (ni = btree->m_min_keys + 1; ni <= btree->m_order; ++ni) { page_sibling->m_keys[ni - 1 - btree->m_min_keys] = temp_keys[ni]; page_sibling->m_data[ni - 1 - btree->m_min_keys] = temp_data[ni]; page_sibling->m_links[ni - btree->m_min_keys] = temp_links[ni + 1]; ++page_sibling->m_key_count; } // replace unused entries with null for (ni = btree->m_min_keys; ni < btree->m_order; ++ni) { page_insert->m_keys[ni] = NULL_KEY; page_insert->m_data[ni] = NULL_DATA; page_insert->m_links[ni + 1] = NULL; } // update parent links in child nodes for (ni = 0; ni <= page_sibling->m_key_count; ++ni) { btree_page * child = page_sibling->m_links[ni]; child->m_parent = page_sibling; } // promote key and pointer if (page_insert->m_parent == NULL) { // create a new root promote_root(btree, temp_keys[btree->m_min_keys], temp_data[btree->m_min_keys], page_insert, page_sibling); } else { // read parent and promote key btree_page * parent_page = page_insert->m_parent; promote_internal(btree, parent_page, temp_keys[btree->m_min_keys], temp_data[btree->m_min_keys], page_sibling); } // release resources free(temp_keys); free(temp_data); free(temp_links); } else { int insert_index = 0; // find insertion point while ((insert_index < page_insert->m_key_count) && (page_insert->m_keys[insert_index] < key)) ++insert_index; // shift keys right for (int n = page_insert->m_key_count; n > insert_index; --n) { page_insert->m_keys[n] = page_insert->m_keys[n - 1]; page_insert->m_data[n] = page_insert->m_data[n - 1]; page_insert->m_links[n + 1] = page_insert->m_links[n]; } page_insert->m_keys[insert_index] = key; page_insert->m_data[insert_index] = datum; page_insert->m_links[insert_index + 1] = link; ++page_insert->m_key_count; } }