int CS_putSegment(struct content_obj * prefix_obj, struct linked_list * content_chunks) { if (!prefix_obj || !content_chunks) return -1; struct CS_segment * segment = malloc(sizeof(struct CS_segment)); /* this is a content matching a prefix */ char * key = malloc(strlen(prefix_obj->name->full_name)); strcpy(key, prefix_obj->name->full_name); segment->index_chunk = prefix_obj; segment->num_chunks = content_chunks->len; segment->chunks = malloc(sizeof(struct content_obj * ) * segment->num_chunks); segment->valid = bit_create(segment->num_chunks); pthread_mutex_init(&segment->lock, NULL); int i = 0; while (content_chunks->len) { bit_set(segment->valid, i); segment->chunks[i++] = linked_list_remove(content_chunks, 0); } pthread_mutex_lock(&_cs.lock); hash_put(_cs.table, key, (void * ) segment); pthread_mutex_unlock(&_cs.lock); return 0; }
int test_base_bitset(const char* param) { rand_seed((uint32_t)time(NULL)); // bit create int size = param ? atoi(param) : rand() % 1024; bit_t* bit = bit_create(size); if (!bit) { fprintf(stderr, "bit create fail\n"); return -1; } // bit set int test_size = (size >> 1); for (int i = 0; i < test_size; ++ i) { bit_set(bit, i); } // bit is set for (int i = 0; i < size; ++ i) { if (i < test_size && bit_isset(bit, i)) { fprintf(stderr, "bit-set error\n"); bit_release(bit); return -1; } if (i >= test_size && bit_isset(bit, i) == 0) { fprintf(stderr, "bit-set error\n"); bit_release(bit); return -1; } } // bit count if (bit_count(bit) != test_size) { fprintf(stderr, "bit-count = %d error\n", bit_count(bit)); bit_release(bit); return -1; } // bit reset -> bit count for (int i = 0; i < test_size; ++ i) { bit_reset(bit, i); } if (bit_count(bit) != 0) { fprintf(stderr, "bit-count error\n"); bit_release(bit); return -1; } bit_release(bit); return 0; }
int CS_put(struct content_obj * content) { content = content_copy(content); log_assert(g_log, content != NULL, "CS: failed to allocate content"); pthread_mutex_lock(&_cs.lock); struct CS_segment * segment = (struct CS_segment * ) hash_get(_cs.table, content_prefix(content->name)); pthread_mutex_unlock(&_cs.lock); int rv = 0; if (content_is_segmented(content->name)) { if (segment) { pthread_mutex_lock(&segment->lock); int seq_no = content_seq_no(content->name); if (seq_no >= segment->num_chunks) { segment->chunks = realloc(segment->chunks, sizeof(struct content_obj * ) * (seq_no + 1)); segment->num_chunks = seq_no + 1; segment->chunks[seq_no] = content; struct bitmap * larger = bit_create(segment->num_chunks); memcpy(larger->map, segment->valid->map, segment->valid->num_words); bit_destroy(segment->valid); segment->valid = larger; bit_set(larger, seq_no); } else { if (bit_test(segment->valid, seq_no)) { content_obj_destroy(segment->chunks[seq_no]); } segment->chunks[seq_no] = content; bit_set(segment->valid, seq_no); } pthread_mutex_unlock(&segment->lock); } else { rv = -1; } } else { if (!segment) { segment = malloc(sizeof(struct CS_segment)); /* this is a content matching a prefix */ char * key = malloc(strlen(content->name->full_name)); strcpy(key, content->name->full_name); segment->index_chunk = content; segment->chunks = NULL; segment->num_chunks = -1; segment->valid = bit_create(0); pthread_mutex_init(&segment->lock, NULL); pthread_mutex_lock(&_cs.lock); hash_put(_cs.table, key, (void * ) segment); pthread_mutex_unlock(&_cs.lock); } else { pthread_mutex_lock(&segment->lock); if (segment->index_chunk) { content_obj_destroy(segment->index_chunk); } segment->index_chunk = content; pthread_mutex_unlock(&segment->lock); } } return rv; }
/*{{{ shape -- reshape a window to specified dimensions*/ int shape(int x, int y, int dx, int dy) { int sx, sy, w, h; WINDOW *win; if (dx > 0) { sx = x; w = dx; } else { sx = x + dx; w = -dx; } if (dy > 0) { sy = y; h = dy; } else { sy = y + dy; h = -dy; } if (sx < 0) sx = 0; if (sx + w >= BIT_WIDE(screen)) w = BIT_WIDE(screen) - sx; if (sy + h >= BIT_HIGH(screen)) h = BIT_HIGH(screen) - sy; if (w < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.wide * MIN_X || h < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.high * MIN_Y) return (-1); #ifdef MGR_ALIGN alignwin(screen, &sx, &w, ACTIVE(borderwid)); #endif /* remove current window position */ save_win(active); erase_win(ACTIVE(border)); clip_bad(active); /* invalidate clip lists */ /* redraw remaining windows */ repair(active); /* adjust window state */ ACTIVE(x0) = sx; ACTIVE(y0) = sy; bit_destroy(ACTIVE(window)); bit_destroy(ACTIVE(border)); ACTIVE(border) = bit_create(screen, sx, sy, w, h); ACTIVE(window) = bit_create(ACTIVE(border), ACTIVE(borderwid), ACTIVE(borderwid), w - ACTIVE(borderwid) * 2, h - ACTIVE(borderwid) * 2); for (win = ACTIVE(next); win != (WINDOW *)0; win = W(next)) { if (W(flags) & W_ACTIVE && intersect(active, win)) save_win(win); } CLEAR(ACTIVE(window), PUTOP(BIT_CLR, ACTIVE(style))); border(active, BORDER_THIN); bit_blit(ACTIVE(border), 0, 0, BIT_WIDE(ACTIVE(save)) - ACTIVE(borderwid), BIT_HIGH(ACTIVE(save)) - ACTIVE(borderwid), BIT_SRC, ACTIVE(save), 0, 0); /* make sure character cursor is in a good spot */ if (ACTIVE(x) > BIT_WIDE(ACTIVE(window))) { ACTIVE(x) = 0; ACTIVE(y) += ((int)(ACTIVE(font)->head.high)); } if (ACTIVE(y) > BIT_HIGH(ACTIVE(window))) { #ifdef WIERD ACTIVE(y) = BIT_HIGH(ACTIVE(window)); scroll(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)), ((int)(ACTIVE(font)->head.high)), SWAPCOLOR(ACTIVE(style))); bit_blit(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high)), BIT_WIDE(ACTIVE(save)), ((int)(ACTIVE(font)->head.high)), BIT_SRC, ACTIVE(save), ACTIVE(borderwid), BIT_HIGH(ACTIVE(save)) - ((int)(ACTIVE(font)->head.high)) - ACTIVE(borderwid)); #else ACTIVE(y) = BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high)); #endif } bit_destroy(ACTIVE(save)); ACTIVE(save) = (BITMAP *)0; /* invalidate clip lists */ clip_bad(active); un_covered(); set_size(active); return (0); }
void test_bit(void) { int i; void* B = bit_create(10); fprintf(stdout, "call function : %s\n", __func__); bit_object_show(B); fprintf(stdout, "\ntest function - bit_set/bit_get ===>\n"); { srand((unsigned int)time(0)); for (i = 0; i < bit_size(B); ++i) bit_set(B, i, rand() % 2); bit_object_show(B); for (i = 0; i < bit_size(B); ++i) fprintf(stdout, "\tbit values [%02d] => %d\n", i, bit_get(B, i)); } fprintf(stdout, "\ntest function - bit_clear_range ===>\n"); { bit_clear_range(B, 0, 4); bit_object_show(B); bit_for_each(B, bit_object_bit_show, NULL); } fprintf(stdout, "\ntest function - bit_set_range ===>\n"); { bit_set_range(B, 5, 9); bit_object_show(B); bit_for_each(B, bit_object_bit_show, NULL); } fprintf(stdout, "\ntest function - bit_not_range ===>\n"); { bit_not_range(B, 0, 9); bit_object_show(B); bit_for_each(B, bit_object_bit_show, NULL); } fprintf(stdout, "\ntest function - bit_clear ===>\n"); { bit_clear(B); bit_object_show(B); } fprintf(stdout, "\ntest function - bit_release ===>\n"); bit_release(&B); bit_object_show(B); fprintf(stdout, "\ntest function - bit_lt/bit_eq/bit_leq ===>\n"); { void* B1 = bit_create(5); void* B2 = bit_create(5); srand((unsigned int)time(0)); for (i = 0; i < 5; ++i) { bit_set(B1, i, rand() % 2); bit_set(B2, i, rand() % 2); } fprintf(stdout, " B1 object show:\n"); bit_for_each(B1, bit_object_bit_show, NULL); fprintf(stdout, " B2 object show:\n"); bit_for_each(B2, bit_object_bit_show, NULL); fprintf(stdout, " B1 < B2 ? '%s'\n", bit_lt(B1, B2) ? "yes" : "no"); fprintf(stdout, " B1 = B2 ? '%s'\n", bit_eq(B1, B2) ? "yes" : "no"); fprintf(stdout, " B1 <= B2 ? '%s'\n", bit_leq(B1, B2) ? "yes" : "no"); bit_release(&B1); bit_release(&B2); } fprintf(stdout, "\ntest function - union/inter/minus/diff ===>\n"); { void* B1 = bit_create(5); void* B2 = bit_create(5); srand((unsigned int)time(0)); for (i = 0; i < 5; ++i) { bit_set(B1, i, rand() % 2); bit_set(B2, i, rand() % 2); } fprintf(stdout, " B1 object show:\n"); bit_for_each(B1, bit_object_bit_show, NULL); fprintf(stdout, " B2 object show:\n"); bit_for_each(B2, bit_object_bit_show, NULL); B = bit_union(B1, B2); fprintf(stdout, " B1 union B2 ->\n"); bit_for_each(B, bit_object_bit_show, NULL); bit_release(&B); B = bit_inter(B1, B2); fprintf(stdout, " B1 inter B2 ->\n"); bit_for_each(B, bit_object_bit_show, NULL); bit_release(&B); B = bit_minus(B1, B2); fprintf(stdout, " B1 minus B2 ->\n"); bit_for_each(B, bit_object_bit_show, NULL); bit_release(&B); B = bit_diff(B1, B2); fprintf(stdout, " B1 diff B2 ->\n"); bit_for_each(B, bit_object_bit_show, NULL); bit_release(&B); bit_release(&B1); bit_release(&B2); } }
static int retrieve_segment(struct segment * seg) { char proc[256]; snprintf(proc, 256, "rsg%u", g_nodeId); prctl(PR_SET_NAME, proc, 0, 0, 0); int rv = -1; log_print(g_log, "retrieve_segment: trying to retrieve segment %s[%d - %d].", seg->name->full_name, 0, seg->num_chunks-1); pthread_mutex_lock(&g_lock); int retries = g_interest_attempts; int timeout_ms = g_timeout_ms; pthread_mutex_unlock(&g_lock); int ttl = MAX_TTL; if ((seg->opts->mode & CCNFDNB_USE_RETRIES) == CCNFDNB_USE_RETRIES) { retries = seg->opts->retries; } if ((seg->opts->mode & CCNFDNB_USE_TIMEOUT) == CCNFDNB_USE_TIMEOUT) { timeout_ms = seg->opts->timeout_ms; } if ((seg->opts->mode & CCNFDNB_USE_TTL) == CCNFDNB_USE_TTL) { ttl = seg->opts->ttl; } struct chunk chunk_window[MAX_INTEREST_PIPELINE]; PENTRY _pit_handles[MAX_INTEREST_PIPELINE]; int pit_to_chunk[PIT_SIZE]; memset(&pit_to_chunk, 0, sizeof(pit_to_chunk)); struct bitmap * window = bit_create(MAX_INTEREST_PIPELINE); struct bitmap * missing = bit_create(seg->num_chunks); char str[MAX_NAME_LENGTH], comp[MAX_NAME_LENGTH]; strncpy(str, seg->name->full_name, seg->name->len); int rtt_est = timeout_ms; int cwnd = 1; int ssthresh = DEFAULT_INTEREST_PIPELINE; int fullfilled = 0; int min_rtt_est = 10; int current_chunk = 0; cc_state state = SLOW_START; int tx; _segment_q_t seg_q; pthread_mutex_init(&seg_q.mutex, NULL); pthread_cond_init(&seg_q.cond, NULL); seg_q.rcv_window = 0; seg_q.max_window = &cwnd; seg_q.rcv_chunks = linked_list_init(NULL); seg_q.base = seg->name; ccnfdnl_reg_segment(&seg_q); int i; window->num_bits = cwnd; while (!bit_allSet(missing)) { tx = cwnd; window->num_bits = cwnd; log_debug(g_log, "state = %d, cwnd = %d, ssthresh = %d rtt_est = %d", state, cwnd, ssthresh, rtt_est); while (tx && (current_chunk < seg->num_chunks)) { snprintf(comp, MAX_NAME_LENGTH - seg->name->len, "/%d", current_chunk); strncpy(str + seg->name->len, comp, seg->name->len); i = bit_find(window); if (i < 0 || i >= MAX_INTEREST_PIPELINE) { /* we must still be waiting for data */ break; } chunk_window[i].intr.name = content_name_create(str); chunk_window[i].intr.ttl = ttl; chunk_window[i].seq_no = current_chunk; chunk_window[i].retries = retries; _pit_handles[i] = PIT_get_handle(chunk_window[i].intr.name); if (!_pit_handles[i]) { bit_clear(window, i); break; } pit_to_chunk[_pit_handles[i]->index] = i; pthread_mutex_unlock(_pit_handles[i]->mutex); struct content_obj * co = CS_get(chunk_window[i].intr.name); if (!co) { log_debug(g_log, "expressing new interest: %s", chunk_window[i].intr.name->full_name); ccnfdnb_fwd_interest(&chunk_window[i].intr); tx--; } else { log_debug(g_log, "retrieved %s from CS", co->name->full_name); PENTRY pe = PIT_exact_match(chunk_window[i].intr.name); *pe->obj = co; pthread_mutex_unlock(pe->mutex); pthread_mutex_lock(&seg_q.mutex); linked_list_append(seg_q.rcv_chunks, pe); seg_q.rcv_window++; pthread_mutex_unlock(&seg_q.mutex); } current_chunk++; } log_debug(g_log, "tx window full"); pthread_mutex_lock(&seg_q.mutex); if (seg_q.rcv_chunks->len == 0) { struct timespec wait; ts_fromnow(&wait); ts_addms(&wait, 2 * rtt_est); rv = pthread_cond_timedwait(&seg_q.cond, &seg_q.mutex, &wait); if ((rv == ETIMEDOUT) && !seg_q.rcv_chunks->len) { /* we timed out, we need to rtx */ rtt_est += rtt_est / 2; if (rtt_est > PIT_LIFETIME_MS) rtt_est = PIT_LIFETIME_MS / 2; } } else { int pit_ages = 0; int pits_fulfilled = 0; while (seg_q.rcv_chunks->len > 0) { PENTRY pe = linked_list_remove(seg_q.rcv_chunks, 0); log_assert(g_log, pe != NULL, "invalid pit entry"); pthread_mutex_lock(pe->mutex); log_debug(g_log, "pit entry %s fulfilled", (*pe->obj)->name->full_name); int chunk_id = pit_to_chunk[pe->index]; log_assert(g_log, chunk_id >= 0, "invalid chunk id"); if (chunk_window[chunk_id].seq_no == 0) { seg->obj->publisher = (*pe->obj)->publisher; seg->obj->timestamp = (*pe->obj)->timestamp; seg->chunk_size = (*pe->obj)->size; } int offset = chunk_window[chunk_id].seq_no * seg->chunk_size; memcpy(&seg->obj->data[offset], (*pe->obj)->data, (*pe->obj)->size); content_obj_destroy(*pe->obj); struct timespec now; ts_fromnow(&now); ts_addms(&now, PIT_LIFETIME_MS); pit_ages += PIT_age(pe); pits_fulfilled++; pit_to_chunk[pe->index] = -1; PIT_release(pe); free(_pit_handles[chunk_id]); _pit_handles[chunk_id] = NULL; bit_clear(window, chunk_id); bit_set(missing, chunk_window[chunk_id].seq_no); log_debug(g_log, "retrieved chunk %s", chunk_window[chunk_id].intr.name->full_name); content_name_delete(chunk_window[chunk_id].intr.name); chunk_window[chunk_id].intr.name = NULL; cwnd++; if (state == CONG_AVOID) fullfilled++; } rtt_est -= floor(pit_ages / pits_fulfilled); if (rtt_est < min_rtt_est) rtt_est = min_rtt_est; } pthread_mutex_unlock(&seg_q.mutex); for (i = 0; i < MAX_INTEREST_PIPELINE; i++) { if (bit_test(window, i)) { if (!_pit_handles[i]) { continue; } pthread_mutex_lock(_pit_handles[i]->mutex); if (PIT_age(_pit_handles[i]) > (2 * rtt_est)) { PIT_refresh(_pit_handles[i]); chunk_window[i].retries--; ccnfdnb_fwd_interest(&chunk_window[i].intr); log_debug(g_log, "rtx interest: %s (rtt = %d)", chunk_window[i].intr.name->full_name, rtt_est); ssthresh = cwnd / 2 + 1; cwnd = 1; state = SLOW_START; } pthread_mutex_unlock(_pit_handles[i]->mutex); } } if ((cwnd >= ssthresh) && (state == SLOW_START)) state = CONG_AVOID; if (state == SLOW_START) fullfilled = 0; if ((fullfilled == cwnd) && (state == CONG_AVOID)) { cwnd++; fullfilled = 0; } if (cwnd > MAX_INTEREST_PIPELINE) cwnd = MAX_INTEREST_PIPELINE; /*log_debug(g_log, "cwnd = %d, ssthresh = %d", cwnd, ssthresh);*/ } log_debug(g_log, "retrieve_segment: finished for %s[%d-%d]", seg->name->full_name, 0, seg->num_chunks-1); rv = 0; PIT_print(); ccnfdnl_unreg_segment(&seg_q); pthread_mutex_destroy(&seg_q.mutex); pthread_cond_destroy(&seg_q.cond); while (seg_q.rcv_chunks->len) { PENTRY pe = linked_list_remove(seg_q.rcv_chunks, 0); content_obj_destroy(*pe->obj); PIT_release(pe); } bit_destroy(window); bit_destroy(missing); return rv; }