This way we create a set of methods that can be used by self-check
to list existing objects.

Signed-off-by: Pete Zaitcev <[email protected]>

---
 server/be-fs.c  |  361 +++++++++++++++++++++++++++++-----------------
 server/chunkd.h |   16 ++
 2 files changed, 244 insertions(+), 133 deletions(-)

commit cbc71b0262fa3594be940d8a758873f746c410e7
Author: Master <[email protected]>
Date:   Sun Dec 27 15:35:13 2009 -0700

    Add methods with which a self-check can list objects later.

diff --git a/server/be-fs.c b/server/be-fs.c
index 89635f8..1f8f1a5 100644
--- a/server/be-fs.c
+++ b/server/be-fs.c
@@ -689,168 +689,263 @@ err_out:
        return false;
 }
 
-GList *fs_list_objs(uint32_t table_id, const char *user)
+int fs_list_objs_open(struct fs_obj_lister *t,
+                     const char *root_path, uint32_t table_id)
 {
-       GList *res = NULL;
-       struct dirent *de, *root_de;
-       DIR *d, *root;
-       char *sub, *table_path = NULL;
+       int err;
 
-       sub = alloca(strlen(chunkd_srv.vol_path) + 1 + 16 + 4 + 1);
+       if (asprintf(&t->table_path, MDB_TPATH_FMT, root_path, table_id) < 0)
+               return -ENOMEM;
+       t->root = opendir(t->table_path);
+       if (!t->root) {
+               err = errno;
+               free(t->table_path);
+               return -err;
+       }
+       return 0;
+}
 
-       if (asprintf(&table_path, MDB_TPATH_FMT,
-                    chunkd_srv.vol_path, table_id) < 0)
-               return NULL;
+/*
+ * Get next filename.
+ * Return:
+ * -1  - error
+ *  0  - EOF
+ *  1  - ok
+ */
+int fs_list_objs_next(struct fs_obj_lister *t, char **fnp)
+{
+       struct dirent *de;
 
-       root = opendir(table_path);
-       if (!root) {
-               syslogerr(table_path);
-               free(table_path);
-               return NULL;
-       }
+again:
+       if (!t->sub) {
+               if ((de = readdir(t->root)) == NULL)
+                       return 0;
 
-       /* iterate through each dir */
-       while ((root_de = readdir(root)) != NULL) {
+               if (de->d_name[0] == '.')
+                       goto again;
+               if (strlen(de->d_name) != 4)
+                       goto again;
 
-               if (root_de->d_name[0] == '.')
-                       continue;
-               if (strlen(root_de->d_name) != 4)
-                       continue;
+               if (asprintf(&t->sub, "%s/%s", t->table_path, de->d_name) < 0)
+                       return -1;
+       }
 
-               sprintf(sub, "%s/%s", table_path, root_de->d_name);
-               d = opendir(sub);
-               if (!d) {
-                       syslogerr(sub);
-                       break;
+       if (!t->d) {
+               t->d = opendir(t->sub);
+               if (!t->d) {
+                       syslogerr(t->sub);
+                       free(t->sub);
+                       t->sub = NULL;
+                       goto again;
                }
+       }
 
-               while ((de = readdir(d)) != NULL) {
-                       int fd;
-                       char *fn;
-                       ssize_t rrc;
-                       struct be_fs_obj_hdr hdr;
-                       struct stat st;
-                       struct volume_entry *ve;
-                       void *p;
-                       size_t alloc_len;
-                       void *key_in;
-                       uint32_t key_len_in;
-
-                       if (de->d_name[0] == '.')
-                               continue;
-
-                       if (asprintf(&fn, "%s/%s", sub, de->d_name) < 0)
-                               break;
-
-                       fd = open(fn, O_RDONLY);
-                       if (fd < 0) {
-                               syslogerr(fn);
-                               free(fn);
-                               break;
-                       }
+       if ((de = readdir(t->d)) == NULL) {
+               closedir(t->d);
+               t->d = NULL;
+               free(t->sub);
+               t->sub = NULL;
+               goto again;
+       }
 
-                       if (fstat(fd, &st) < 0) {
-                               syslogerr(fn);
-                               close(fd);
-                               free(fn);
-                               break;
-                       }
+       if (de->d_name[0] == '.')
+               goto again;
 
-                       rrc = read(fd, &hdr, sizeof(hdr));
-                       if (rrc != sizeof(hdr)) {
-                               if (rrc < 0)
-                                       syslogerr(fn);
-                               else
-                                       applog(LOG_ERR, "%s hdr read failed", 
fn);
-                               close(fd);
-                               free(fn);
-                               break;
-                       }
+       if (asprintf(fnp, "%s/%s", t->sub, de->d_name) < 0)
+               return -1;
 
-                       key_len_in = GUINT32_FROM_LE(hdr.key_len);
-                       if (key_len_in < 1 || key_len_in > CHD_KEY_SZ) {
-                               applog(LOG_ERR, "%s hdr key len invalid", fn);
-                               close(fd);
-                               free(fn);
-                               break;
-                       }
+       return 1;
+}
 
-                       key_in = malloc(key_len_in);
-                       if (!key_in) {
-                               close(fd);
-                               free(fn);
-                               break;
-                       }
+void fs_list_objs_close(struct fs_obj_lister *t)
+{
+       closedir(t->root);
+       free(t->table_path);
 
-                       rrc = read(fd, key_in, key_len_in);
-                       if (rrc != key_len_in) {
-                               if (rrc < 0)
-                                       syslogerr(fn);
-                               else
-                                       applog(LOG_ERR, "%s hdr read failed", 
fn);
-                               close(fd);
-                               free(fn);
-                               free(key_in);
-                               break;
-                       }
+       if (t->d)
+               closedir(t->d);
+       free(t->sub);
+}
 
-                       if (close(fd) < 0)
-                               syslogerr(fn);
+GList *fs_list_objs(uint32_t table_id, const char *user)
+{
+       struct fs_obj_lister lister;
+       GList *res = NULL;
+       char *fn;
+       int rc;
+
+       memset(&lister, 0, sizeof(struct fs_obj_lister));
+       rc = fs_list_objs_open(&lister, chunkd_srv.vol_path, table_id);
+       if (rc) {
+               applog(LOG_WARNING, "Cannot open table %u: %s", table_id,
+                      strerror(-rc));
+               return NULL;
+       }
 
+       while (fs_list_objs_next(&lister, &fn) > 0) {
+               char *owner;
+               char *csum;
+               unsigned long long size;
+               time_t mtime;
+               struct volume_entry *ve;
+               void *p;
+               size_t alloc_len;
+               void *key_in;
+               size_t klen_in;
+
+               rc = fs_obj_hdr_read(fn, &owner, &csum, &key_in, &klen_in,
+                                    &size, &mtime);
+               if (rc < 0) {
                        free(fn);
+                       break;
+               }
+               free(fn);
+
+               /* filter out results that do not match
+                * the authenticated user
+                */
+               if (strcmp(user, owner)) {
+                       free(owner);
+                       free(csum);
+                       free(key_in);
+                       continue;
+               }
 
-                       /* filter out results that do not match
-                        * the authenticated user
-                        */
-                       if (strcmp(user, hdr.owner)) {
-                               free(key_in);
-                               continue;
-                       }
+               /* one alloc, for fixed + var length struct */
+               alloc_len = sizeof(*ve) + strlen(csum) + 1 + strlen(owner) + 1;
 
-                       /* one alloc, for fixed + var length struct */
-                       alloc_len = sizeof(*ve) +
-                                   strlen(hdr.checksum) + 1 +
-                                   strlen(hdr.owner) + 1;
+               ve = malloc(alloc_len);
+               if (!ve) {
+                       free(owner);
+                       free(csum);
+                       free(key_in);
+                       applog(LOG_ERR, "OOM");
+                       break;
+               }
 
-                       ve = malloc(alloc_len);
-                       if (!ve) {
-                               free(key_in);
-                               applog(LOG_ERR, "OOM");
-                               break;
-                       }
+               /* store fixed-length portion of struct */
+               ve->size = size;
+               ve->mtime = mtime;
+               ve->key = key_in;
+               ve->key_len = klen_in;
 
-                       /* store fixed-length portion of struct */
-                       st.st_size -= sizeof(struct be_fs_obj_hdr);
-                       st.st_size -= key_len_in;
+               /*
+                * store variable-length portion of struct:
+                * checksum, owner strings
+                */
 
-                       ve->size = st.st_size;
-                       ve->mtime = st.st_mtime;
-                       ve->key = key_in;
-                       ve->key_len = key_len_in;
+               p = (ve + 1);
+               ve->hash = p;
+               strcpy(ve->hash, csum);
 
-                       /*
-                        * store variable-length portion of struct:
-                        * checksum, owner strings
-                        */
+               p += strlen(ve->hash) + 1;
+               ve->owner = p;
+               strcpy(ve->owner, owner);
 
-                       p = (ve + 1);
-                       ve->hash = p;
-                       strcpy(ve->hash, hdr.checksum);
+               /* add entry to result list */
+               res = g_list_append(res, ve);
 
-                       p += strlen(ve->hash) + 1;
-                       ve->owner = p;
-                       strcpy(ve->owner, hdr.owner);
+               free(owner);
+               free(csum);
+       }
 
-                       /* add entry to result list */
-                       res = g_list_append(res, ve);
-               }
+       fs_list_objs_close(&lister);
+       return res;
+}
+
+/*
+ * Read an object by filename.
+ * TODO - possibly factor out some code from fs_obj_open and fs_obj_delete.
+ */
+int fs_obj_hdr_read(const char *fn, char **owner, char **csum,
+                   void **keyp, size_t *klenp,
+                   unsigned long long *size, time_t *mtime)
+{
+       struct be_fs_obj_hdr hdr;
+       struct stat st;
+       int fd;
+       ssize_t rrc;
+       void *key_in;
+       size_t klen_in;
+       unsigned long long sz;
 
-               closedir(d);
+       fd = open(fn, O_RDONLY);
+       if (fd < 0) {
+               syslogerr(fn);
+               goto err_open;
        }
 
-       closedir(root);
+       if (fstat(fd, &st) < 0) {
+               syslogerr(fn);
+               goto err_stat;
+       }
 
-       free(table_path);
-       return res;
+       rrc = read(fd, &hdr, sizeof(hdr));
+       if (rrc != sizeof(hdr)) {
+               if (rrc < 0)
+                       syslogerr(fn);
+               else
+                       applog(LOG_WARNING, "%s hdr read failed", fn);
+               goto err_fix;
+       }
+
+       klen_in = GUINT32_FROM_LE(hdr.key_len);
+       if (klen_in < 1 || klen_in > CHD_KEY_SZ) {
+               applog(LOG_WARNING, "%s hdr key len (0x%x) invalid",
+                      fn, (unsigned int)klen_in);
+               goto err_fix;
+       }
+
+       key_in = malloc(klen_in);
+       if (!key_in) {
+               applog(LOG_WARNING, "NO CORE");
+               goto err_fix;
+       }
+
+       rrc = read(fd, key_in, klen_in);
+       if (rrc != klen_in) {
+               if (rrc < 0)
+                       syslogerr(fn);
+               else
+                       applog(LOG_ERR, "%s hdr short read (%lu)",
+                              fn, (unsigned long)rrc);
+               goto err_var;
+       }
+
+       *owner = strndup(hdr.owner, sizeof(hdr.owner));
+       if (!*owner) {
+               applog(LOG_WARNING, "NO CORE");
+               goto err_owner;
+       }
+       *csum = strndup(hdr.checksum, sizeof(hdr.checksum));
+       if (!*csum) {
+               applog(LOG_WARNING, "NO CORE");
+               goto err_csum;
+       }
+
+       *keyp = key_in;
+       *klenp = klen_in;
+
+       sz = st.st_size;
+       if (sz < klen_in + sizeof(struct be_fs_obj_hdr))
+               sz = 0;
+       else
+               sz = st.st_size - (sizeof(struct be_fs_obj_hdr) + klen_in);
+       *size = sz;
+       *mtime = st.st_mtime;
+
+       close(fd);
+       return 0;
+
+ err_csum:
+       free(*owner);
+ err_owner:
+ err_var:
+       free(key_in);
+ err_fix:
+ err_stat:
+       close(fd);
+ err_open:
+       return -1;
 }
 
diff --git a/server/chunkd.h b/server/chunkd.h
index 57726fd..a97088d 100644
--- a/server/chunkd.h
+++ b/server/chunkd.h
@@ -217,6 +217,15 @@ struct server {
 extern struct hail_log cldu_hail_log;
 
 /* be-fs.c */
+#include <dirent.h>
+struct fs_obj_lister {
+       DIR *root;
+       char *table_path;
+
+       DIR *d;
+       char *sub;
+};
+
 extern int fs_open(void);
 extern void fs_close(void);
 extern void fs_free(void);
@@ -234,6 +243,13 @@ extern bool fs_obj_delete(uint32_t table_id, const char 
*user,
                          const void *kbuf, size_t klen,
                          enum chunk_errcode *err_code);
 extern ssize_t fs_obj_sendfile(struct backend_obj *bo, int out_fd, size_t len);
+extern int fs_list_objs_open(struct fs_obj_lister *t,
+                            const char *root_path, uint32_t table_id);
+extern int fs_list_objs_next(struct fs_obj_lister *t, char **fnp);
+extern void fs_list_objs_close(struct fs_obj_lister *t);
+extern int fs_obj_hdr_read(const char *fn, char **owner, char **checksum,
+                          void **keyp, size_t *klenp,
+                          unsigned long long *size, time_t *mtime);
 extern GList *fs_list_objs(uint32_t table_id, const char *user);
 extern bool fs_table_open(const char *user, const void *kbuf, size_t klen,
                   bool tbl_creat, bool excl_creat, uint32_t *table_id,
--
To unsubscribe from this list: send the line "unsubscribe hail-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to