static void _root_update_thread () { error_t err; while (1) { if (hurd_condition_wait (&update_wakeup, &update_lock)) mutex_unlock (&update_lock); rwlock_writer_lock (&update_rwlock); do { ulfs_check(); err = node_init_root (netfs_root_node); } while (err == ENOENT); if (err) { fprintf (stderr, "update thread: got a %s\n", strerror (err)); } ncache_reset (); rwlock_writer_unlock (&update_rwlock); } }
static bool db_insert_try(struct DB *const db, struct KeyValue *const kv) { const uint64_t ticket = rwlock_writer_lock(&(db->rwlock)); struct Table *at = db->active_table[0]; const bool ri = table_insert_kv_safe(at, kv); rwlock_writer_unlock(&(db->rwlock), ticket); return ri; }
bool db_multi_insert(struct DB *const db, uint64_t nr_items, const struct KeyValue *const kvs) { uint64_t i = 0; while (i < nr_items) { const uint64_t ticket = rwlock_writer_lock(&(db->rwlock)); struct Table *at = db->active_table[0]; while (i < nr_items) { if (!table_insert_kv_safe(at, &kvs[i])) break; i++; } rwlock_writer_unlock(&(db->rwlock), ticket); if (i < nr_items) { db_wait_active_table(db); stat_inc(&(db->stat.nr_set_retry)); } } stat_inc_n(&(db->stat.nr_set), nr_items); return true; }
static void compaction_update_vc(struct Compaction *const comp) { const uint64_t ticket = rwlock_writer_lock(&(comp->db->rwlock)); struct VirtualContainer *const vc = comp->vc; // insert new mts for (uint64_t i = 0; i < 8; i++) { const bool ri = vc_insert_internal(vc->sub_vc[i], comp->mts_new[i], comp->mbcs_new[i]); assert(ri); } const uint64_t nr_keep = vc->cc.count - comp->nr_feed; // shift for (uint64_t i = 0; i < nr_keep; i++) { vc->cc.metatables[i] = vc->cc.metatables[i + comp->nr_feed]; } // NULL for (uint64_t i = nr_keep; i < DB_CONTAINER_NR; i++) { vc->cc.metatables[i] = NULL; } vc->cc.count = nr_keep; rwlock_writer_unlock(&(comp->db->rwlock), ticket); }
/* cvsfs_make_node * * create a struct node* for the specified netnode 'nn'. */ struct node * cvsfs_make_node(struct netnode *nn) { struct node *node; rwlock_writer_lock(&nn->lock); if(nn->node) { /* there already is a node structure, just return another reference * to this one, instead of wasting memory for yet another one */ mutex_lock(&nn->node->lock); netfs_nref(nn->node); mutex_unlock(&nn->node->lock); rwlock_writer_unlock(&nn->lock); return nn->node; } if(! (node = netfs_make_node(nn))) { rwlock_writer_unlock(&nn->lock); return NULL; } /* put timestamp on file */ fshelp_touch(&node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, cvsfs_maptime); /* initialize stats of new node ... */ node->nn_stat.st_fstype = FSTYPE_MISC; node->nn_stat.st_fsid = stat_template.fsid; node->nn_stat.st_ino = nn->fileno; node->nn_stat.st_mode = stat_template.mode; node->nn_stat.st_nlink = 1; node->nn_stat.st_uid = stat_template.uid; node->nn_stat.st_gid = stat_template.gid; node->nn_stat.st_size = 0; node->nn_stat.st_blksize = 4096; /* is there a better default?? */ node->nn_stat.st_blocks = 0; node->nn_stat.st_author = stat_template.author; if(! nn->revision) { /* we're creating a node for a directory, mark as such! */ node->nn_stat.st_mode |= S_IFDIR; /* since we got a directory we need to supply "executable" * permissions, so our user is enabled to make use of this dir */ if(node->nn_stat.st_mode & S_IRUSR) node->nn_stat.st_mode |= S_IXUSR; if(node->nn_stat.st_mode & S_IRGRP) node->nn_stat.st_mode |= S_IXGRP; if(node->nn_stat.st_mode & S_IROTH) node->nn_stat.st_mode |= S_IXOTH; } else { if(nn->revision->contents && ! config.nostats) { node->nn_stat.st_mode = nn->revision->perm; node->nn_stat.st_size = nn->revision->length; node->nn_stat.st_blocks = (node->nn_stat.st_size >> 9) + 1; node->nn_stat.st_atime = node->nn_stat.st_mtime = node->nn_stat.st_ctime = nn->revision->time; node->nn_stat.st_atime_usec = node->nn_stat.st_mtime_usec = node->nn_stat.st_ctime_usec = 0; } /* well, we're creating a new node for a file ... */ node->nn_stat.st_mode |= S_IFREG; /* for now simply drop all execute permissions, this needs to be fixed, * since CVS support executables, e.g. shell scripts, that we need to * support .... FIXME */ node->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH); }
// pthread static void *thread_active_dumper(void *ptr) { struct DB *const db = (typeof(db))ptr; conc_set_affinity_n(2); while (db->active_table[0]) { // active pthread_mutex_lock(&(db->mutex_active)); if ((db->active_table[0]->volume == 0) && db->closing) { pthread_mutex_unlock(&(db->mutex_active)); table_free(db->active_table[0]); db->active_table[0] = NULL; break; } while ((!table_full(db->active_table[0])) && (!db->closing)) { pthread_cond_wait(&(db->cond_active), &(db->mutex_active)); } // shift active table const uint64_t ticket1 = rwlock_writer_lock(&(db->rwlock)); db->active_table[1] = db->active_table[0]; if (db->closing) { db->active_table[0] = NULL; } else { db->active_table[0] = table_alloc_default(15.0); } rwlock_writer_unlock(&(db->rwlock), ticket1); // notify writers pthread_cond_broadcast(&(db->cond_writer)); pthread_mutex_unlock(&(db->mutex_active)); struct Table *const table1 = db->active_table[1]; if (containermap_unused(db->cms[0]) < 8u) { db_log(db, "ContainerMap is near full, dropping current active-table"); sleep(10); const uint64_t ticket2 = rwlock_writer_lock(&(db->rwlock)); db->active_table[1] = NULL; rwlock_writer_unlock(&(db->rwlock), ticket2); } else if (table1->volume > 0) { const bool rbt = table_build_bloomtable(table1); assert(rbt); const uint64_t mtid = db_table_dump(db, table1, 0); struct MetaTable *const mt = db_load_metatable(db, mtid, db->cms[0]->raw_fd, false); assert(mt); stat_inc_n(&(db->stat.nr_write[0]), TABLE_NR_BARRELS); mt->bt = table1->bt; // mark !active_table[1]->bt before free it // wait for room pthread_mutex_lock(&(db->mutex_current)); while (db->vcroot->cc.count == DB_CONTAINER_NR) { pthread_cond_wait(&(db->cond_root_producer), &(db->mutex_current)); } pthread_mutex_unlock(&(db->mutex_current)); // insert const uint64_t ticket2 = rwlock_writer_lock(&(db->rwlock)); const bool ri = vc_insert_internal(db->vcroot, mt, NULL); assert(ri); stat_inc(&(db->stat.nr_active_dumped)); // alert compaction thread if have work to be done if (db->vcroot->cc.count >= 8) { pthread_mutex_lock(&(db->mutex_current)); pthread_cond_broadcast(&(db->cond_root_consumer)); pthread_mutex_unlock(&(db->mutex_current)); } db->active_table[1] = NULL; rwlock_writer_unlock(&(db->rwlock), ticket2); // post process table1->bt = NULL; } table_free(table1); } pthread_exit(NULL); return NULL; }