/** * Opens a directory in cache fs form (ie. client cached index + data files) */ int cache_open_fs_dir(cache_t* cache, const char* directory) { DIR *dir = opendir(directory); struct dirent *entry; int num_indices = 0; sorted_list_t* index_list = object_new(sorted_list); index_list->compare_func = strcmp_wrap; if (dir == NULL) { return 1; } char data_file[256]; while ((entry = readdir(dir)) != NULL) { if (strstr(entry->d_name, "idx")) { index_list_node_t* node = (index_list_node_t*)malloc(sizeof(index_list_node_t)); strcpy(node->index, entry->d_name); sorted_list_insert(index_list, &node->node); num_indices++; } else if (strstr(entry->d_name, "dat")) { sprintf(data_file, "%s/%s", directory, entry->d_name); } } if (data_file == NULL || num_indices == 0) { return 1; } char** index_files = (char**)malloc(sizeof(char*)*num_indices); int i = 0; while (!list_empty(&index_list->list)) { list_node_t* node = list_front(&index_list->list); index_list_node_t* index_node = container_of(node, index_list_node_t, node); index_files[i] = (char*)malloc(sizeof(char)*256); sprintf(index_files[i++], "%s/%s", directory, (char*)index_node->index); list_erase(&index_list->list, node); free(index_node); } object_free(index_list); closedir(dir); cache_open_fs(cache, num_indices, (const char**)index_files, data_file); for (int i = 0; i < num_indices; i++) { free(index_files[i]); } free(index_files); return 0; }
void make_screen_list() { hash_node_type* n = NULL; while(hash_next_item(screen_hash, &n) == HASH_STATUS_OK) { host_pair_line* line = (host_pair_line*)n->rec; int i; for(i = 0; i < HISTORY_DIVISIONS; i++) { line->recv[i] /= history_length(i); line->sent[i] /= history_length(i); } /* Don't make a new, sorted screen list if order is frozen */ if(!options.freezeorder) { sorted_list_insert(&screen_list, line); } } }
/* recv_window_receive takes in a window, a pointer, the length associated with the memory pointed to by that pointer, and also the sequence number of the given data (the first octet of that data). This function performs all the necessary sliding window functions, and then returns the ACK number to send back. If there is no such number (ie the window didn't slide at all, it will return -1. stores the data directly, so give it something that it can free! */ void recv_window_receive_synchronized(recv_window_t recv_window, void* data, uint32_t length, uint32_t seqnum){ int offset = recv_window_validate_seqnum(recv_window, seqnum, length); if(offset<0){ LOG(("seqnum %d not accepted. left: %d\n", seqnum, recv_window->left)); return; } if(length==0){ // then theres nothing to do return; } uint32_t to_write = MIN(length-offset, WRAP_DIFF(seqnum, (recv_window->left+recv_window->size)%MAX_SEQNUM, MAX_SEQNUM)); if(!to_write){ // then there's also nothing to do return; } /* if the data has a non-zero offset, then we will need to make a new chunk of data that the recv_chunk can point to so that when it frees that void* pointer it actually does something. Let me illustrate: void* chunk = malloc(100); free(chunk+1); // LEAK! free(chunk); // good */ if(offset > 0){ void* new_data = malloc(to_write); memcpy(new_data, data+offset, to_write); free(data); data = new_data; } int already_read_overlap = WRAP_DIFF((seqnum+offset)%MAX_SEQNUM, recv_window->read_left, MAX_SEQNUM); if(already_read_overlap >= 0) { to_write -= already_read_overlap; ext_array_push(recv_window->data_queue, data+already_read_overlap, to_write); free(data); recv_window->read_left += to_write; recv_window->available_size -= to_write; /* then go through and see if this connects to the next received_chunk */ recv_chunk_t next_chunk; int overlap; while((next_chunk = sorted_list_peek(recv_window->chunks_received))){ /* if the next chunk is farther along then the last byte that's been read, then just continue */ if(WRAP_DIFF(next_chunk->seqnum, recv_window->read_left, MAX_SEQNUM) < 0) break; // better be the same! next_chunk = sorted_list_pop(recv_window->chunks_received); /* check the overlap between the chunk that you've previously received and the chunk that was just read */ overlap = WRAP_DIFF(next_chunk->seqnum, recv_window->read_left, MAX_SEQNUM); /* if the overlap is less than the length of the chunk (ie the chunk that was in the received list isn't completely covered by the chunk taht was just pushed) then push its data */ if(overlap < next_chunk->length){ ext_array_push(recv_window->data_queue, next_chunk->data+overlap, next_chunk->length-overlap); /* only incremente the read_left/decrement the available size by the amount that you actually used from the most recent chunk */ recv_window->read_left += next_chunk->length-overlap; recv_window->available_size -= next_chunk->length-overlap; } /* destroy that chunk */ recv_chunk_destroy(&next_chunk); } } else { sorted_list_insert(recv_window->chunks_received, recv_chunk_init(seqnum, data, to_write)); } // inform any interested parties that you just got some new stuff pthread_cond_signal(&(recv_window->read_cond)); }