struct keydb_node* keydb_find(int fd, char *key, int64_t pos) { // finds the node that matches key in the tree pointed at by pos. // returns a pointer that must be freed by the caller. int64_t n; struct keydb_node *buffer; int cmp; buffer = key_buf_read(fd, pos); if (buffer == NULL) return NULL; cmp = strncmp(buffer->column, key, KEY_LEN); if (cmp == 0) { if (pos != buffer->pos) fprintf(stderr, "positions don't match.\n"); return(buffer); } else if (cmp < 0) { // Go right pos = buffer->right; free(buffer); if (pos != 0) return(keydb_find(fd, key, pos)); } else { // Go left pos = buffer->left; free(buffer); if (pos != 0) return(keydb_find(fd, key, pos)); } return NULL; }
int composite_delete(int fd, struct keydb_column *tuple) { // Reduces the refcounts of the given list of key components into the keydb. int64_t pos = 0; struct keydb_node *node; //sem_wait(KEYDB_LOCK); while (tuple) { keydb_lock(pos); // Lock the tree we're deleting from. node = keydb_find(fd, tuple->column, pos); if (node == NULL) { //sem_post(KEYDB_LOCK); keydb_unlock(pos); return -1; } if (node->refcount == 0) { // nothing here. We can't lower refcount below zero. free(node); //sem_post(KEYDB_LOCK); keydb_unlock(pos); return(-1); } keydb_unlock(pos); pos = node->pos; keydb_lock(pos); node->refcount--; if ((pwrite(fd, node, sizeof(struct keydb_node), pos)) == -1) { fprintf(stderr, "Problem writing node at %llu in composite_delete().\n", pos); keydb_unlock(pos); return(-1); free(node); }; keydb_unlock(pos); pos = node->next; tuple = tuple->next; free(node); } //sem_post(KEYDB_LOCK); return 0; }
struct response_struct keys_command(char* token_vector[], int token_count) { char* part = NULL; char key[KEY_LEN] = ""; int length = 0; int i = 0; int retval; int64_t pos = 0; struct keydb_node *node; struct keydb_column *list, *tmp, *cursor; bool some_content = false; // Does our key list have any keys in it? list = NULL; char* tmp_response; int response_free_bytes = MSG_SIZE; int responselen = 0; int column_size; struct response_struct response; response.status = 0; if ((response.msg = malloc(sizeof(char) * MSG_SIZE)) == NULL) { perror(NULL); cleanup_and_exit(); } bzero(response.msg, MSG_SIZE); for (i = 1; (part = token_vector[i]) && (i < MAX_ARGS); i++) { length += strlen(part); if (length > KEY_LEN - 1) { response.status = 1; sprintf(response.msg, "Key too large."); return response; } node = keydb_find(KEYDB_FD, part, pos); if (!(node = keydb_find(KEYDB_FD, part, pos))) { response.status = 1; sprintf(response.msg, "Not found."); return response; } if (node->refcount <= 0) { response.status = 1; sprintf(response.msg, "Not found."); return response; } pos = node->next; free(node); if (pos == 0) { // There is no next subtree. response.status = 1; sprintf(response.msg, "No subkeys."); return response; } } keydb_tree(KEYDB_FD, pos, &list); while (list) { if (list->column[0] != '\0') { column_size = strlen(list->column) + 2; response_free_bytes -= column_size; if (response_free_bytes < 1) { // need to expand response. responselen = strlen(response.msg); responselen += column_size; tmp_response = malloc(sizeof(char) * responselen); strcpy(tmp_response, response.msg); free(response.msg); response.msg = tmp_response; response_free_bytes = 0; } strcat(response.msg, list->column); strcat(response.msg, " "); some_content = true; } tmp = list->next; free(list); list = tmp; } if (!some_content) { sprintf(response.msg, "No subkeys."); response.status = 1; } response.msg[strlen(response.msg) - 1] = '\0'; // Knock out that last extra space. return response; }