From: <tb...@us...> - 2011-01-31 07:06:16
|
Revision: 5099 http://gfarm.svn.sourceforge.net/gfarm/?rev=5099&view=rev Author: tbaba Date: 2011-01-31 07:06:07 +0000 (Mon, 31 Jan 2011) Log Message: ----------- add metadata journaling function for gfmd redundancy. * To enable metadata journaling, 1. add -DENABLE_JOURNAL to the compile option and recompile. 2. add a following line in gfmd.conf journal_dir /var/gfarm-metadata/journal 3. mkdir -p /var/gfarm-metadata/journal * Move rpc functions in subr.c into rpcsubr.c. Modified Paths: -------------- gfarm_v2/trunk/include/gfarm/error.h gfarm_v2/trunk/lib/libgfarm/gfarm/config.c gfarm_v2/trunk/lib/libgfarm/gfarm/config.h gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.h gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.c gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.h gfarm_v2/trunk/lib/libgfarm/gfarm/liberror.c gfarm_v2/trunk/makes/var.mk gfarm_v2/trunk/server/gfmd/Makefile gfarm_v2/trunk/server/gfmd/back_channel.c gfarm_v2/trunk/server/gfmd/db_access.c gfarm_v2/trunk/server/gfmd/db_access.h gfarm_v2/trunk/server/gfmd/db_ldap.c gfarm_v2/trunk/server/gfmd/db_none.c gfarm_v2/trunk/server/gfmd/db_ops.h gfarm_v2/trunk/server/gfmd/db_pgsql.c gfarm_v2/trunk/server/gfmd/fs.c gfarm_v2/trunk/server/gfmd/gfmd.c gfarm_v2/trunk/server/gfmd/group.c gfarm_v2/trunk/server/gfmd/group.h gfarm_v2/trunk/server/gfmd/host.c gfarm_v2/trunk/server/gfmd/host.h gfarm_v2/trunk/server/gfmd/inode.c gfarm_v2/trunk/server/gfmd/inode.h gfarm_v2/trunk/server/gfmd/job.c gfarm_v2/trunk/server/gfmd/process.c gfarm_v2/trunk/server/gfmd/quota.c gfarm_v2/trunk/server/gfmd/quota.h gfarm_v2/trunk/server/gfmd/subr.c gfarm_v2/trunk/server/gfmd/subr.h gfarm_v2/trunk/server/gfmd/user.c gfarm_v2/trunk/server/gfmd/user.h gfarm_v2/trunk/server/gfmd/xattr.c Added Paths: ----------- gfarm_v2/trunk/server/gfmd/db_journal.c gfarm_v2/trunk/server/gfmd/db_journal.h gfarm_v2/trunk/server/gfmd/db_journal_apply.c gfarm_v2/trunk/server/gfmd/db_journal_apply.h gfarm_v2/trunk/server/gfmd/journal_file.c gfarm_v2/trunk/server/gfmd/journal_file.h gfarm_v2/trunk/server/gfmd/rpcsubr.c gfarm_v2/trunk/server/gfmd/rpcsubr.h Modified: gfarm_v2/trunk/include/gfarm/error.h =================================================================== --- gfarm_v2/trunk/include/gfarm/error.h 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/include/gfarm/error.h 2011-01-31 07:06:07 UTC (rev 5099) @@ -125,6 +125,7 @@ GFARM_ERR_NOT_A_REGULAR_FILE, GFARM_ERR_IS_A_REGULAR_FILE, GFARM_ERR_PATH_IS_ROOT, + GFARM_ERR_INTERNAL_ERROR, GFARM_ERR_NUMBER }; Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/config.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/config.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/config.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -724,6 +724,7 @@ #define GFARM_GFMD_CONNECTION_CACHE_DEFAULT 8 /* 8 free connections */ #define GFARM_RECORD_ATIME_DEFAULT 1 /* enable */ #define GFARM_PROFILE_DEFAULT 0 /* disable */ +#define GFARM_JOURNAL_MAX_SIZE_DEFAULT (32 * 1024 * 1024) /* 32MB */ #define MISC_DEFAULT -1 int gfarm_log_level = MISC_DEFAULT; int gfarm_log_message_verbose = MISC_DEFAULT; @@ -748,6 +749,8 @@ int gfarm_metadb_dbq_size = MISC_DEFAULT; int gfarm_record_atime = MISC_DEFAULT; int gfarm_profile = MISC_DEFAULT; +static char *journal_dir = NULL; +static int journal_max_size = MISC_DEFAULT; void gfarm_config_clear(void) @@ -776,6 +779,7 @@ &gfarm_postgresql_conninfo, &gfarm_localfs_datadir, &schedule_write_target_domain, + &journal_dir, }; int i; @@ -854,6 +858,18 @@ gfarm_record_atime = boolean; } +const char * +gfarm_journal_dir(void) +{ + return (journal_dir); +} + +int +gfarm_journal_max_size(void) +{ + return (journal_max_size); +} + /* * get (almost) shell style token. * e.g. @@ -1987,6 +2003,10 @@ } else if (strcmp(s, o = "profile") == 0) { e = parse_profile(p, &gfarm_profile); + } else if (strcmp(s, o = "journal_dir") == 0) { + e = parse_set_var(p, &journal_dir); + } else if (strcmp(s, o = "journal_max_size") == 0) { + e = parse_set_misc_int(p, &journal_max_size); } else { o = s; gflog_debug(GFARM_MSG_1000974, @@ -2130,6 +2150,8 @@ gfarm_record_atime = GFARM_RECORD_ATIME_DEFAULT; if (gfarm_profile == MISC_DEFAULT) gfarm_profile = GFARM_PROFILE_DEFAULT; + if (journal_max_size == MISC_DEFAULT) + journal_max_size = GFARM_JOURNAL_MAX_SIZE_DEFAULT; } void Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/config.h =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/config.h 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/config.h 2011-01-31 07:06:07 UTC (rev 5099) @@ -81,6 +81,8 @@ int gfarm_schedule_write_local_priority(void); char *gfarm_schedule_write_target_domain(void); gfarm_off_t gfarm_get_minimum_free_disk_space(void); +const char *gfarm_journal_dir(void); +int gfarm_journal_max_size(void); /* redirection */ extern struct gfs_file *gf_stdout, *gf_stderr; Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -47,15 +47,20 @@ conn->cookie = cookie; conn->fd = fd; - gfarm_iobuffer_set_read(conn->recvbuffer, ops->blocking_read, - cookie, fd); - gfarm_iobuffer_set_write(conn->sendbuffer, ops->blocking_write, - cookie, fd); + if (conn->recvbuffer) + gfarm_iobuffer_set_read(conn->recvbuffer, ops->blocking_read, + cookie, fd); + if (conn->sendbuffer) + gfarm_iobuffer_set_write(conn->sendbuffer, ops->blocking_write, + cookie, fd); } -gfarm_error_t -gfp_xdr_new(struct gfp_iobuffer_ops *ops, void *cookie, int fd, - struct gfp_xdr **connp) +#define GFP_XDR_NEW_RECV 1 +#define GFP_XDR_NEW_SEND 2 + +static gfarm_error_t +gfp_xdr_new0(struct gfp_iobuffer_ops *ops, void *cookie, int fd, + int flags, struct gfp_xdr **connp) { struct gfp_xdr *conn; @@ -66,23 +71,31 @@ gfarm_error_string(GFARM_ERR_NO_MEMORY)); return (GFARM_ERR_NO_MEMORY); } - conn->recvbuffer = gfarm_iobuffer_alloc(GFP_XDR_BUFSIZE); - if (conn->recvbuffer == NULL) { - free(conn); - gflog_debug(GFARM_MSG_1000997, - "allocation of 'conn recvbuffer' failed: %s", - gfarm_error_string(GFARM_ERR_NO_MEMORY)); - return (GFARM_ERR_NO_MEMORY); - } - conn->sendbuffer = gfarm_iobuffer_alloc(GFP_XDR_BUFSIZE); - if (conn->sendbuffer == NULL) { - gfarm_iobuffer_free(conn->recvbuffer); - free(conn); - gflog_debug(GFARM_MSG_1000998, - "allocation of 'conn sendbuffer' failed: %s", - gfarm_error_string(GFARM_ERR_NO_MEMORY)); - return (GFARM_ERR_NO_MEMORY); - } + if ((flags & GFP_XDR_NEW_RECV) != 0) { + conn->recvbuffer = gfarm_iobuffer_alloc(GFP_XDR_BUFSIZE); + if (conn->recvbuffer == NULL) { + free(conn); + gflog_debug(GFARM_MSG_1000997, + "allocation of 'conn recvbuffer' failed: %s", + gfarm_error_string(GFARM_ERR_NO_MEMORY)); + return (GFARM_ERR_NO_MEMORY); + } + } else + conn->recvbuffer = NULL; + + if ((flags & GFP_XDR_NEW_SEND) != 0) { + conn->sendbuffer = gfarm_iobuffer_alloc(GFP_XDR_BUFSIZE); + if (conn->sendbuffer == NULL) { + gfarm_iobuffer_free(conn->recvbuffer); + free(conn); + gflog_debug(GFARM_MSG_1000998, + "allocation of 'conn sendbuffer' failed: %s", + gfarm_error_string(GFARM_ERR_NO_MEMORY)); + return (GFARM_ERR_NO_MEMORY); + } + } else + conn->sendbuffer = NULL; + gfp_xdr_set(conn, ops, cookie, fd); *connp = conn; @@ -90,6 +103,31 @@ } gfarm_error_t +gfp_xdr_new(struct gfp_iobuffer_ops *ops, void *cookie, int fd, + struct gfp_xdr **connp) +{ + return (gfp_xdr_new0(ops, cookie, fd, + GFP_XDR_NEW_RECV|GFP_XDR_NEW_SEND, connp)); +} + +gfarm_error_t +gfp_xdr_new_recv_only(struct gfp_iobuffer_ops *ops, void *cookie, int fd, + struct gfp_xdr **connp) +{ + return (gfp_xdr_new0(ops, cookie, fd, + GFP_XDR_NEW_RECV, connp)); +} + +gfarm_error_t +gfp_xdr_new_send_only(struct gfp_iobuffer_ops *ops, void *cookie, int fd, + struct gfp_xdr **connp) +{ + return (gfp_xdr_new0(ops, cookie, fd, + GFP_XDR_NEW_SEND, connp)); +} + + +gfarm_error_t gfp_xdr_free(struct gfp_xdr *conn) { gfarm_error_t e, e_save; @@ -129,7 +167,25 @@ return (GFARM_ERR_NO_ERROR); } +gfarm_error_t +gfp_xdr_recvbuffer_check_size(struct gfp_xdr *conn, int size) +{ + if (size > gfarm_iobuffer_get_size(conn->recvbuffer)) { + gflog_fatal(GFARM_MSG_UNFIXED, + "%s", gfarm_error_string(GFARM_ERR_INTERNAL_ERROR)); + return (GFARM_ERR_INTERNAL_ERROR); + } else if (size > gfarm_iobuffer_avail_length(conn->recvbuffer)) + return (GFARM_ERR_RESOURCE_TEMPORARILY_UNAVAILABLE); + else + return (GFARM_ERR_NO_ERROR); +} +void +gfp_xdr_recvbuffer_clear_read_eof(struct gfp_xdr *conn) +{ + gfarm_iobuffer_clear_read_eof(conn->recvbuffer); +} + gfarm_error_t gfp_xdr_export_credential(struct gfp_xdr *conn) { @@ -175,6 +231,8 @@ gfarm_error_t gfp_xdr_flush(struct gfp_xdr *conn) { + if (conn->sendbuffer == NULL) + return (GFARM_ERR_NO_ERROR); gfarm_iobuffer_flush_write(conn->sendbuffer); return (gfarm_iobuffer_get_error(conn->sendbuffer)); } @@ -209,6 +267,17 @@ return (GFARM_ERR_NO_ERROR); } +void +gfp_xdr_purge_all(struct gfp_xdr *conn) +{ + if (conn->sendbuffer) + while (gfarm_iobuffer_purge(conn->sendbuffer, NULL) > 0) + ; + if (conn->recvbuffer) + while (gfarm_iobuffer_purge(conn->recvbuffer, NULL) > 0) + ; +} + gfarm_error_t gfp_xdr_vsend_size_add(size_t *sizep, const char **formatp, va_list *app) { @@ -712,6 +781,35 @@ return (GFARM_ERR_NO_ERROR); } +gfarm_uint32_t +gfp_xdr_send_calc_crc32(struct gfp_xdr *conn, gfarm_uint32_t crc, int offset, + size_t length) +{ + return (gfarm_iobuffer_calc_crc32(conn->sendbuffer, crc, + offset, length, 0)); +} + +gfarm_uint32_t +gfp_xdr_recv_calc_crc32(struct gfp_xdr *conn, gfarm_uint32_t crc, int offset, + size_t length) +{ + return (gfarm_iobuffer_calc_crc32(conn->recvbuffer, crc, + offset, length, 1)); +} + +gfarm_uint32_t +gfp_xdr_recv_get_crc32_ahead(struct gfp_xdr *conn, int offset) +{ + gfarm_uint32_t n; + int err; + int len = gfarm_iobuffer_get_read_x_ahead(conn->recvbuffer, + &n, sizeof(n), 1, offset, &err); + + if (len != sizeof(n)) + return (0); + return (ntohl(n)); +} + gfarm_error_t gfp_xdr_recv_sized(struct gfp_xdr *conn, int just, size_t *sizep, int *eofp, const char *format, ...) @@ -762,6 +860,19 @@ return (GFARM_ERR_NO_ERROR); } +gfarm_error_t +gfp_xdr_recv_ahead(struct gfp_xdr *conn, int len, size_t *availp) +{ + int r = gfarm_iobuffer_read_ahead(conn->recvbuffer, len); + + if (r == 0) { + *availp = 0; + return (gfarm_iobuffer_get_error(conn->recvbuffer)); + } + *availp = gfarm_iobuffer_avail_length(conn->recvbuffer); + return (GFARM_ERR_NO_ERROR); +} + /* * do RPC request */ Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.h =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.h 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfp_xdr.h 2011-01-31 07:06:07 UTC (rev 5099) @@ -32,11 +32,18 @@ gfarm_error_t gfp_xdr_new(struct gfp_iobuffer_ops *, void *, int, struct gfp_xdr **); +gfarm_error_t gfp_xdr_new_recv_only(struct gfp_iobuffer_ops *, void *, int, + struct gfp_xdr **); +gfarm_error_t gfp_xdr_new_send_only(struct gfp_iobuffer_ops *, void *, int, + struct gfp_xdr **); gfarm_error_t gfp_xdr_free(struct gfp_xdr *); void *gfp_xdr_cookie(struct gfp_xdr *); int gfp_xdr_fd(struct gfp_xdr *); +int gfp_xdr_read_fd(struct gfp_xdr *); gfarm_error_t gfp_xdr_sendbuffer_check_size(struct gfp_xdr *, int); +gfarm_error_t gfp_xdr_recvbuffer_check_size(struct gfp_xdr *, int); +void gfp_xdr_recvbuffer_clear_read_eof(struct gfp_xdr *); void gfp_xdr_set(struct gfp_xdr *, struct gfp_iobuffer_ops *, void *, int); @@ -52,6 +59,7 @@ int gfp_xdr_recv_is_ready(struct gfp_xdr *); gfarm_error_t gfp_xdr_flush(struct gfp_xdr *); gfarm_error_t gfp_xdr_purge(struct gfp_xdr *, int, int); +void gfp_xdr_purge_all(struct gfp_xdr *); gfarm_error_t gfp_xdr_vsend_size_add(size_t *, const char **, va_list *); gfarm_error_t gfp_xdr_vsend(struct gfp_xdr *, const char **, va_list *); @@ -62,10 +70,16 @@ gfarm_error_t gfp_xdr_send_size_add(size_t *, const char *, ...); gfarm_error_t gfp_xdr_send(struct gfp_xdr *, const char *, ...); +gfarm_uint32_t gfp_xdr_send_calc_crc32(struct gfp_xdr *, gfarm_uint32_t, + int, size_t); gfarm_error_t gfp_xdr_recv_sized(struct gfp_xdr *, int, size_t *, int *, const char *, ...); gfarm_error_t gfp_xdr_recv(struct gfp_xdr *, int, int *, const char *, ...); +gfarm_uint32_t gfp_xdr_recv_calc_crc32(struct gfp_xdr *, gfarm_uint32_t, + int, size_t); +gfarm_uint32_t gfp_xdr_recv_get_crc32_ahead(struct gfp_xdr *, int); +gfarm_error_t gfp_xdr_recv_ahead(struct gfp_xdr *, int, size_t *); gfarm_error_t gfp_xdr_vrpc_request(struct gfp_xdr *, gfarm_int32_t, const char **, va_list *); gfarm_error_t gfp_xdr_vrpc_result_sized(struct gfp_xdr *, int, size_t *, Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -4,6 +4,7 @@ #include <gfarm/gflog.h> #include <gfarm/gfarm_misc.h> #include "iobuffer.h" +#include "crc32.h" /* XXX - This implementation is somewhat slow, but probably acceptable */ @@ -71,6 +72,8 @@ void gfarm_iobuffer_free(struct gfarm_iobuffer *b) { + if (b == NULL) + return; free(b->buffer); free(b); } @@ -258,7 +261,6 @@ b->tail += rv; *residualp -= rv; } - return; } int @@ -522,3 +524,48 @@ { /* nop */ } + +gfarm_uint32_t +gfarm_iobuffer_calc_crc32(struct gfarm_iobuffer *b, gfarm_uint32_t crc, + int offset, int len, int head_or_tail) +{ + return (gfarm_crc32(crc, b->buffer + (head_or_tail ? b->head : b->tail) + + offset, len)); +} + +int +gfarm_iobuffer_get_read_x_ahead(struct gfarm_iobuffer *b, void *data, int len, + int just, int offset, int *errp) +{ + int rlen; + int head0 = b->head; + int tail0 = b->tail; + int read_eof0 = b->read_eof; + int error0 = b->error; + + if (b->head + offset > b->tail) + return (0); + b->head += offset; + rlen = gfarm_iobuffer_get_read_x(b, data, len, just); + if (rlen == 0) + *errp = b->error; + b->head = head0; + b->tail = tail0; + b->read_eof = read_eof0; + b->error = error0; + return (rlen); +} + +int +gfarm_iobuffer_read_ahead(struct gfarm_iobuffer *b, int len) +{ + size_t alen = IOBUFFER_AVAIL_LENGTH(b); + int rlen; + + if (alen > len) + return (alen); + rlen = len - alen; + while (rlen > 0 && gfarm_iobuffer_is_readable(b) && b->error == 0) + gfarm_iobuffer_read(b, &rlen); + return (len - rlen); +} Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.h =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.h 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/iobuffer.h 2011-01-31 07:06:07 UTC (rev 5099) @@ -80,6 +80,7 @@ void *gfarm_iobuffer_get_read_cookie(struct gfarm_iobuffer *); int gfarm_iobuffer_get_read_fd(struct gfarm_iobuffer *); void gfarm_iobuffer_read(struct gfarm_iobuffer *, int *); +int gfarm_iobuffer_read_ahead(struct gfarm_iobuffer *, int); int gfarm_iobuffer_put(struct gfarm_iobuffer *, const void *, int); /* dequeue */ @@ -106,6 +107,8 @@ int gfarm_iobuffer_get_read_partial_x(struct gfarm_iobuffer *, void *,int,int); int gfarm_iobuffer_get_read_partial_just(struct gfarm_iobuffer *, void *, int); int gfarm_iobuffer_get_read_partial(struct gfarm_iobuffer *, void *, int); +int gfarm_iobuffer_get_read_x_ahead(struct gfarm_iobuffer *, void *, int, int, + int, int *); /* * gfarm_iobuffer_get_read{,_partial}_just() functions doesn't perform * read ahead for given stream, so the caller can perform read operation @@ -117,3 +120,5 @@ /* default operation for gfarm_iobuffer_set_write_close() */ void gfarm_iobuffer_write_close_nop(struct gfarm_iobuffer *, void *, int); +gfarm_uint32_t gfarm_iobuffer_calc_crc32(struct gfarm_iobuffer *, + gfarm_uint32_t, int, int, int); Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/liberror.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/liberror.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/liberror.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -134,6 +134,7 @@ "not a regular file", "is a regular file", "path is root", + "internal error", }; static const char *errmsg_string[GFARM_ERRMSG_END - GFARM_ERRMSG_BEGIN] = { Modified: gfarm_v2/trunk/makes/var.mk =================================================================== --- gfarm_v2/trunk/makes/var.mk 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/makes/var.mk 2011-01-31 07:06:07 UTC (rev 5099) @@ -59,6 +59,10 @@ GFUTIL_SRCDIR = $(top_srcdir)/lib/libgfarm/gfutil GFARMLIB_SRCDIR = $(top_srcdir)/lib/libgfarm/gfarm +# gfmd + +GFMD_SRCDIR = $(top_srcdir)/server/gfmd + # doc & man DOCBOOK2MAN = jw -b man Modified: gfarm_v2/trunk/server/gfmd/Makefile =================================================================== --- gfarm_v2/trunk/server/gfmd/Makefile 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/server/gfmd/Makefile 2011-01-31 07:06:07 UTC (rev 5099) @@ -30,16 +30,20 @@ PUBLIC_OBJS = SRCS = gfmd.c thrpool.c callout.c \ - subr.c user.c group.c host.c peer.c dead_file_copy.c \ + subr.c rpcsubr.c user.c group.c host.c peer.c dead_file_copy.c \ process.c job.c \ dir.c inode.c fs.c back_channel.c acl.c \ + journal_file.c \ db_access.c db_common.c db_none.c quota.c xattr.c \ + db_journal.c db_journal_apply.c \ $(ldap_srcs) $(postgresql_srcs) $(optional_srcs) OBJS = gfmd.o thrpool.o callout.o \ - subr.o user.o group.o host.o peer.o dead_file_copy.o \ + subr.o rpcsubr.o user.o group.o host.o peer.o dead_file_copy.o \ process.o job.o \ dir.o inode.o fs.o back_channel.o acl.o \ + journal_file.o \ db_access.o db_common.o db_none.o quota.o xattr.o \ + db_journal.o db_journal_apply.o \ $(ldap_objs) $(postgresql_objs) $(optional_objs) all: $(PROGRAM) @@ -64,8 +68,9 @@ $(GFARMLIB_SRCDIR)/gfm_proto.h \ $(GFARMLIB_SRCDIR)/gfj_client.h \ $(GFARMLIB_SRCDIR)/timespec.h \ - thrpool.h subr.h callout.h acl.h \ + thrpool.h subr.h rpcsubr.h callout.h acl.h \ user.h group.h host.h peer.h dead_file_copy.h process.h job.h \ - dir.h inode.h fs.h back_channel.h protocol_state.h quota.h xattr.h + dir.h inode.h fs.h back_channel.h protocol_state.h quota.h xattr.h \ + journal_file.h db_journal.h db_journal_apply.h include $(optional_rule) Modified: gfarm_v2/trunk/server/gfmd/back_channel.c =================================================================== --- gfarm_v2/trunk/server/gfmd/back_channel.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/server/gfmd/back_channel.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -24,6 +24,7 @@ #include "peer.h" #include "subr.h" +#include "rpcsubr.h" #include "thrpool.h" #include "callout.h" #include "host.h" Modified: gfarm_v2/trunk/server/gfmd/db_access.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_access.c 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/server/gfmd/db_access.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -21,11 +21,14 @@ #include "quota.h" #include "db_access.h" #include "db_ops.h" +#include "db_journal.h" +#include "db_journal_apply.h" #define ALIGNMENT 8 #define ALIGN(offset) (((offset) + ALIGNMENT - 1) & ~(ALIGNMENT - 1)) typedef void (*dbq_entry_func_callback_t)(gfarm_error_t, void *); +typedef gfarm_error_t (*db_enter_func_t)(dbq_entry_func_t, void *); struct dbq_callback_arg { dbq_entry_func_t func; @@ -37,6 +40,7 @@ struct dbq_entry { dbq_entry_func_t func; void *data; + gfarm_uint64_t seqnum; }; struct dbq { @@ -47,6 +51,26 @@ struct dbq_entry *entries; } dbq; +#ifdef ENABLE_JOURNAL +static gfarm_error_t db_journal_enter(dbq_entry_func_t, void *); +#else +static gfarm_error_t dbq_enter(dbq_entry_func_t, void *); +#endif + +static const struct db_ops *ops = +#ifdef ENABLE_JOURNAL + &db_journal_ops; +#else + &db_none_ops; +#endif +const struct db_ops *store_ops = &db_none_ops; +static db_enter_func_t db_enter = +#ifdef ENABLE_JOURNAL + &db_journal_enter; +#else + &dbq_enter; +#endif + gfarm_error_t dbq_init(struct dbq *q) { @@ -82,10 +106,11 @@ } static gfarm_error_t -dbq_enter(struct dbq *q, dbq_entry_func_t func, void *data) +dbq_enter0(struct dbq *q, dbq_entry_func_t func, void *data) { gfarm_error_t e; static const char diag[] = "dbq_enter"; + struct dbq_entry *ent; gfarm_mutex_lock(&q->mutex, diag, "mutex"); if (q->quitting) { @@ -102,8 +127,9 @@ gfarm_cond_wait(&q->nonfull, &q->mutex, diag, "nonfull"); } - q->entries[q->in].func = func; - q->entries[q->in].data = data; + ent = &q->entries[q->in]; + ent->func = func; + ent->data = data; q->in++; if (q->in >= gfarm_metadb_dbq_size) q->in = 0; @@ -114,21 +140,27 @@ return (e); } +static gfarm_error_t +dbq_enter(dbq_entry_func_t func, void *data) +{ + return (dbq_enter0(&dbq, func, data)); +} + /* DO NOT REMOVE: this interfaces is provided for a private extension */ /* The official gfmd source code shouldn't use these interface */ gfarm_error_t gfarm_dbq_enter(dbq_entry_func_t func, void *data) { - return (dbq_enter(&dbq, func, data)); + return (dbq_enter(func, data)); } static gfarm_error_t -dbq_call_callback(void *a) +dbq_call_callback(gfarm_uint64_t seqnum, void *a) { gfarm_error_t e; struct dbq_callback_arg *arg = (struct dbq_callback_arg *)a; - e = (*arg->func)(arg->data); + e = (*arg->func)(seqnum, arg->data); if (arg->cbfunc != NULL) { (*arg->cbfunc)(e, arg->cbdata); } @@ -137,8 +169,7 @@ } static gfarm_error_t -dbq_enter_withcallback(struct dbq *q, - dbq_entry_func_t func, void *data, +dbq_enter_withcallback(dbq_entry_func_t func, void *data, dbq_entry_func_callback_t cbfunc, void *cbdata) { gfarm_error_t e; @@ -154,7 +185,7 @@ arg->data = data; arg->cbfunc = cbfunc; arg->cbdata = cbdata; - e = dbq_enter(q, dbq_call_callback, arg); + e = dbq_enter(dbq_call_callback, arg); if (e != GFARM_ERR_NO_ERROR) free(arg); return (e); @@ -218,10 +249,10 @@ } static gfarm_error_t -dbq_enter_for_waitret(struct dbq *q, +dbq_enter_for_waitret( dbq_entry_func_t func, void *data, struct db_waitctx *ctx) { - return (dbq_enter_withcallback(q, func, data, + return (dbq_enter_withcallback(func, data, dbq_done_callback, ctx)); } @@ -231,7 +262,7 @@ gfarm_dbq_enter_for_waitret( dbq_entry_func_t func, void *data, struct db_waitctx *ctx) { - return (dbq_enter_for_waitret(&dbq, func, data, ctx)); + return (dbq_enter_for_waitret(func, data, ctx)); } gfarm_error_t @@ -278,38 +309,72 @@ return (freenum); } -static const struct db_ops *ops = &db_none_ops; +#ifdef ENABLE_JOURNAL +static gfarm_error_t +db_journal_enter(dbq_entry_func_t func, void *data) +{ + return (func(db_journal_next_seqnum(), data)); +} +#endif /* DO NOT REMOVE: this interfaces is provided for a private extension */ /* The official gfmd source code shouldn't use these interface */ const struct db_ops * db_get_ops(void) { +#ifdef ENABLE_JOURNAL + return (store_ops); +#else return (ops); +#endif } gfarm_error_t db_use(const struct db_ops *o) { +#ifdef ENABLE_JOURNAL + store_ops = o; +#else ops = o; +#endif return (GFARM_ERR_NO_ERROR); } gfarm_error_t db_initialize(void) { + gfarm_error_t e; + dbq_init(&dbq); - return ((*ops->initialize)()); +#ifdef ENABLE_JOURNAL + if ((e = (*store_ops->initialize)()) != GFARM_ERR_NO_ERROR) + return (e); + db_journal_set_apply_ops(&db_journal_apply_ops); +#endif + if ((e = (*ops->initialize)()) != GFARM_ERR_NO_ERROR) + return (e); + return (e); } gfarm_error_t db_terminate(void) { + gfarm_error_t e_save; +#ifdef ENABLE_JOURNAL + gfarm_error_t e; +#endif + gflog_info(GFARM_MSG_1000406, "try to stop database syncer"); dbq_wait_to_finish(&dbq); gflog_info(GFARM_MSG_1000407, "terminating the database"); - return ((*ops->terminate)()); + e_save = (*ops->terminate)(); +#ifdef ENABLE_JOURNAL + e = (*store_ops->terminate)(); + return (e_save == GFARM_ERR_NO_ERROR ? e : e_save); +#else + return (e_save); +#endif } void * @@ -321,18 +386,17 @@ for (;;) { e = dbq_delete(&dbq, &ent); if (e == GFARM_ERR_NO_ERROR) { - (*ent.func)(ent.data); + (*ent.func)(0, ent.data); } else if (e == GFARM_ERR_NO_SUCH_OBJECT) break; } - return (NULL); } gfarm_error_t db_begin(const char *diag) { - gfarm_error_t e = dbq_enter(&dbq, (dbq_entry_func_t)ops->begin, NULL); + gfarm_error_t e = db_enter((dbq_entry_func_t)ops->begin, NULL); if (e != GFARM_ERR_NO_ERROR) gflog_error(GFARM_MSG_1000408, @@ -343,7 +407,7 @@ gfarm_error_t db_end(const char *diag) { - gfarm_error_t e = dbq_enter(&dbq, (dbq_entry_func_t)ops->end, NULL); + gfarm_error_t e = db_enter((dbq_entry_func_t)ops->end, NULL); if (e != GFARM_ERR_NO_ERROR) gflog_error(GFARM_MSG_1000409, @@ -390,34 +454,47 @@ gfarm_error_t db_host_add(const struct gfarm_host_info *hi) { - struct gfarm_host_info *h = db_host_dup(hi, sizeof(*h)); + struct gfarm_host_info *h = db_host_dup(hi, sizeof(*hi)); if (h == NULL) { gflog_debug(GFARM_MSG_1002002, "db_host_dup() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->host_add, h)); + return (db_enter((dbq_entry_func_t)ops->host_add, h)); } -gfarm_error_t -db_host_modify(const struct gfarm_host_info *hi, +struct db_host_modify_arg * +db_host_modify_arg_alloc(const struct gfarm_host_info *hi, int modflags, int add_count, const char **add_aliases, int del_count, const char **del_aliases) { struct db_host_modify_arg *arg = db_host_dup(hi, sizeof(*arg)); - if (arg == NULL) { - gflog_debug(GFARM_MSG_1002003, "db_host_dup() failed"); - return (GFARM_ERR_NO_MEMORY); - } - + if (arg == NULL) + return (NULL); arg->modflags = modflags; /* XXX FIXME missing hostaliases */ arg->add_count = 0; arg->add_aliases = NULL; arg->del_count = 0; arg->del_aliases = NULL; + return (arg); +} - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->host_modify, arg)); +gfarm_error_t +db_host_modify(const struct gfarm_host_info *hi, + int modflags, + int add_count, const char **add_aliases, + int del_count, const char **del_aliases) +{ + struct db_host_modify_arg *arg = db_host_modify_arg_alloc(hi, modflags, + add_count, add_aliases, del_count, del_aliases); + + if (arg == NULL) { + gflog_debug(GFARM_MSG_UNFIXED, + "db_host_modify_arg_alloc failed"); + return (GFARM_ERR_NO_MEMORY); + } + return (db_enter((dbq_entry_func_t)ops->host_modify, arg)); } gfarm_error_t @@ -427,7 +504,7 @@ if (h == NULL) return (GFARM_ERR_NO_MEMORY); - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->host_remove, h)); + return (db_enter((dbq_entry_func_t)ops->host_remove, h)); } gfarm_error_t @@ -480,20 +557,32 @@ gflog_debug(GFARM_MSG_1002006, "db_user_dup() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->user_add, u)); + return (db_enter((dbq_entry_func_t)ops->user_add, u)); } +struct db_user_modify_arg * +db_user_modify_arg_alloc(const struct gfarm_user_info *ui, int modflags) +{ + struct db_user_modify_arg *arg = db_user_dup(ui, sizeof(*arg)); + + if (arg == NULL) + return (NULL); + arg->modflags = modflags; + return (arg); +} + gfarm_error_t db_user_modify(const struct gfarm_user_info *ui, int modflags) { - struct db_user_modify_arg *arg = db_user_dup(ui, sizeof(*arg)); + struct db_user_modify_arg *arg = db_user_modify_arg_alloc( + ui, modflags); if (arg == NULL) { - gflog_debug(GFARM_MSG_1002007, "db_user_dup() failed"); + gflog_debug(GFARM_MSG_UNFIXED, + "db_user_modify_arg_alloc failed"); return (GFARM_ERR_NO_MEMORY); } - arg->modflags = modflags; - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->user_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->user_modify, arg)); } gfarm_error_t @@ -503,7 +592,7 @@ if (u == NULL) return (GFARM_ERR_NO_MEMORY); - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->user_remove, u)); + return (db_enter((dbq_entry_func_t)ops->user_remove, u)); } gfarm_error_t @@ -572,11 +661,11 @@ gflog_debug(GFARM_MSG_1002010, "db_group_dup() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->group_add, g)); + return (db_enter((dbq_entry_func_t)ops->group_add, g)); } -gfarm_error_t -db_group_modify(const struct gfarm_group_info *gi, int modflags, +struct db_group_modify_arg * +db_group_modify_arg_alloc(const struct gfarm_group_info *gi, int modflags, int add_count, const char **add_users, int del_count, const char **del_users) { @@ -604,11 +693,8 @@ if (!overflow) arg = db_group_dup(gi, size); - if (overflow || arg == NULL) { - gflog_debug(GFARM_MSG_1002011, - "overflow occurred or db_group_dup() failed"); - return (GFARM_ERR_NO_MEMORY); - } + if (overflow || arg == NULL) + return (NULL); arg->add_users = (char **)((char *)arg + ALIGN(sizeof(*arg))); arg->del_users = (char **)((char *)arg->add_users + sizeof(*arg->add_users) * add_count); @@ -631,17 +717,33 @@ strcpy(arg->add_users[i], add_users[i]); for (i = 0; i < del_count; i++) strcpy(arg->del_users[i], del_users[i]); - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->group_modify, arg)); + return (arg); } gfarm_error_t +db_group_modify(const struct gfarm_group_info *gi, int modflags, + int add_count, const char **add_users, + int del_count, const char **del_users) +{ + struct db_group_modify_arg *arg = db_group_modify_arg_alloc( + gi, modflags, add_count, add_users, del_count, del_users); + + if (arg == NULL) { + gflog_debug(GFARM_MSG_UNFIXED, + "db_group_modify_arg_alloc failed"); + return (GFARM_ERR_NO_MEMORY); + } + return (db_enter((dbq_entry_func_t)ops->group_modify, arg)); +} + +gfarm_error_t db_group_remove(const char *groupname) { char *g = strdup_log(groupname, "db_group_remove"); if (g == NULL) return (GFARM_ERR_NO_MEMORY); - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->group_remove, g)); + return (db_enter((dbq_entry_func_t)ops->group_remove, g)); } gfarm_error_t @@ -698,7 +800,7 @@ gflog_debug(GFARM_MSG_1002014, "db_inode_dup() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->inode_add, i)); + return (db_enter((dbq_entry_func_t)ops->inode_add, i)); } gfarm_error_t @@ -710,7 +812,7 @@ gflog_debug(GFARM_MSG_1002015, "db_inode_dup() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->inode_modify, i)); + return (db_enter((dbq_entry_func_t)ops->inode_modify, i)); } gfarm_error_t @@ -726,8 +828,7 @@ } arg->inum = inum; arg->uint64 = gen; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_gen_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_gen_modify, arg)); } gfarm_error_t @@ -743,8 +844,7 @@ } arg->inum = inum; arg->uint64 = nlink; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_nlink_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_nlink_modify, arg)); } gfarm_error_t @@ -760,8 +860,7 @@ } arg->inum = inum; arg->uint64 = size; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_size_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_size_modify, arg)); } gfarm_error_t @@ -777,117 +876,104 @@ } arg->inum = inum; arg->uint32 = mode; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_mode_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_mode_modify, arg)); } -gfarm_error_t -db_inode_user_modify(gfarm_ino_t inum, const char *user) +struct db_inode_string_modify_arg * +db_inode_string_modify_arg_alloc(gfarm_ino_t inum, const char *str) { struct db_inode_string_modify_arg *arg; size_t sz; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), - gfarm_size_add(&overflow, strlen(user), 1)); + gfarm_size_add(&overflow, strlen(str), 1)); if (!overflow) arg = malloc(sz); - if (overflow || arg == NULL) { - gflog_debug(GFARM_MSG_1002019, - "allocation of 'db_inode_string_modify_arg' failed " - "or overflow"); - return (GFARM_ERR_NO_MEMORY); - } + if (overflow || arg == NULL) + return (NULL); arg->string = (char *)arg + sizeof(*arg); arg->inum = inum; - strcpy(arg->string, user); - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_user_modify, arg)); + strcpy(arg->string, str); + return (arg); } gfarm_error_t -db_inode_group_modify(gfarm_ino_t inum, const char *group) +db_inode_user_modify(gfarm_ino_t inum, const char *user) { - struct db_inode_string_modify_arg *arg; - size_t sz; - int overflow = 0; + struct db_inode_string_modify_arg *arg = + db_inode_string_modify_arg_alloc(inum, user); - sz = gfarm_size_add(&overflow, sizeof(*arg), - gfarm_size_add(&overflow, strlen(group), 1)); - if (!overflow) - arg = malloc(sz); - if (overflow || arg == NULL) { - gflog_debug(GFARM_MSG_1002020, - "allocation of 'db_inode_string_modify_arg' failed"); + if (arg == NULL) { + gflog_debug(GFARM_MSG_UNFIXED, + "db_inode_string_modify_arg_alloc failed"); return (GFARM_ERR_NO_MEMORY); } - arg->string = (char *)arg + sizeof(*arg); - - arg->inum = inum; - strcpy(arg->string, group); - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_group_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_user_modify, arg)); } gfarm_error_t -db_inode_atime_modify(gfarm_ino_t inum, struct gfarm_timespec *atime) +db_inode_group_modify(gfarm_ino_t inum, const char *group) { - struct db_inode_timespec_modify_arg *arg; + struct db_inode_string_modify_arg *arg = + db_inode_string_modify_arg_alloc(inum, group); - GFARM_MALLOC(arg); if (arg == NULL) { - gflog_debug(GFARM_MSG_1002021, - "allocation of 'db_inode_timespec_modify_arg' failed"); + gflog_debug(GFARM_MSG_UNFIXED, + "db_inode_string_modify_arg_alloc failed"); return (GFARM_ERR_NO_MEMORY); } - arg->inum = inum; - arg->time = *atime; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_atime_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_group_modify, arg)); } -gfarm_error_t -db_inode_mtime_modify(gfarm_ino_t inum, struct gfarm_timespec *mtime) +static gfarm_error_t +db_inode_time_modify(gfarm_ino_t inum, struct gfarm_timespec *t, + dbq_entry_func_t op) { struct db_inode_timespec_modify_arg *arg; GFARM_MALLOC(arg); if (arg == NULL) { - gflog_debug(GFARM_MSG_1002022, + gflog_debug(GFARM_MSG_1002021, "allocation of 'db_inode_timespec_modify_arg' failed"); return (GFARM_ERR_NO_MEMORY); } arg->inum = inum; - arg->time = *mtime; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_mtime_modify, arg)); + arg->time = *t; + return (db_enter(op, arg)); } gfarm_error_t -db_inode_ctime_modify(gfarm_ino_t inum, struct gfarm_timespec *ctime) +db_inode_atime_modify(gfarm_ino_t inum, struct gfarm_timespec *atime) { - struct db_inode_timespec_modify_arg *arg; + return (db_inode_time_modify(inum, atime, + (dbq_entry_func_t)ops->inode_atime_modify)); +} - GFARM_MALLOC(arg); - if (arg == NULL) { - gflog_debug(GFARM_MSG_1002023, - "allocation of 'db_inode_timespec_modify_arg' failed"); - return (GFARM_ERR_NO_MEMORY); - } - arg->inum = inum; - arg->time = *ctime; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_ctime_modify, arg)); +gfarm_error_t +db_inode_mtime_modify(gfarm_ino_t inum, struct gfarm_timespec *mtime) +{ + return (db_inode_time_modify(inum, mtime, + (dbq_entry_func_t)ops->inode_mtime_modify)); } gfarm_error_t +db_inode_ctime_modify(gfarm_ino_t inum, struct gfarm_timespec *ctime) +{ + return (db_inode_time_modify(inum, ctime, + (dbq_entry_func_t)ops->inode_ctime_modify)); +} + +gfarm_error_t db_inode_load(void *closure, void (*callback)(void *, struct gfs_stat *)) { return ((*ops->inode_load)(closure, callback)); } - struct db_inode_cksum_arg * db_inode_cksum_arg_alloc(gfarm_ino_t inum, const char *type, size_t len, const char *sum) @@ -931,8 +1017,7 @@ "db_inode_cksum_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_cksum_add, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_cksum_add, arg)); } gfarm_error_t @@ -947,8 +1032,7 @@ "db_inode_cksum_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_cksum_modify, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_cksum_modify, arg)); } gfarm_error_t @@ -963,8 +1047,7 @@ return (GFARM_ERR_NO_MEMORY); } arg->inum = inum; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->inode_cksum_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->inode_cksum_remove, arg)); } gfarm_error_t @@ -983,6 +1066,9 @@ size_t sz; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), hsize); if (!overflow) arg = malloc(sz); @@ -1009,7 +1095,7 @@ "db_filecopy_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->filecopy_add, arg)); + return (db_enter((dbq_entry_func_t)ops->filecopy_add, arg)); } gfarm_error_t @@ -1023,7 +1109,7 @@ "db_filecopy_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->filecopy_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->filecopy_remove, arg)); } gfarm_error_t @@ -1043,6 +1129,9 @@ size_t sz; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), hsize); if (!overflow) arg = malloc(sz); @@ -1072,8 +1161,7 @@ "db_deadfilecopy_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->deadfilecopy_add, arg)); + return (db_enter((dbq_entry_func_t)ops->deadfilecopy_add, arg)); } gfarm_error_t @@ -1088,8 +1176,7 @@ "db_deadfilecopy_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->deadfilecopy_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->deadfilecopy_remove, arg)); } gfarm_error_t @@ -1109,6 +1196,9 @@ size_t sz; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), entry_len + 1); if (!overflow) arg = malloc(sz); @@ -1139,8 +1229,7 @@ "db_direntry_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->direntry_add, arg)); + return (db_enter((dbq_entry_func_t)ops->direntry_add, arg)); } gfarm_error_t @@ -1154,8 +1243,7 @@ "db_direntry_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->direntry_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->direntry_remove, arg)); } gfarm_error_t @@ -1172,6 +1260,9 @@ size_t sz; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), strlen(source_path) + 1); if (!overflow) arg = malloc(sz); @@ -1198,7 +1289,7 @@ "db_symlink_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->symlink_add, arg)); + return (db_enter((dbq_entry_func_t)ops->symlink_add, arg)); } gfarm_error_t @@ -1213,7 +1304,7 @@ return (GFARM_ERR_NO_MEMORY); } arg->inum = inum; - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->symlink_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->symlink_remove, arg)); } gfarm_error_t @@ -1222,13 +1313,17 @@ return ((*ops->symlink_load)(closure, callback)); } -static struct db_xattr_arg * -db_xattr_arg_alloc(char *attrname, size_t valsize) +struct db_xattr_arg * +db_xattr_arg_alloc(int xmlMode, gfarm_ino_t inum, const char *attrname, + void *value, size_t valsize) { struct db_xattr_arg *arg; size_t size; int overflow = 0; +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif size = gfarm_size_add(&overflow, sizeof(*arg), valsize); if (attrname != NULL) { size = gfarm_size_add(&overflow, size, strlen(attrname) + 1); @@ -1247,6 +1342,16 @@ if (attrname != NULL) { arg->attrname = (char *)(arg + 1) + valsize; strcpy(arg->attrname, attrname); + } else + arg->attrname = NULL; + arg->xmlMode = xmlMode; + arg->inum = inum; + if (value != NULL) { + memcpy(arg->value, value, valsize); + arg->size = valsize; + } else { + arg->value = NULL; + arg->size = 0; } return (arg); } @@ -1256,28 +1361,31 @@ void *value, size_t size, struct db_waitctx *waitctx) { gfarm_error_t e; - struct db_xattr_arg *arg = db_xattr_arg_alloc(attrname, size); + struct db_xattr_arg *arg = db_xattr_arg_alloc(xmlMode, inum, + attrname, value, size); if (arg == NULL) { gflog_debug(GFARM_MSG_1002041, "db_xattr_arg_alloc() failed"); return (GFARM_ERR_NO_ERROR); } - arg->xmlMode = xmlMode; - arg->inum = inum; - memcpy(arg->value, value, size); - arg->size = size; if (waitctx != NULL) { +#ifdef ENABLE_JOURNAL + /* XXX FIXME we cannot wait for db transaction to be + * committed when the journal function is enabled. */ + e = db_enter((dbq_entry_func_t)ops->xattr_add, arg); + waitctx->e = e; +#else /* * NOTE: EINVAL returns from PostgreSQL if value is * invalid XML data. We must wait to check it. * Same as db_xattr_modify(). */ - e = dbq_enter_for_waitret(&dbq, + e = dbq_enter_for_waitret( (dbq_entry_func_t)ops->xattr_add, arg, waitctx); +#endif } else - e = dbq_enter(&dbq, - (dbq_entry_func_t)ops->xattr_add, arg); + e = db_enter((dbq_entry_func_t)ops->xattr_add, arg); return (e); } @@ -1286,55 +1394,55 @@ void *value, size_t size, struct db_waitctx *waitctx) { gfarm_error_t e; - struct db_xattr_arg *arg = db_xattr_arg_alloc(attrname, size); + struct db_xattr_arg *arg = db_xattr_arg_alloc(xmlMode, inum, + attrname, value, size); if (arg == NULL) { gflog_debug(GFARM_MSG_1002042, "db_xattr_arg_alloc() failed"); return (GFARM_ERR_NO_ERROR); } - arg->xmlMode = xmlMode; - arg->inum = inum; - memcpy(arg->value, value, size); - arg->size = size; - if (waitctx != NULL) - e = dbq_enter_for_waitret(&dbq, + if (waitctx != NULL) { +#ifdef ENABLE_JOURNAL + /* XXX FIXME we cannot wait for db transaction to be + * committed when the journal function is enabled. */ + e = db_enter((dbq_entry_func_t)ops->xattr_modify, arg); + waitctx->e = e; +#else + e = dbq_enter_for_waitret( (dbq_entry_func_t)ops->xattr_modify, arg, waitctx); - else - e = dbq_enter(&dbq, - (dbq_entry_func_t)ops->xattr_modify, arg); +#endif + } else + e = db_enter((dbq_entry_func_t)ops->xattr_modify, arg); return (e); } gfarm_error_t db_xattr_remove(int xmlMode, gfarm_ino_t inum, char *attrname) { - struct db_xattr_arg *arg = db_xattr_arg_alloc(attrname, 0); + struct db_xattr_arg *arg = db_xattr_arg_alloc(xmlMode, inum, + attrname, NULL, 0); if (arg == NULL) { gflog_debug(GFARM_MSG_1002043, "db_xattr_arg_alloc() failed"); return (GFARM_ERR_NO_ERROR); } - arg->xmlMode = xmlMode; - arg->inum = inum; - return (dbq_enter(&dbq, - (dbq_entry_func_t)ops->xattr_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->xattr_remove, arg)); } gfarm_error_t db_xattr_removeall(int xmlMode, gfarm_ino_t inum) { if (ops->xattr_removeall != NULL) { - struct db_xattr_arg *arg = db_xattr_arg_alloc(NULL, 0); + struct db_xattr_arg *arg = db_xattr_arg_alloc(xmlMode, inum, + NULL, NULL, 0); if (arg == NULL) { gflog_debug(GFARM_MSG_1002044, "db_xattr_arg_alloc() failed"); return (GFARM_ERR_NO_ERROR); } - arg->xmlMode = xmlMode; - arg->inum = inum; - return (dbq_enter(&dbq, + return (db_enter( (dbq_entry_func_t)ops->xattr_removeall, arg)); } else return (GFARM_ERR_OPERATION_NOT_SUPPORTED); @@ -1344,17 +1452,16 @@ db_xattr_get(int xmlMode, gfarm_ino_t inum, char *attrname, void **valuep, size_t *sizep, struct db_waitctx *waitctx) { - struct db_xattr_arg *arg = db_xattr_arg_alloc(attrname, 0); + struct db_xattr_arg *arg = db_xattr_arg_alloc(xmlMode, inum, + attrname, NULL, 0); if (arg == NULL) { gflog_debug(GFARM_MSG_1002045, "db_xattr_arg_alloc() failed"); return (GFARM_ERR_NO_ERROR); } - arg->xmlMode = xmlMode; - arg->inum = inum; arg->valuep = valuep; arg->sizep = sizep; - return (dbq_enter_for_waitret(&dbq, + return (dbq_enter_for_waitret( (dbq_entry_func_t)ops->xattr_get, arg, waitctx)); } @@ -1382,13 +1489,13 @@ arg->expr = expr; arg->foundcallback = foundcallback; arg->foundcbdata = foundcbdata; - return (dbq_enter_withcallback(&dbq, + return (dbq_enter_withcallback( (dbq_entry_func_t)ops->xmlattr_find, arg, (dbq_entry_func_callback_t)callback, cbdata)); } /* quota */ -static struct db_quota_arg * +struct db_quota_arg * db_quota_arg_alloc(const struct quota *q, const char *name, int is_group) { struct db_quota_arg *arg; @@ -1396,6 +1503,9 @@ int overflow = 0; int name_len = strlen(name); +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), name_len + 1); if (!overflow) arg = malloc(sz); @@ -1425,11 +1535,9 @@ } if (q->on_db) - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->quota_modify, - arg)); + return (db_enter((dbq_entry_func_t)ops->quota_modify, arg)); else - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->quota_add, - arg)); + return (db_enter((dbq_entry_func_t)ops->quota_add, arg)); } gfarm_error_t @@ -1444,7 +1552,7 @@ return (db_quota_set_common(q, groupname, 1)); } -static struct db_quota_remove_arg * +struct db_quota_remove_arg * db_quota_remove_arg_alloc(const char *name, int is_group) { struct db_quota_remove_arg *arg; @@ -1452,6 +1560,9 @@ int overflow = 0; int name_len = strlen(name); +#ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ + arg = NULL; +#endif sz = gfarm_size_add(&overflow, sizeof(*arg), name_len + 1); if (!overflow) arg = malloc(sz); @@ -1480,7 +1591,7 @@ "db_quota_remove_arg_alloc() failed"); return (GFARM_ERR_NO_MEMORY); } - return (dbq_enter(&dbq, (dbq_entry_func_t)ops->quota_remove, arg)); + return (db_enter((dbq_entry_func_t)ops->quota_remove, arg)); } gfarm_error_t @@ -1508,3 +1619,42 @@ { return ((*ops->quota_load)(closure, 1, callback)); } + +#ifdef ENABLE_JOURNAL + +gfarm_error_t +db_seqnum_add(char *name, gfarm_uint64_t value) +{ + struct db_seqnum_arg a; + + a.name = name; + a.value = value; + /* a is not freed */ + return (ops->seqnum_add(&a)); +} + +gfarm_error_t +db_seqnum_modify(char *name, gfarm_uint64_t value) +{ + struct db_seqnum_arg a; + + a.name = name; + a.value = value; + /* a is not freed */ + return (ops->seqnum_modify(&a)); +} + +gfarm_error_t +db_seqnum_remove(char *name) +{ + return (ops->seqnum_remove(name)); +} + +gfarm_error_t +db_seqnum_load(void *closure, + void (*callback)(void *, struct db_seqnum_arg *)) +{ + return ((*ops->seqnum_load)(closure, callback)); +} + +#endif /* ENABLE_JOURNAL */ Modified: gfarm_v2/trunk/server/gfmd/db_access.h =================================================================== --- gfarm_v2/trunk/server/gfmd/db_access.h 2011-01-31 05:47:18 UTC (rev 5098) +++ gfarm_v2/trunk/server/gfmd/db_access.h 2011-01-31 07:06:07 UTC (rev 5099) @@ -109,13 +109,64 @@ void (*)(void *, struct gfarm_quota_info *)); gfarm_error_t db_quota_group_load(void *, void (*)(void *, struct gfarm_quota_info *)); +#ifdef ENABLE_JOURNAL +struct db_seqnum_arg; +gfarm_error_t db_seqnum_add(char *, gfarm_uint64_t); +gfarm_error_t db_seqnum_modify(char *, gfarm_uint64_t); +gfarm_error_t db_seqnum_remove(char *); +gfarm_error_t db_seqnum_load(void *, + void (*)(void *, struct db_seqnum_arg *)); +#endif +/* allocation for storage operations arguments */ +struct db_host_modify_arg; +struct db_user_modify_arg; +struct db_group_modify_arg; +struct db_inode_string_modify_arg; +struct db_inode_cksum_arg; +struct db_filecopy_arg; +struct db_deadfilecopy_arg; +struct db_direntry_arg; +struct db_symlink_arg; +struct db_xattr_arg; +struct db_quota_arg; +struct db_quota_remove_arg; + +void *db_host_dup(const struct gfarm_host_info *, size_t); +void *db_user_dup(const struct gfarm_user_info *, size_t); +void *db_group_dup(const struct gfarm_group_info *, size_t); +struct gfs_stat *db_inode_dup(const struct gfs_stat *, size_t); +struct db_host_modify_arg *db_host_modify_arg_alloc( + const struct gfarm_host_info *, int, int, const char **, int, + const char **); +struct db_user_modify_arg *db_user_modify_arg_alloc( + const struct gfarm_user_info *, int); +struct db_group_modify_arg *db_group_modify_arg_alloc( + const struct gfarm_group_info *, int, int, const char **, int, + const char **); +struct db_inode_string_modify_arg *db_inode_string_modify_arg_alloc( + gfarm_ino_t, const char *); +struct db_inode_cksum_arg *db_inode_cksum_arg_alloc(gfarm_ino_t, + const char *, size_t, const char *); +struct db_filecopy_arg *db_filecopy_arg_alloc(gfarm_ino_t, const char *); +struct db_deadfilecopy_arg *db_deadfilecopy_arg_alloc(gfarm_ino_t, + gfarm_uint64_t, const char *); +struct db_direntry_arg *db_direntry_arg_alloc(gfarm_ino_t, const char *, + int, gfarm_ino_t); +struct db_symlink_arg *db_symlink_arg_alloc(gfarm_ino_t, const char *); +struct db_xattr_arg *db_xattr_arg_alloc(int, gfarm_ino_t, const char *, + void *, size_t); +struct db_quota_arg *db_quota_arg_alloc(const struct quota *, const char *, + int); +struct db_quota_remove_arg *db_quota_remove_arg_alloc(const char *, int); + /* external interface to select metadb backend type */ struct db_ops; gfarm_error_t db_use(const struct db_ops *); extern const struct db_ops db_none_ops, db_ldap_ops, db_pgsql_ops; +const struct db_ops *store_ops; struct db_waitctx { @@ -131,7 +182,7 @@ /* exported for a use from a private extension */ /* The official gfmd source code shouldn't use these interface */ -typedef gfarm_error_t (*dbq_entry_func_t)(void *); +typedef gfarm_error_t (*dbq_entry_func_t)(gfarm_uint64_t, void *); gfarm_error_t gfarm_dbq_enter(dbq_entry_func_t, void *); gfarm_error_t gfarm_dbq_enter_for_waitret( dbq_entry_func_t, void *, struct db_waitctx *); Added: gfarm_v2/trunk/server/gfmd/db_journal.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_journal.c (rev 0) +++ gfarm_v2/trunk/server/gfmd/db_journal.c 2011-01-31 07:06:07 UTC (rev 5099) @@ -0,0 +1,6642 @@ +/* + * $Id$ + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netinet/in.h> +#include <stdarg.h> +#include <errno.h> +#include <sys/param.h> +#ifdef DEBUG_JOURNAL +#include <sys/time.h> +#endif + +#include <gfarm/gfarm.h> + +#include "gfutil.h" +#ifdef DEBUG_JOURNAL +#include "timer.h" +#endif + +#include "metadb_common.h" +#include "xattr_info.h" +#include "quota_info.h" +#include "quota.h" +#include "gfp_xdr.h" +#include "io_fd.h" +#ifdef DEBUG_JOURNAL +#include "gfs_profile.h" +#endif +#include "config.h" + +#include "subr.h" +#include "thrsubr.h" +#include "host.h" +#include "user.h" +#include "group.h" +#include "inode.h" +#include "journal_file.h" +#include "db_common.h" +#include "db_access.h" +#include "db_ops.h" +#include "db_journal.h" + +#define JOURNAL_SEQNUM_NOT_SET UINT64_MAX +#define JOURNAL_W_XDR journal_file_writer_xdr( \ + journal_file_writer(self_jf)) + +#define NON_NULL_STR(s) ((s) ? (s) : "") + +#ifdef ENABLE_JOURNAL + +static struct journal_file *self_jf; +static const struct db_ops *journal_apply_ops; + +static gfarm_uint64_t journal_seqnum = JOURNAL_SEQNUM_NOT_SET; +static int journal_transaction_nesting = 0; + +static void +db_seqnum_load_callback(void *closure, struct db_seqnum_arg *a) +{ + if (a->name == NULL || strlen(a->name) == 0) + journal_seqnum = a->value; + free(a->name); +} + +static gfarm_error_t +db_journal_initialize(void) +{ + gfarm_error_t e; + char path[MAXPATHLEN + 1]; + const char *journal_dir = gfarm_journal_dir(); + const char *diag = "db_journal_initialize"; +#ifdef DEBUG_JOURNAL + gfarm_timerval_t t1, t2; + double ts; +#endif + + if (journal_dir == NULL) { + e = GFARM_ERR_INVALID_ARGUMENT; + gflog_error(GFARM_MSG_UNFIXED, + "gfarm_journal_file_dir is empty : %s", + gfarm_error_string(e)); + return (e); + } + if ((e = db_seqnum_load(NULL, db_seqnum_load_callback)) + != GFARM_ERR_NO_ERROR && e != GFARM_ERR_NO_SUCH_OBJECT) { + gflog_debug(GFARM_MSG_UNFIXED, + "db_seqnum_load : %s", + gfarm_error_string(e)); + return (e); + } + if (journal_seqnum == JOURNAL_SEQNUM_NOT_SET) { + do { + if ((e = db_begin(diag)) != GFARM_ERR_NO_ERROR) + break; + if ((e = db_seqnum_add("", 1)) != GFARM_ERR_NO_ERROR) + break; + e = db_end(diag); + } while (0); + if (e != GFARM_ERR_NO_ERROR) { + gflog_error(GFARM_MSG_UNFIXED, + "failed to add the update sequence number to db" + " : %s", gfarm_error_string(e)); + return (e); + } + } + + snprintf(path, MAXPATHLEN, "%s/%010d.gmj", journal_dir, 0); +#ifdef DEBUG_JOURNAL + gfs_profile_set(); + gfarm_gettimerval(&t1); +#endif + if ((e = journal_file_open(path, gfarm_journal_max_size(), + journal_seqnum, &self_jf, GFARM_JOURNAL_RDWR)) + != GFARM_ERR_NO_ERROR) { + gflog_debug(GFARM_MSG_UNFIXED, + "gfm_server_journal_file_open : %s", + gfarm_error_string(e)); + return (e); + } +#ifdef DEBUG_JOURNAL + gfarm_gettimerval(&t2); + ts = gfarm_timerval_sub(&t2, &t1); + gflog_info(GFARM_MSG_UNFIXED, + "DEBUG_JOURNAL : journal_file_open : %10.5lf sec", ts); +#endif + + return (GFARM_ERR_NO_ERROR); +} + +void +db_journal_set_apply_ops(const struct db_ops *apply_ops) +{ + journal_apply_ops = apply_ops; +} + +static gfarm_error_t +db_journal_terminate(void) +{ + journal_file_close(self_jf); + return (GFARM_ERR_NO_ERROR); +} + +static gfarm_error_t +db_journal_begin(gfarm_uint64_t seqnum, void *arg) +{ + ++journal_transaction_nesting; + return (GFARM_ERR_NO_ERROR); +} + +static gfarm_error_t +db_journal_end(gfarm_uint64_t seqnum, void *arg) +{ + if (journal_transaction_nesting > 0) + --journal_transaction_nesting; + return (GFARM_ERR_NO_ERROR); +} + +/* PREREQUISITE: giant_lock */ +gfarm_uint64_t +db_journal_next_seqnum(void) +{ + return (++journal_seqnum); +} + +static gfarm_error_t +db_journal_read_string(struct gfp_xdr *xdr, enum journal_operation ope, + char **strp) +{ + gfarm_error_t e; + int eof; + + if ((e = gfp_xdr_recv(xdr, 1, &eof, "s", strp)) + != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_recv", e, ope); + return (e); + } + return (GFARM_ERR_NO_ERROR); +} + +static gfarm_error_t +db_journal_xdr_send_string_array_size_add(size_t *sizep, + enum journal_operation ope, int n, char **ary) +{ + gfarm_error_t e; + int i; + + if ((e = gfp_xdr_send_size_add(sizep, "i", n)) + != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_send_size_add", e, ope); + return (e); + } + for (i = 0; i < n; ++i) { + if ((e = gfp_xdr_send_size_add(sizep, "s", + ary[i])) != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_send_size_add", e, ope); + return (e); + } + } + return (GFARM_ERR_NO_ERROR); +} + +static gfarm_error_t +db_journal_xdr_send_string_array( + enum journal_operation ope, int n, char **ary) +{ + gfarm_error_t e; + int i; + + if ((e = gfp_xdr_send(JOURNAL_W_XDR, "i", n)) + != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_send", e, ope); + return (e); + } + for (i = 0; i < n; ++i) { + if ((e = gfp_xdr_send(JOURNAL_W_XDR, "s", + ary[i])) != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_send", e, ope); + return (e); + } + } + return (GFARM_ERR_NO_ERROR); +} + +static gfarm_error_t +db_journal_xdr_recv_string_array(struct gfp_xdr *xdr, + enum journal_operation ope, int *np, char ***aryp) +{ + gfarm_error_t e; + char **ary; + int i, j, eof, n; + + *aryp = NULL; + *np = 0; + + if ((e = gfp_xdr_recv(xdr, 1, &eof, "i", &n)) + != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_recv", e, ope); + return (e); + } + GFARM_MALLOC_ARRAY(ary, n + 1); + if (ary == NULL) { + e = GFARM_ERR_NO_MEMORY; + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "GFARM_MALLOC_ARRAY", e, ope); + return (e); + } + for (i = 0; i < n; ++i) { + if ((e = gfp_xdr_recv(xdr, 1, &eof, "s", + &ary[i])) != GFARM_ERR_NO_ERROR) { + GFLOG_DEBUG_WITH_OPE(GFARM_MSG_UNFIXED, + "gfp_xdr_recv", e, ope); + for (j = 0; j < i; ++j) + free(ary[i]); + free(ary); + return (e); + } + } + ary[n] = NULL; + *aryp = ary; + *np = n; + return (GFARM_ERR_NO_ERROR); +} + +/**********************************************************/ +/* destructor */ + +static void +db_journal_string_array_free(int n, char **ary) +{ + int i; + + for (i = 0; i < n; ++i) + free(ary[i]); + if (ary) + free(ary); +} + +static void +db_journal_host_info_destroy(struct gfarm_host_info *hi) +{ + gfarm_host_info_free(hi); + free(hi); +} + +static void +db_journal_host_modify_arg_destroy(struct db_host_modify_arg *arg) +{ + gfarm_host_info_free(&arg->hi); + db_journal_string_array_free(arg->add_count, arg->add_aliases); + db_journal_string_array_free(arg->del_count, arg->del_aliases); + free(arg); +} + +static void +db_journal_user_modify_arg_destroy(struct db_user_modify_arg *arg) +{ + gfarm_user_info_free(&arg->ui); + free(arg); +} + +static void +db_journal_user_info_destroy(struct gfarm_user_info *ui) +{ + gfarm_user_info_free(ui); + free(ui); +} + +static void +db_journal_group_info_destroy(struct gfarm_group_info *gi) +{ + gfarm_group_info_free(gi); + free(gi); +} + +static void +db_journal_group_modify_arg_destroy(struct db_group_modify_arg *arg) +{ + gfarm_group_info_free(&arg->gi); + db_journal_string_array_free(arg->add_count, arg->add_users); + db_journal_string_array_free(arg->del_count, arg->del_users); + free(arg); +} + +static void +db_journal_inode_string_modify_arg_destroy( + struct db_inode_string_modify_arg *arg) +{ + free(arg->string); + free(arg); +} + +static void +db_journal_inode_cksum_arg_destroy(struct db_inode_cksum_arg *arg) +{ + free(arg->type); + free(arg->sum); + free(arg); +} + +static void +db_journal_filecopy_arg_destroy(struct db_filecopy_arg *arg) +{ + free(arg->hostname); + free(arg); +} + +static void +db_journal_deadfilecopy_arg_destroy(struct db_deadfilecopy_arg *arg) +{ + free(arg->hostname); + free(arg); +} + +static void +db_journal_direntry_arg_destroy(struct db_direntry_arg *arg) +{ + free(arg->entry_name); + free(arg); +} + +static void +db_journal_symlink_arg_destroy(struct db_symlink_arg *arg) +{ + free(arg->source_path); + free(arg); +} + +static void +db_journal_xattr_arg_destroy(struct db_xattr_arg *arg) +{ + free(arg->attrname); + free(arg->value); + free(arg); +} + +static void +db_journal_quota_arg_destroy(struct db_quota_arg *arg) +{ + free(arg->name); + free(arg); +} + +static void +db_journal_quota_remove_arg_destroy(struct db_quota_remove_arg *arg) +{ + free(arg->name); + free(arg); +} + +static void +db_journal_stat_destroy(struct gfs_stat *st) +{ + gfs_stat_free(st); + free(st); +} + +/**********************************************************/ + +/* PREREQUISITE: gi... [truncated message content] |