Пример #1
0
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);
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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);
}
Пример #5
0
/* 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);
    }
Пример #6
0
// 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;
}