diff options
Diffstat (limited to 'xlators/meta/src/tree.c')
-rw-r--r-- | xlators/meta/src/tree.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/xlators/meta/src/tree.c b/xlators/meta/src/tree.c new file mode 100644 index 00000000000..ec88c42a084 --- /dev/null +++ b/xlators/meta/src/tree.c @@ -0,0 +1,176 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> + +#include "glusterfs.h" +#include "xlator.h" + +#include "meta.h" + +static int +is_meta_path (const char *path) +{ + while (*path == '/') + path++; + if (!strncmp (path, ".meta", strlen (".meta"))) + return 1; + return 0; +} + +struct stat * +new_stbuf (void) +{ + static int next_inode = 0; + struct stat *stbuf = CALLOC (1, sizeof (struct stat)); + + ERR_ABORT (stbuf); + + stbuf->st_dev = 0; + stbuf->st_ino = next_inode++; + stbuf->st_mode = S_IRUSR | S_IRGRP | S_IROTH; + stbuf->st_nlink = 1; + stbuf->st_uid = 0; + stbuf->st_gid = 0; + stbuf->st_rdev = 0; + stbuf->st_size = 0; + stbuf->st_blksize = 0; + stbuf->st_blocks = 0; + stbuf->st_atime = time (NULL); + stbuf->st_atim.tv_nsec = 0; + stbuf->st_mtime = stbuf->st_atime; + stbuf->st_mtim.tv_nsec = 0; + stbuf->st_ctime = stbuf->st_ctime; + stbuf->st_ctim.tv_nsec = 0; + + return stbuf; +} + +/* find an entry among the siblings of an entry */ +static meta_dirent_t * +find_entry (meta_dirent_t *node, const char *dir) +{ + meta_dirent_t *trav = node; + while (trav) { + if (!strcmp (trav->name, dir)) + return trav; + trav = trav->next; + } + return NULL; +} + +/* + * Return the meta_dirent_t corresponding to the pathname. + * + * If pathname does not exist in the meta tree, try to return + * its highest parent that does exist. The part of the + * pathname that is left over is returned in the value-result + * variable {remain}. + * For example, for "/.meta/xlators/brick1/view/foo/bar/baz", + * return the entry for "/.meta/xlators/brick1/view" + * and set remain to "/bar/baz" + */ + +meta_dirent_t * +lookup_meta_entry (meta_dirent_t *root, const char *path, + char **remain) +{ + char *_path = strdup (path); + + if (!is_meta_path (path)) + return NULL; + + meta_dirent_t *trav = root; + char *dir = strtok (_path, "/"); + dir = strtok (NULL, "/"); + + while (dir) { + meta_dirent_t *ntrav; + ntrav = find_entry (trav->children, dir); + if (!ntrav) { + /* we have reached bottom of the meta tree. + Unknown dragons lie further below */ + if (remain) { + char *piece = dir; + while (piece) { + char *tmp = *remain; + if (*remain) + asprintf (remain, "/%s/%s", *remain, piece); + else + asprintf (remain, "/%s", piece); + if (tmp) free (tmp); + piece = strtok (NULL, "/"); + } + } + return trav; + } + dir = strtok (NULL, "/"); + trav = ntrav; + } + + free (_path); + return trav; +} + +meta_dirent_t * +insert_meta_entry (meta_dirent_t *root, const char *path, + int type, struct stat *stbuf, struct xlator_fops *fops) +{ + if (!is_meta_path (path)) + return NULL; + char *slashpos = strrchr (path, '/'); + char *dir = strndup (path, slashpos - path); + meta_dirent_t *parent = lookup_meta_entry (root, dir, NULL); + if (!dir) + return NULL; + + meta_dirent_t *new = CALLOC (1, sizeof (meta_dirent_t)); + ERR_ABORT (new); + new->name = strdup (slashpos+1); + new->type = type; + new->parent = parent; + new->next = parent->children; + parent->children = new; + if (stbuf) + new->stbuf = stbuf; + else + new->stbuf = new_stbuf (); + + new->stbuf->st_mode |= type; + new->fops = fops; + return new; +} + +int main (void) +{ + meta_dirent_t *root = CALLOC (1, sizeof (meta_dirent_t)); + ERR_ABORT (root); + root->name = strdup (".meta"); + + insert_meta_entry (root, "/.meta/version", S_IFREG, NULL, NULL); + return 0; +} |