int main(int argc, char *argv[]) { setbuf(stdout,NULL); stress_test(1 << 2); struct s_arena *arena = new_arena(); for(int i = 0;i < 10; i++) { struct s_cache *sc = new_cache(arena,i,0); print_cache(sc); } struct s_cache *sc1 = new_cache(arena,7,4); struct s_cache *sc2 = new_cache(arena,1,3); printf("Alloc1: %p\n", s_alloc(saved_gc, sc1)); printf("Alloc1: %p\n", s_alloc(saved_gc, sc1)); printf("Alloc1: %p\n", s_alloc(saved_gc, sc1)); printf("Alloc2: %p\n", s_alloc(saved_gc, sc2)); printf("Alloc2: %p\n", s_alloc(saved_gc, sc2)); printf("Alloc2: %p\n", s_alloc(saved_gc, sc2)); print_cache(sc1); print_cache(sc2); return 0; }
static int caching_list_directory(const char *path, dir_entry **list) { pthread_mutex_lock(&dmut); if (!strcmp(path, "/")) path = ""; dir_cache *cw; for (cw = dcache; cw; cw = cw->next) if (!strcmp(cw->path, path)) break; if (!cw) { if (!cloudfs_list_directory(path, list)) return 0; cw = new_cache(path); } else if (cache_timeout > 0 && (time(NULL) - cw->cached > cache_timeout)) { if (!cloudfs_list_directory(path, list)) return 0; cloudfs_free_dir_list(cw->entries); cw->cached = time(NULL); } else *list = cw->entries; cw->entries = *list; pthread_mutex_unlock(&dmut); return 1; }
int main(int argc, char **argv) { if(argc>1) { int i; for(i=1;i<argc;i++) { if(strcmp("-p",*(argv+i))==0) // push updates PUSH_UPDATES = 1; else { printf("Unrecognized argument.\n"); printf("Usage ---------------------->\n" "-p\tActivate Push Updates\n"); exit(EXIT_FAILURE); } } } start_listener(); // handles incoming messages. see listener.c listener.h for more info. start_sender(); // handles outgoing messages. see sender.c, sender.h "" "" "" clients_cache = new_cache(-1); for(;;) { } return 0; }
cache *find_cache( cache **rsc, struct s_arena *arena, unsigned short size, unsigned short num_ptrs ) { if (!*rsc) { *rsc = new_cache( arena, size, num_ptrs ); } return *rsc; }
static bool load_cache(RECPOS r) { cache_ptr = new_cache(); if(!read_if(r, (char *)&BUFBLOCK(cache_ptr), sizeof(BLOCK))) { DD("error in file %s line %d:\n", __FILE__, __LINE__); return FALSE; } else { return TRUE; } }
static void update_dir_cache(const char *path, off_t size, int isdir, int islink) { pthread_mutex_lock(&dmut); dir_cache *cw; dir_entry *de; char dir[MAX_PATH_SIZE]; dir_for(path, dir); for (cw = dcache; cw; cw = cw->next) { if (!strcmp(cw->path, dir)) { for (de = cw->entries; de; de = de->next) { if (!strcmp(de->full_name, path)) { de->size = size; pthread_mutex_unlock(&dmut); return; } } de = (dir_entry *)malloc(sizeof(dir_entry)); de->size = size; de->isdir = isdir; de->islink = islink; de->name = strdup(&path[strlen(cw->path)+1]); de->full_name = strdup(path); if (isdir) { de->content_type = strdup("application/link"); } if(islink) { de->content_type = strdup("application/directory"); } else { de->content_type = strdup("application/octet-stream"); } de->last_modified = time(NULL); de->next = cw->entries; cw->entries = de; if (isdir) new_cache(path); break; } } pthread_mutex_unlock(&dmut); }
int mutualproximity::set_normtracks( musly_track** tracks, int length) { new_cache(length); int track_size = m->track_getsize(); for (int i = 0; i < length; i++) { std::copy(tracks[i], tracks[i]+track_size, norm_tracks[i]); } return 0; }
//check for file in cache, if found size will be updated, if not found //and this is a dir, a new dir cache entry is created void update_dir_cache(const char* path, off_t size, int isdir, int islink) { debugf(DBG_LEVEL_EXTALL, KCYN "update_dir_cache(%s)", path); pthread_mutex_lock(&dcachemut); dir_cache* cw; dir_entry* de; char dir[MAX_PATH_SIZE]; dir_for(path, dir); for (cw = dcache; cw; cw = cw->next) { if (!strcmp(cw->path, dir)) { for (de = cw->entries; de; de = de->next) { if (!strcmp(de->full_name, path)) { de->size = size; pthread_mutex_unlock(&dcachemut); debugf(DBG_LEVEL_EXTALL, "exit 0: update_dir_cache(%s)", path); return; } } de = init_dir_entry(); de->size = size; de->isdir = isdir; de->islink = islink; de->name = strdup(&path[strlen(cw->path) + 1]); de->full_name = strdup(path); //fixed: the conditions below were mixed up dir -> link? if (islink) de->content_type = strdup("application/link"); if (isdir) de->content_type = strdup("application/directory"); else de->content_type = strdup("application/octet-stream"); de->next = cw->entries; cw->entries = de; if (isdir) new_cache(path); break; } } debugf(DBG_LEVEL_EXTALL, "exit 1: update_dir_cache(%s)", path); pthread_mutex_unlock(&dcachemut); }
void Square::generateStep(const float duty) { if (duty <= 0.0f || duty >= 1.0f) return; int8_t onTime = (int8_t) (1.0f / (duty <= 0.5f ? duty : (1.0f - duty))) - 1; if (onTime > 32767) return; pair<int8_t, vector<float >> nc; for (auto now = Square::cache.begin(); now != Square::cache.end(); now++) { if (now->first == onTime) { nc = *now; break; } } if (nc.second.empty()) { int8_t* l = new int8_t[onTime + 1]; if (duty <= 0.5f) { // 10, 100, 1000, ... l[0] = (int8_t) 1; } else { // 10, 110, 1110, ... for (int i = 0; i < onTime; i++) l[i] = (int8_t) 1; } this->setStep(l, onTime + 1); pair<int8_t, vector<float >> new_cache(onTime, this->value); Square::cache.push_front(new_cache); if (Square::cache.size() > 32) Square::cache.pop_back(); delete[] l; } else { this->value = nc.second; this->length = (float) nc.second.size(); } }
/* insert new entries into tree */ static bool split(int l, ENTRY *pe, ENTRY *e) { int half, ins_pos, size; ins_pos = CO(pci->level); half = scan_blk(block_ptr->bend / 2 + sizeof(RECPOS)); if (half == ins_pos) { *e = *pe; } else { copy_entry(e, ENT_ADR(block_ptr, half)); size = ENT_SIZE(e); movedown(block_ptr, half, size); block_ptr->bend -= size; update_root(block_ptr); } spare_block = &BUFBLOCK(new_cache()); memcpy(spare_block->entries, ENT_ADR(block_ptr,half), block_ptr->bend - half); spare_block->brec = get_free(); spare_block->bend = block_ptr->bend - half; spare_block->p0 = e->idxptr; block_ptr->bend = half; e->idxptr = spare_block->brec; if (ins_pos < half) { ins_block(block_ptr,pe,ins_pos); } else if (ins_pos > half) { ins_pos -= ENT_SIZE(e); ins_block(spare_block,pe,ins_pos - half); CB(l) = e->idxptr; CO(l) = CO(l) - half; } write_if(pci->ixfile, spare_block->brec,(char *) spare_block, sizeof(BLOCK)); return TRUE; }
/* create(Cache :: atom(), MaxSize :: integer(), MinQ1Size :: integer()) */ static ERL_NIF_TERM create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM atom; ErlNifUInt64 max_size, min_q1_size; struct cache *c; if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); atom = argv[0]; if (!enif_get_uint64(env, argv[1], &max_size)) return enif_make_badarg(env); if (!enif_get_uint64(env, argv[2], &min_q1_size)) return enif_make_badarg(env); if ((c = get_cache(atom))) { ERL_NIF_TERM ret = enif_make_atom(env, "already_exists"); enif_consume_timeslice(env, 5); enif_rwlock_rwlock(c->cache_lock); /* expansion is safe because we don't have to engage the background thread and won't cause sudden eviction pressure TODO: a nice way to shrink the cache without seizing it up */ if (c->max_size < max_size && c->min_q1_size < min_q1_size) { c->max_size = max_size; c->min_q1_size = min_q1_size; enif_rwlock_rwunlock(c->cache_lock); ret = enif_make_atom(env, "ok"); enif_consume_timeslice(env, 10); } else { enif_rwlock_rwunlock(c->cache_lock); } return ret; } else { c = new_cache(atom, max_size, min_q1_size); enif_consume_timeslice(env, 20); return enif_make_atom(env, "ok"); } }
void stress_test(int n) { jhc_alloc_init(); struct s_arena *arena = new_arena(); struct s_cache *caches[NUM_CACHES]; void *ptrs[n]; memset(ptrs,0,n*sizeof(void *)); for(int i = 0; i < NUM_CACHES; i++) caches[i] = new_cache(arena,sizeof(void *)*(i + 1), 0); for(int i = 0; i < FACTOR * n; i++) { int wp = rand() % n; if (ptrs[wp]) { //s_free(ptrs[wp]); //free(ptrs[wp]); ptrs[wp] = NULL; } else { ptrs[wp] = s_alloc(saved_gc, caches[rand() % NUM_CACHES]); //ptrs[wp] = malloc((rand() % NUM_CACHES) * sizeof(uintptr_t)); } } }
void Triangle::generateStep(const int step) { if (step <= 0 || step >= 256) return; pair<int8_t, vector<float >> nc; for (auto now = Triangle::cache.begin(); now != Triangle::cache.end(); now++) { if (now->first == step) { nc = *now; break; } } if (nc.second.empty()) { int8_t* l = new int8_t[step * 2]; for (int i = 0; i < step; i++) l[i] = (int8_t) i; for (int i = step; i < step * 2; i++) l[i] = (int8_t) (step * 2 - i - 1); this->setStep(l, step * 2); pair<int8_t, vector<float >> new_cache(step, this->value); Triangle::cache.push_front(new_cache); if (Triangle::cache.size() > 32) Triangle::cache.pop_back(); delete[] l; } else { this->value = nc.second; this->length = (float) nc.second.size(); } }
mutualproximity::~mutualproximity() { // clear cache new_cache(0); }
int main(int argc, char **argv) { pthread_mutex_init(&heart,NULL); // protects the beat counter pthread_mutex_init(&con,NULL); // protects the default server connection value from badly-timed updates pthread_mutex_init(&queue,NULL); // protects the cache from poorly-timed access cache = new_cache(-1); // creates query cache with default size (when arg is < 0, MAX_SIZE used. See cache.h clients = new_cache(100); // creates a cache of connected clients pending_queries = new_cache(100); // creates a cache of pending updates. When client requests a value that // must be retrieved from the database, the client's callback information is stored here until the DB query // is completed. /* Read command-line arguments */ if(argc>1) { int x; for(x=1;x<argc;x++) { // database addr if(strcmp("-d",*(argv + x))==0) { if(strlen( *(argv + x + 1) )>0) { strcpy(database_addr,*(argv + x + 1)); } else { usage(); } } else if(strcmp("-P",*(argv + x))==0) { pthread_t pull_thread; pthread_create(&pull_thread,NULL,(void *)pull_updater,(void *)cache); } else if(strcmp("-C",*(argv + x))==0) { pthread_t updater; pthread_create(&updater,NULL,(void *)caco,NULL); } else if(strcmp("-n",*(argv + x))==0) { strcpy(neighbor_addr,*(argv + x + 1)); } else if(strcmp("-S",*(argv + x))==0) { server_id = atoi(*(argv + x + 1)); } } } else { usage(); } start_listener(); start_sender(); // wait for all threads to come online sleep(2); while(server_id==0); /* Begin the heartbeat between this host and its neighbor */ char h_msg[CONTENT_MAX]; sprintf(h_msg,"%s,%d,NULL",hea,server_id); while(sender_queue==NULL); message_host(neighbor_addr,h_msg); /* End Heartbeat. Should be cycling now */ for(;;) { // neighbor recovered! if(beat_count == 0 && solo == 1) { // if we took over the Caco process for another server, shut it down now if(!CACO_SERVER) { printf("\n\n** ATTENTION! ***************************\n"); printf("****** CANCELING CACO UPDATER ************\n"); printf("******************************************\n\n"); pthread_cancel(caco_thread); } solo = 0; printf("\n\n** ATTENTION! ****************************\n"); printf("** NEIGHBOR BACK ONLINE *******************\n"); printf("*******************************************\n\n"); struct cache_entry *client; int x; /* Inform all adopted clients that the other server is back online */ for(x=0;x<clients->length;x++) { client = get_index(x,clients); // only message clients of the other front-end server if(client->server_id==server_id) continue; char r_msg[CONTENT_MAX]; sprintf(r_msg,"%s,%s,NULL",rea,neighbor_addr); message_host(client->value,r_msg); } } pthread_mutex_lock(&heart); beat_count++; // we'll wait until HEARTBEAT_DELAY has elapsed before we declare the other // server dead. // assume we've lost the neighbor if(beat_count==HEARTBEAT_DELAY) { // If we need to take over the Caco process for the other server, start it now. if(!CACO_SERVER) { printf("\n\n** NOTICE *************************\n"); printf("** taking over caco updater *******\n"); printf("***********************************\n\n"); pthread_create(&caco_thread,NULL,caco,NULL); } // sets the state-var solo, indicating that we are running alone solo = 1; printf("\n\n** NOTICE *************************.\n"); printf("** LOST CONTACT WITH NEIGHBOR SERVER **\n"); printf("** ASSUMING RESPONSIBILITY ************\n"); printf("***************************************\n\n"); struct cache_entry *client; int x; /* Adopt the clients from the other server. Notify them of the changes */ for(x=0;x<clients->length;x++) { client = get_index(x,clients); // only message clients of the other front-end server if(client->server_id==server_id) continue; char r_msg[CONTENT_MAX]; char addr[CONTENT_MAX]; get_local_addr(addr); sprintf(r_msg,"%s,%s,NULL",rea,addr); message_host(client->value,r_msg); } } pthread_mutex_unlock(&heart); sleep(1); } return 0; }
//returns first file entry in linked list. if not in cache will be downloaded. int caching_list_directory(const char* path, dir_entry** list) { debugf(DBG_LEVEL_EXT, "caching_list_directory(%s)", path); pthread_mutex_lock(&dcachemut); bool new_entry = false; if (!strcmp(path, "/")) path = ""; dir_cache* cw; for (cw = dcache; cw; cw = cw->next) { if (cw->was_deleted == true) { debugf(DBG_LEVEL_EXT, KMAG"caching_list_directory status: dir(%s) is empty as cached expired, reload from cloud", cw->path); if (!cloudfs_list_directory(cw->path, list)) debugf(DBG_LEVEL_EXT, KMAG"caching_list_directory status: cannot reload dir(%s)", cw->path); else { debugf(DBG_LEVEL_EXT, KMAG"caching_list_directory status: reloaded dir(%s)", cw->path); //cw->entries = *list; cw->was_deleted = false; cw->cached = time(NULL); } } if (cw->was_deleted == false) { if (!strcmp(cw->path, path)) break; } } if (!cw) { //trying to download this entry from cloud, list will point to cached or downloaded entries if (!cloudfs_list_directory(path, list)) { //download was not ok pthread_mutex_unlock(&dcachemut); debugf(DBG_LEVEL_EXT, "exit 0: caching_list_directory(%s) "KYEL"[CACHE-DIR-MISS]", path); return 0; } debugf(DBG_LEVEL_EXT, "caching_list_directory: new_cache(%s) "KYEL"[CACHE-CREATE]", path); cw = new_cache(path); new_entry = true; } else if (cache_timeout > 0 && (time(NULL) - cw->cached > cache_timeout)) { if (!cloudfs_list_directory(path, list)) { //mutex unlock was forgotten pthread_mutex_unlock(&dcachemut); debugf(DBG_LEVEL_EXT, "exit 1: caching_list_directory(%s)", path); return 0; } //fixme: this frees dir subentries but leaves the dir parent entry, this confuses path_info //which believes this dir has no entries if (cw->entries != NULL) { cloudfs_free_dir_list(cw->entries); cw->was_deleted = true; cw->cached = time(NULL); debugf(DBG_LEVEL_EXT, "caching_list_directory(%s) "KYEL"[CACHE-EXPIRED]", path); } else { debugf(DBG_LEVEL_EXT, "got NULL on caching_list_directory(%s) "KYEL"[CACHE-EXPIRED w NULL]", path); pthread_mutex_unlock(&dcachemut); return 0; } } else { debugf(DBG_LEVEL_EXT, "caching_list_directory(%s) "KGRN"[CACHE-DIR-HIT]", path); *list = cw->entries; } //adding new dir file list to global cache, now this dir becomes visible in cache cw->entries = *list; pthread_mutex_unlock(&dcachemut); debugf(DBG_LEVEL_EXT, "exit 2: caching_list_directory(%s)", path); return 1; }
static ERL_NIF_TERM put(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM atom; ErlNifBinary kbin, vbin; struct cache *c; struct cache_node *n, *ng; ErlNifUInt64 lifetime = 0; if (!enif_is_atom(env, argv[0])) return enif_make_badarg(env); atom = argv[0]; if (!enif_inspect_binary(env, argv[1], &kbin)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[2], &vbin)) return enif_make_badarg(env); if ((c = get_cache(atom))) { enif_consume_timeslice(env, 1); } else { /* if we've been asked to put() in to a cache that doesn't exist yet then we should create it! */ ErlNifUInt64 max_size, min_q1_size; if (!enif_get_uint64(env, argv[3], &max_size)) return enif_make_badarg(env); if (!enif_get_uint64(env, argv[4], &min_q1_size)) return enif_make_badarg(env); c = new_cache(atom, max_size, min_q1_size); enif_consume_timeslice(env, 20); } if (argc > 5) if (!enif_get_uint64(env, argv[5], &lifetime)) return enif_make_badarg(env); n = enif_alloc(sizeof(*n)); memset(n, 0, sizeof(*n)); n->c = c; n->vsize = vbin.size; n->ksize = kbin.size; n->size = vbin.size + kbin.size; n->key = enif_alloc(kbin.size); memcpy(n->key, kbin.data, kbin.size); n->val = enif_alloc_resource(value_type, vbin.size); memcpy(n->val, vbin.data, vbin.size); n->q = &(c->q1); if (lifetime) { clock_now(&(n->expiry)); n->expiry.tv_sec += lifetime; } enif_rwlock_rwlock(c->cache_lock); enif_rwlock_rwlock(c->lookup_lock); HASH_FIND(hh, c->lookup, kbin.data, kbin.size, ng); if (ng) { enif_mutex_lock(c->ctrl_lock); destroy_cache_node(ng); enif_mutex_unlock(c->ctrl_lock); } TAILQ_INSERT_HEAD(&(c->q1.head), n, entry); c->q1.size += n->size; HASH_ADD_KEYPTR(hh, c->lookup, n->key, n->ksize, n); if (lifetime) { struct cache_node *rn; rn = RB_INSERT(expiry_tree, &(c->expiry_head), n); /* it's possible to get two timestamps that are the same, if this happens just bump us forwards by 1 usec until we're unique */ while (rn != NULL) { ++(n->expiry.tv_nsec); rn = RB_INSERT(expiry_tree, &(c->expiry_head), n); } } enif_rwlock_rwunlock(c->lookup_lock); enif_rwlock_rwunlock(c->cache_lock); enif_cond_broadcast(c->check_cond); enif_consume_timeslice(env, 50); return enif_make_atom(env, "ok"); }