Mercurial > nomad
view src/objstore/include/nomad/objstore_backend.h @ 555:0e7e00acfe88
objstore: maintain a tree of head object versions
We must keep track of which versions are heads in order to properly
determine which version to use when handling unqualified opens.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 15 Nov 2018 17:24:12 -0500 |
parents | 4b1b3fffdf7b |
children | 62cb9de73005 |
line wrap: on
line source
/* * Copyright (c) 2015-2018 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. */ #ifndef __NOMAD_OBJSTORE_BACKEND_H #define __NOMAD_OBJSTORE_BACKEND_H #include <jeffpc/rbtree.h> #include <nomad/objstore.h> enum obj_state { OBJ_STATE_NEW = 0, /* newly allocated */ OBJ_STATE_LIVE, /* fully initialized */ OBJ_STATE_DEAD, /* initialization failed */ }; struct obj { /* key */ struct noid oid; /* value */ struct rb_tree versions;/* cached versions */ struct rb_tree heads; /* head versions */ uint64_t nversions; /* number of versions */ uint32_t nlink; /* file link count */ void *private; /* misc */ enum obj_state state; refcnt_t refcnt; struct lock lock; struct rb_node node; /* constant for the lifetime of the object */ struct objstore *vol; const struct obj_ops *ops; }; struct objver { /* key */ struct nvclock *clock; /* value */ /* * Everything in the attrs structure is used for attribute storage * except for: * - nlink: use nlink field in struct obj */ struct nattr attrs; void *private; /* * Keep track of opens - both qualified and unqualified. * * ->open[0 aka. false] = unqualified * ->open[1 aka. true] = qualified */ struct objstore_open_obj_info *open[2]; /* misc */ struct obj *obj; struct rb_node all_node; /* all versions */ struct rb_node head_node; /* head versions */ }; struct objstore_open_obj_info { /* constant for the lifetime of this struct */ struct obj *obj; /* protected by the obj lock */ struct objver *ver; uint32_t open_count; }; struct obj_ops { /* * Determine if a specified version of an object exists. * * This is meant as a lightweight check to avoid allocating an * objver only to have to free it on error. * * If not implemented, the normal getattr call is used all the time. */ int (*checkversion)(struct obj *obj, const struct nvclock *clock); /* open objects must be closed */ int (*open)(struct objver *ver); int (*close)(struct objver *ver); /* cloned objects must be committed/aborted */ int (*clone)(); /* * create a new temp obj as a copy of * existing obj */ int (*commit)(); /* make temp object live */ int (*abort)(); /* delete temp object */ int (*getattr)(struct objver *ver, struct nattr *attr); int (*setattr)(struct objver *ver, struct nattr *attr, const unsigned valid); ssize_t (*read)(struct objver *ver, void *buf, size_t len, uint64_t offset); ssize_t (*write)(struct objver *ver, const void *buf, size_t len, uint64_t offset); int (*lookup_one)(struct objver *dirver, const char *name, const struct noid *desired, struct noid *child, uint8_t *type); int (*create)(struct objver *dirver, const char *name, uint16_t mode, struct noid *child); int (*unlink)(struct objver *dirver, const char *name, struct obj *child); int (*getdent)(struct objver *dirver, const uint64_t offset, struct ndirent *child); /* * Called just before the generic object is freed. */ void (*free)(struct obj *obj); }; struct vol_ops { int (*getroot)(struct objstore *vol, struct noid *root); /* * Initialize an object. * * At a minimum, the backend must: * - set obj->nversions * - set obj->ops * - add head versions to obj->versions * * Typically, the backend also: * - sets obj->private */ int (*initobj)(struct obj *obj); }; struct objstore_vdev_def { const char *name; int (*create_vdev)(struct objstore_vdev *vdev); int (*create_vol)(struct objstore *vol); int (*import_vdev)(struct objstore_vdev *vdev); }; extern struct objver *obj_add_version(struct obj *obj, const struct nvclock *clock); #endif