view src/objstore/mem/main.c @ 158:efde22afef53

objstore/mem: root obj should have nlink = 1 Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sun, 18 Oct 2015 16:21:57 -0400
parents 6dd1b43f0589
children
line wrap: on
line source

/*
 * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <sys/avl.h>
#include <stdlib.h>
#include <stddef.h>

#include <nomad/error.h>
#include <nomad/time.h>
#include <nomad/rand.h>
#include <nomad/atomic.h>
#include <nomad/mutex.h>
#include <nomad/objstore_impl.h>

/* each <oid,ver> */
struct memobj {
	/* key */
	struct noid oid;
	struct nvclock *ver;

	/* value */
	struct nattr attrs;
	void *blob;

	/* misc */
	avl_node_t node;
};

/* the whole store */
struct memstore {
	avl_tree_t objs;
	struct memobj *root;

	uint32_t ds; /* our dataset id */
	atomic64_t next_oid_uniq; /* the next unique part of noid */

	pthread_mutex_t lock;
};

static int cmp(const void *va, const void *vb)
{
	const struct memobj *a = va;
	const struct memobj *b = vb;
	int ret;

	ret = noid_cmp(&a->oid, &b->oid);
	if (ret)
		return ret;

	return nvclock_cmp_total(a->ver, b->ver);
}

static struct memobj *newobj(uint16_t mode)
{
	struct memobj *obj;
	int ret;

	ret = ENOMEM;

	obj = malloc(sizeof(struct memobj));
	if (!obj)
		goto err;

	obj->ver = nvclock_alloc();
	if (!obj->ver)
		goto err;

	ret = nvclock_set(obj->ver, 1);
	if (ret)
		goto err_vector;

	obj->attrs._reserved = 0;
	obj->attrs.mode = mode;
	obj->attrs.nlink = 0;
	obj->attrs.size = 0;
	obj->attrs.atime = gettime();
	obj->attrs.btime = obj->attrs.atime;
	obj->attrs.ctime = obj->attrs.atime;
	obj->attrs.mtime = obj->attrs.atime;

	return obj;

err_vector:
	nvclock_free(obj->ver);

err:
	free(obj);

	return ERR_PTR(ret);
}

static int mem_vol_create(struct objstore_vol *store)
{
	struct memstore *ms;
	struct memobj *obj;

	ms = malloc(sizeof(struct memstore));
	if (!ms)
		return ENOMEM;

	atomic_set(&ms->next_oid_uniq, 1);
	avl_create(&ms->objs, cmp, sizeof(struct memobj),
		   offsetof(struct memobj, node));

	mxinit(&ms->lock);

	ms->ds = rand32();

	obj = newobj(NATTR_DIR | 0777);
	if (IS_ERR(obj)) {
		free(ms);
		return PTR_ERR(obj);
	}

	obj->attrs.nlink = 1;
	noid_set(&obj->oid, ms->ds, atomic_inc(&ms->next_oid_uniq));

	ms->root = obj;
	avl_add(&ms->objs, obj);

	store->private = ms;

	return 0;
}

static int mem_vol_getroot(struct objstore_vol *store, struct nobjhndl *hndl)
{
	struct memstore *ms;

	if (!store || !store->private || !hndl)
		return EINVAL;

	ms = store->private;

	mxlock(&ms->lock);
	hndl->oid = ms->root->oid;
	hndl->clock = nvclock_dup(ms->root->ver);
	mxunlock(&ms->lock);

	if (!hndl->clock)
		return ENOMEM;

	return 0;
}

static int mem_obj_getattr(struct objstore_vol *vol, const struct nobjhndl *hndl,
			   struct nattr *attr)
{
	struct memstore *ms;
	struct memobj *obj;
	struct memobj key;
	int ret;

	if (!vol || !hndl || !attr)
		return EINVAL;

	ms = vol->private;

	key.oid = hndl->oid;
	key.ver = hndl->clock;

	mxlock(&ms->lock);

	obj = avl_find(&ms->objs, &key, NULL);
	if (!obj) {
		ret = ENOENT;
	} else {
		ret = 0;
		*attr = obj->attrs;
	}

	mxunlock(&ms->lock);

	return ret;
}

static const struct vol_ops vol_ops = {
	.create = mem_vol_create,
	.getroot = mem_vol_getroot,
};

static const struct obj_ops obj_ops = {
	.getattr = mem_obj_getattr,
};

const struct objstore_vol_def objvol = {
	.name = "mem",
	.vol_ops = &vol_ops,
	.obj_ops = &obj_ops,
};