/* first calls search_by_key, then, if item is not found looks for the entry inside directory item indicated by search_by_key. (We assign a key to each directory item, and place multiple entries in a single directory item.) Fills the path to the entry, and to the entry position in the item */ int search_by_entry_key (struct super_block * sb, struct key * key, struct path * path, int * pos_in_item, int * repeat) { /* search for a directory item using key of entry */ if (search_by_key (sb, key, path, repeat, DISK_LEAF_NODE_LEVEL, READ_BLOCKS) == ITEM_FOUND) { *pos_in_item = 0; return POSITION_FOUND; } #ifdef REISERFS_CHECK if (!PATH_LAST_POSITION (path)) reiserfs_panic (sb, "vs-7000: search_by_entry_key: search_by_key returned item position == 0"); #endif /* REISERFS_CHECK */ PATH_LAST_POSITION (path) --; #ifdef REISERFS_CHECK { struct item_head * ih = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), PATH_LAST_POSITION (path)); if (!I_IS_DIRECTORY_ITEM (ih) || COMP_SHORT_KEYS (&(ih->ih_key), key)) { print_block (PATH_PLAST_BUFFER (path), 0, -1, -1); reiserfs_panic (sb, "vs-7005: search_by_entry_key: found item %h is not directory item or " "does not belong to the same directory as key %k", ih, key); } } #endif /* REISERFS_CHECK */ /* binary search in directory item by third component of the key */ return bin_search_in_dir_item (PATH_PITEM_HEAD (path), B_I_DEH (PATH_PLAST_BUFFER (path), PATH_PITEM_HEAD (path)), key, pos_in_item); }
static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, struct path * path_to_entry, struct reiserfs_dir_entry * de) { struct key key_to_search; int repeat; int retval; if (!dir || !dir->i_sb) return POSITION_NOT_FOUND; if ((unsigned int)namelen > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize)) return POSITION_NOT_FOUND; /* there are no entries having the same third component of key, so fourth key component is not used */ copy_key (&key_to_search, INODE_PKEY (dir)); key_to_search.k_offset = get_third_component (name, namelen); key_to_search.k_uniqueness = DIRENTRY_UNIQUENESS; while (1) { /* search for a directory item using the formed key */ if (search_by_key (dir->i_sb, &key_to_search, path_to_entry, &repeat, DISK_LEAF_NODE_LEVEL, READ_BLOCKS) == ITEM_NOT_FOUND) { /* take previous item */ #ifdef REISERFS_CHECK if (!PATH_LAST_POSITION (path_to_entry)) reiserfs_panic (dir->i_sb, "vs-7010: reiserfs_find_entry: search_by_key returned bad position == 0"); #endif /* REISERFS_CHECK */ PATH_LAST_POSITION (path_to_entry) --; } de->de_bh = PATH_PLAST_BUFFER (path_to_entry); de->de_item_num = PATH_LAST_POSITION (path_to_entry); de->de_ih = B_N_PITEM_HEAD (de->de_bh, de->de_item_num); de->de_deh = B_I_DEH (de->de_bh, de->de_ih); #ifdef REISERFS_CHECK if (!I_IS_DIRECTORY_ITEM (de->de_ih) || COMP_SHORT_KEYS (&(de->de_ih->ih_key), INODE_PKEY (dir))) reiserfs_panic (dir->i_sb, "vs-7020: reiserfs_find_entry: item must be an item of the same directory item as inode"); #endif /* REISERFS_CHECK */ /* we do not check whether bin_search_in_dir_item found the given key, even if so, we still have to compare names */ bin_search_in_dir_item (de->de_ih, de->de_deh, &key_to_search, &(de->de_entry_num)); /* compare names for all entries having given hash value */ retval = linear_search_in_dir_item (&key_to_search, de, name, namelen); if (retval != GOTO_PREVIOUS_ITEM) /* there is no need to scan directory anymore. Given entry found or does not exist */ return retval; /* there is left neighboring item of this directory and given entry can be there */ key_to_search.k_offset = de->de_ih->ih_key.k_offset - 1; pathrelse (path_to_entry); } /* while (1) */ }
void run_test (FILE *data_stream, FILE *test_in, FILE *test_out) { int num_of_request; unsigned short ordered_rids[100]; char num_of_request_str[10]; char target_key[20]; struct page result; num_of_request = atoi (fget_num (num_of_request_str, 10, test_in)); while (num_of_request--) { init_page (&result, true); fget_num (target_key, 20, test_in); // Get a request. if (search_by_key (target_key, &result, data_stream)) // sth worng here!!! { sort_record_in_page (&result, 2, ordered_rids); put_result (&result, ordered_rids, test_out); } else fprintf (test_out, "%d\r\n", -1); } }