From: <ta...@us...> - 2006-09-19 15:46:30
|
Revision: 3176 http://svn.sourceforge.net/gfarm/?rev=3176&view=rev Author: tatebe Date: 2006-09-19 08:46:23 -0700 (Tue, 19 Sep 2006) Log Message: ----------- merge the following change by soda-san in AIST cvs repository: make GFS_Dir functions work even when the return value of gfarm_agent_check() is changed. without this change, the functions may dump core. Modified Paths: -------------- trunk/gfarm/lib/libgfarm/gfarm/Makefile trunk/gfarm/lib/libgfarm/gfarm/agent_client.c trunk/gfarm/lib/libgfarm/gfarm/agent_client.h trunk/gfarm/lib/libgfarm/gfarm/agent_wrap.c trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.c Added Paths: ----------- trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.h Modified: trunk/gfarm/lib/libgfarm/gfarm/Makefile =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/Makefile 2006-09-19 15:35:24 UTC (rev 3175) +++ trunk/gfarm/lib/libgfarm/gfarm/Makefile 2006-09-19 15:46:23 UTC (rev 3176) @@ -64,7 +64,7 @@ $(OBJS): $(DEPGFARMINC) $(GLOBUS_OBJS): $(DEPGFSLINC) -agent_wrap.lo: agent_client.h agent_wrap.h metadb_access.h +agent_wrap.lo: agent_client.h agent_wrap.h metadb_access.h gfs_dir.h agent_client.lo: xxx_proto.h io_fd.h config.h sockopt.h agent_proto.h agent_client.h agent_wrap.h agent_proto.lo: xxx_proto.h auth_client.lo: $(GFUTIL_SRCDIR)/gfutil.h $(GFUTIL_SRCDIR)/gfevent.h xxx_proto.h auth.h @@ -86,7 +86,7 @@ gfs_client_apply.lo: $(GFUTIL_SRCDIR)/gfutil.h host.h config.h gfs_client.h gfs_misc.h schedule.h gfs_client_dir.lo: config.h gfs_client.h gfs_misc.h gfs_client_rep.lo: $(GFUTIL_SRCDIR)/gfutil.h xxx_proto.h io_fd.h host.h param.h auth.h config.h gfs_proto.h gfs_client.h -gfs_dir.lo: $(GFUTIL_SRCDIR)/hash.h $(GFUTIL_SRCDIR)/tree.h $(GFUTIL_SRCDIR)/gfutil.h metadb_access.h gfs_misc.h path_info_cache.h +gfs_dir.lo: $(GFUTIL_SRCDIR)/hash.h $(GFUTIL_SRCDIR)/tree.h $(GFUTIL_SRCDIR)/gfutil.h metadb_access.h gfs_misc.h path_info_cache.h gfs_dir.h gfs_exec.lo: config.h gfs_misc.h gfs_lock.lo: $(INC_SRCDIR)/gfarm_misc.h gfs_pio.lo: $(GFUTIL_SRCDIR)/timer.h $(GFUTIL_SRCDIR)/gfutil.h config.h gfs_proto.h gfs_pio.h gfs_misc.h Modified: trunk/gfarm/lib/libgfarm/gfarm/agent_client.c =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/agent_client.c 2006-09-19 15:35:24 UTC (rev 3175) +++ trunk/gfarm/lib/libgfarm/gfarm/agent_client.c 2006-09-19 15:46:23 UTC (rev 3176) @@ -289,31 +289,23 @@ char * agent_client_opendir(struct agent_connection *agent_server, - const char *path, GFS_Dir *dirp) + const char *path, gfarm_int32_t *dirdescp) { - gfarm_int32_t p; - char *e; - - e = agent_client_rpc(agent_server, 0, AGENT_PROTO_OPENDIR, "s/i", - path, &p); - if (e == NULL) - /* portability fix for lp64 */ - *dirp = (GFS_Dir)(long)p; - return (e); + return (agent_client_rpc(agent_server, 0, AGENT_PROTO_OPENDIR, "s/i", + path, dirdescp)); } char * agent_client_readdir(struct agent_connection *agent_server, - GFS_Dir dir, struct gfs_dirent **entry) + gfarm_int32_t dirdesc, struct gfs_dirent **entry) { - gfarm_int32_t p = (gfarm_int32_t)(long)dir; char *e, *name; static struct gfs_dirent de; gfarm_uint32_t ino; e = agent_client_rpc( agent_server, 0, AGENT_PROTO_READDIR, - "i/ihccs", p, + "i/ihccs", dirdesc, &ino, &de.d_reclen, &de.d_type, &de.d_namlen, &name); if (e == NULL) { @@ -330,25 +322,24 @@ } char * -agent_client_closedir(struct agent_connection *agent_server, GFS_Dir dir) +agent_client_closedir(struct agent_connection *agent_server, + gfarm_int32_t dirdesc) { - gfarm_int32_t p = (gfarm_int32_t)(long)dir; - return (agent_client_rpc( agent_server, 0, AGENT_PROTO_CLOSEDIR, - "i/", p)); + "i/", dirdesc)); } char * -agent_client_dirname(struct agent_connection *agent_server, GFS_Dir dir) +agent_client_dirname(struct agent_connection *agent_server, + gfarm_int32_t dirdesc) { - gfarm_int32_t p = (gfarm_int32_t)(long)dir; char *e, *n; static char name[GFS_MAXNAMLEN]; e = agent_client_rpc( agent_server, 0, AGENT_PROTO_DIRNAME, - "i/s", p, &n); + "i/s", dirdesc, &n); if (e == NULL) { strcpy(name, n); free(n); @@ -360,22 +351,18 @@ char * agent_client_seekdir(struct agent_connection *agent_server, - GFS_Dir dir, file_offset_t off) + gfarm_int32_t dirdesc, file_offset_t off) { - gfarm_int32_t p = (gfarm_int32_t)(long)dir; - return (agent_client_rpc(agent_server, 0, AGENT_PROTO_SEEKDIR, "io/", - p, off)); + dirdesc, off)); } char * agent_client_telldir(struct agent_connection *agent_server, - GFS_Dir dir, file_offset_t *offp) + gfarm_int32_t dirdesc, file_offset_t *offp) { - gfarm_int32_t p = (gfarm_int32_t)(long)dir; - return (agent_client_rpc(agent_server, 0, AGENT_PROTO_TELLDIR, "i/o", - p, offp)); + dirdesc, offp)); } char * Modified: trunk/gfarm/lib/libgfarm/gfarm/agent_client.h =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/agent_client.h 2006-09-19 15:35:24 UTC (rev 3175) +++ trunk/gfarm/lib/libgfarm/gfarm/agent_client.h 2006-09-19 15:46:23 UTC (rev 3176) @@ -25,13 +25,16 @@ struct agent_connection *, const char *, char **); char *agent_client_get_ino( struct agent_connection *, const char *, gfarm_int32_t *); -char *agent_client_opendir(struct agent_connection *, const char *, GFS_Dir *); +char *agent_client_opendir(struct agent_connection *, const char *, + gfarm_int32_t *); char *agent_client_readdir( - struct agent_connection *, GFS_Dir, struct gfs_dirent **); -char *agent_client_closedir(struct agent_connection *, GFS_Dir); -char *agent_client_dirname(struct agent_connection *, GFS_Dir); -char *agent_client_seekdir(struct agent_connection *, GFS_Dir, file_offset_t); -char *agent_client_telldir(struct agent_connection *, GFS_Dir, file_offset_t*); + struct agent_connection *, gfarm_int32_t, struct gfs_dirent **); +char *agent_client_closedir(struct agent_connection *, gfarm_int32_t); +char *agent_client_dirname(struct agent_connection *, gfarm_int32_t); +char *agent_client_seekdir(struct agent_connection *, + gfarm_int32_t, file_offset_t); +char *agent_client_telldir(struct agent_connection *, + gfarm_int32_t, file_offset_t*); char *agent_client_uncachedir(struct agent_connection *); char *agent_client_host_info_get( Modified: trunk/gfarm/lib/libgfarm/gfarm/agent_wrap.c =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/agent_wrap.c 2006-09-19 15:35:24 UTC (rev 3175) +++ trunk/gfarm/lib/libgfarm/gfarm/agent_wrap.c 2006-09-19 15:46:23 UTC (rev 3176) @@ -19,6 +19,8 @@ #include "agent_client.h" #include "agent_wrap.h" +#include "gfs_dir.h" + extern char *gfarm_client_initialize(int *, char ***); extern char *gfarm_client_terminate(void); @@ -211,6 +213,8 @@ return (e); } +static void gfarm_agent_dir_invalidate(void); + char * gfarm_agent_disconnect() { @@ -223,6 +227,7 @@ /* reset agent_server even in error case */ agent_server = NULL; agent_pid = 0; + gfarm_agent_dir_invalidate(); return (e); } @@ -337,6 +342,144 @@ return (gfs_i_get_ino(canonic_path, inop)); } +/* + * GFS_Dir / gfarm_agent + */ + +struct gfs_dir_agent { + struct gfs_dir base; /* abstract base class, must be first member */ + gfarm_int32_t dirdesc; + + int valid; + struct gfs_dir_agent *next, *prev; /* doubly linked circular list */ +}; + +/* doubly linked circular list head which points all struct gfs_dir_agent */ +struct gfs_dir_agent gfs_dir_agent_list_head = { + { NULL }, + -1, + 0, + &gfs_dir_agent_list_head, &gfs_dir_agent_list_head +}; + +static char GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED[] = + "gfarm_agent connection is already closed"; + +static char * +gfarm_agent_closedir(GFS_Dir dirbase) +{ + struct gfs_dir_agent *dir = (struct gfs_dir_agent *)dirbase; + char *e = dir->valid ? + agent_client_closedir(agent_server, dir->dirdesc) : + GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED; + + /* unlink from gfs_dir_agent_list_head */ + dir->next->prev = dir->prev; + dir->prev->next = dir->next; + + free(dir); + return (e); +} + +static char * +gfarm_agent_readdir(GFS_Dir dirbase, struct gfs_dirent **entry) +{ + struct gfs_dir_agent *dir = (struct gfs_dir_agent *)dirbase; + char *e = dir->valid ? + agent_client_readdir(agent_server, dir->dirdesc, entry) : + GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED; + + return (e); +} + + +static char * +gfarm_agent_seekdir(GFS_Dir dirbase, file_offset_t off) +{ + struct gfs_dir_agent *dir = (struct gfs_dir_agent *)dirbase; + char *e = dir->valid ? + agent_client_seekdir(agent_server, dir->dirdesc, off) : + GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED; + + return (e); +} + +static char * +gfarm_agent_telldir(GFS_Dir dirbase, file_offset_t *offp) +{ + struct gfs_dir_agent *dir = (struct gfs_dir_agent *)dirbase; + char *e = dir->valid ? + agent_client_telldir(agent_server, dir->dirdesc, offp) : + GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED; + + return (e); +} + +static char * +gfarm_agent_dirname(GFS_Dir dirbase) +{ + struct gfs_dir_agent *dir = (struct gfs_dir_agent *)dirbase; + char *e = dir->valid ? + agent_client_dirname(agent_server, dir->dirdesc) : + GFARM_ERR_AGENT_CONNECTION_ALREADY_CLOSED; + + return (e); +} + +static struct gfs_dir_ops gfarm_agent_dir_ops = { + gfarm_agent_closedir, + gfarm_agent_readdir, + gfarm_agent_seekdir, + gfarm_agent_telldir, + gfarm_agent_dirname, +}; + +static char * +gfarm_agent_opendir(const char *path, GFS_Dir *dirp) +{ + struct gfs_dir_agent *dir; + char *e; + gfarm_int32_t dirdesc; + + GFARM_MALLOC(dir); + if (dir == NULL) + return (GFARM_ERR_NO_MEMORY); + + e = agent_client_opendir(agent_server, path, &dirdesc); + if (e != NULL) { + free(dir); + return (e); + } + dir->base.ops = &gfarm_agent_dir_ops; + dir->dirdesc = dirdesc; + dir->valid = 1; + + /* link to gfs_dir_agent_list_head */ + dir->next = gfs_dir_agent_list_head.next; + dir->prev = &gfs_dir_agent_list_head; + gfs_dir_agent_list_head.next->prev = dir; + gfs_dir_agent_list_head.next = dir; + + *dirp = &dir->base; + return (NULL); +} + +static void +gfarm_agent_dir_invalidate(void) +{ + struct gfs_dir_agent *dir; + + /* traverse gfs_dir_agent_list_head */ + for (dir = gfs_dir_agent_list_head.next; + dir != &gfs_dir_agent_list_head; dir = dir->next) { + dir->valid = 0; + } +} + +/* + * GFS_Dir wrapper functions + */ + char * gfs_opendir(const char *path, GFS_Dir *dirp) { @@ -371,7 +514,7 @@ return (e); if (gfarm_agent_check() == NULL) { - e = agent_client_opendir(agent_server, path, dirp); + e = gfarm_agent_opendir(path, dirp); if (e != GFARM_ERR_CONNECTION_REFUSED) return (e); /* reconnection failed, connect to metadb directly */ @@ -382,61 +525,31 @@ char * gfs_readdir(GFS_Dir dir, struct gfs_dirent **entry) { - if (gfarm_agent_check() == NULL) { - char *e = agent_client_readdir(agent_server, dir, entry); - if (e != GFARM_ERR_CONNECTION_REFUSED) - return (e); - /* reconnection failed, connect to metadb directly */ - } - return (gfs_i_readdir(dir, entry)); + return ((*dir->ops->read)(dir, entry)); } char * gfs_closedir(GFS_Dir dir) { - if (gfarm_agent_check() == NULL) { - char *e = agent_client_closedir(agent_server, dir); - if (e != GFARM_ERR_CONNECTION_REFUSED) - return (e); - /* reconnection failed, connect to metadb directly */ - } - return (gfs_i_closedir(dir)); + return ((*dir->ops->close)(dir)); } char * gfs_dirname(GFS_Dir dir) { - if (gfarm_agent_check() == NULL) { - char *e = agent_client_dirname(agent_server, dir); - if (e != GFARM_ERR_CONNECTION_REFUSED) - return (e); - /* reconnection failed, connect to metadb directly */ - } - return (gfs_i_dirname(dir)); + return ((*dir->ops->dirname)(dir)); } char * gfs_seekdir(GFS_Dir dir, file_offset_t off) { - if (gfarm_agent_check() == NULL) { - char *e = agent_client_seekdir(agent_server, dir, off); - if (e != GFARM_ERR_CONNECTION_REFUSED) - return (e); - /* reconnection failed, connect to metadb directly */ - } - return (gfs_i_seekdir(dir, off)); + return ((*dir->ops->seek)(dir, off)); } char * gfs_telldir(GFS_Dir dir, file_offset_t *offp) { - if (gfarm_agent_check() == NULL) { - char *e = agent_client_telldir(agent_server, dir, offp); - if (e != GFARM_ERR_CONNECTION_REFUSED) - return (e); - /* reconnection failed, connect to metadb directly */ - } - return (gfs_i_telldir(dir, offp)); + return ((*dir->ops->tell)(dir, offp)); } void @@ -449,7 +562,9 @@ gfs_i_uncachedir(); } -/* host info */ +/* + * host info + */ /* * If gfarm_cache_host_info_*() is used once, Modified: trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.c =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.c 2006-09-19 15:35:24 UTC (rev 3175) +++ trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.c 2006-09-19 15:46:23 UTC (rev 3176) @@ -34,6 +34,7 @@ #include "gfs_misc.h" /* gfarm_path_expand_home() */ #include "path_info_cache.h" +#include "gfs_dir.h" static char *gfarm_current_working_directory; @@ -1427,57 +1428,21 @@ * gfs_opendir()/readdir()/closedir() */ -struct gfs_dir { +struct gfs_dir_internal { + struct gfs_dir base; /* abstract base class, must be first member */ + struct node *dir; DirIterator iterator; struct gfs_dirent buffer; int index; }; -char * -gfs_i_opendir(const char *path, GFS_Dir *dirp) -{ - char *e, *canonic_path; - struct node *n; - struct gfs_dir *dir; - - e = gfarm_canonical_path(gfarm_url_prefix_skip(path), &canonic_path); - if (e != NULL) - return (e); - - e = lookup_relative(root, canonic_path, NODE_FLAG_IS_DIR, - GFARM_INODE_LOOKUP, &n); - free(canonic_path); - if (e != NULL) - return (e); - - /* here, refresh directory cache */ - if (n->flags & NODE_FLAG_INVALID) { - gfs_i_uncachedir(); - e = gfs_refreshdir(); - if (e != NULL) - return (e); - /* NODE_FLAG_INVALID is reset in gfs_cachedir() */ - } - - GFARM_MALLOC(dir); - if (dir == NULL) - return (GFARM_ERR_NO_MEMORY); - dir->dir = n; - dir_iterator_init(&dir->iterator, &n->u.d.children); - dir->index = 0; - *dirp = dir; - - ++opendir_count; - /* XXX if someone removed a path, while opening a directory... */ - return (NULL); -} - #define GFS_DIRENTSIZE 0x100 /* XXX */ char * -gfs_i_readdir(GFS_Dir dir, struct gfs_dirent **entry) +gfs_i_readdir(GFS_Dir dirbase, struct gfs_dirent **entry) { + struct gfs_dir_internal *dir = (struct gfs_dir_internal *)dirbase; struct node *n; if (dir->index == 0) { @@ -1515,16 +1480,19 @@ } char * -gfs_i_closedir(GFS_Dir dir) +gfs_i_closedir(GFS_Dir dirbase) { + struct gfs_dir_internal *dir = (struct gfs_dir_internal *)dirbase; + free(dir); --opendir_count; return (NULL); } char * -gfs_i_seekdir(GFS_Dir dir, file_offset_t off) +gfs_i_seekdir(GFS_Dir dirbase, file_offset_t off) { + struct gfs_dir_internal *dir = (struct gfs_dir_internal *)dirbase; char *e; int new_index; struct gfs_dirent *ent; @@ -1538,7 +1506,7 @@ dir->index = 0; } while (dir->index < new_index) { - e = gfs_i_readdir(dir, &ent); + e = gfs_i_readdir(&dir->base, &ent); if (e != NULL) return (e); if (ent == NULL) @@ -1548,18 +1516,65 @@ } char * -gfs_i_telldir(GFS_Dir dir, file_offset_t *offp) +gfs_i_telldir(GFS_Dir dirbase, file_offset_t *offp) { + struct gfs_dir_internal *dir = (struct gfs_dir_internal *)dirbase; *offp = dir->index * GFS_DIRENTSIZE; return (NULL); } -/* - * gfs_dirname() - */ - char * -gfs_i_dirname(GFS_Dir dir) +gfs_i_dirname(GFS_Dir dirbase) { + struct gfs_dir_internal *dir = (struct gfs_dir_internal *)dirbase; return (dir->dir->name); } + + +static struct gfs_dir_ops gfs_i_dir_ops = { + gfs_i_closedir, + gfs_i_readdir, + gfs_i_seekdir, + gfs_i_telldir, + gfs_i_dirname, +}; + +char * +gfs_i_opendir(const char *path, GFS_Dir *dirp) +{ + char *e, *canonic_path; + struct node *n; + struct gfs_dir_internal *dir; + + e = gfarm_canonical_path(gfarm_url_prefix_skip(path), &canonic_path); + if (e != NULL) + return (e); + + e = lookup_relative(root, canonic_path, NODE_FLAG_IS_DIR, + GFARM_INODE_LOOKUP, &n); + free(canonic_path); + if (e != NULL) + return (e); + + /* here, refresh directory cache */ + if (n->flags & NODE_FLAG_INVALID) { + gfs_i_uncachedir(); + e = gfs_refreshdir(); + if (e != NULL) + return (e); + /* NODE_FLAG_INVALID is reset in gfs_cachedir() */ + } + + GFARM_MALLOC(dir); + if (dir == NULL) + return (GFARM_ERR_NO_MEMORY); + dir->base.ops = &gfs_i_dir_ops; + dir->dir = n; + dir_iterator_init(&dir->iterator, &n->u.d.children); + dir->index = 0; + *dirp = &dir->base; + + ++opendir_count; + /* XXX if someone removed a path, while opening a directory... */ + return (NULL); +} Added: trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.h =================================================================== --- trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.h (rev 0) +++ trunk/gfarm/lib/libgfarm/gfarm/gfs_dir.h 2006-09-19 15:46:23 UTC (rev 3176) @@ -0,0 +1,22 @@ +/* + * This is a private header. + * + * Only gfs_dir.c and agent_wrap.c are allowed to include this header file. + * Every other modules shouldn't include this. + */ + +struct gfs_dir_ops { + char *(*close)(GFS_Dir); + char *(*read)(GFS_Dir, struct gfs_dirent **); + char *(*seek)(GFS_Dir, file_offset_t); + char *(*tell)(GFS_Dir, file_offset_t *); + char *(*dirname)(GFS_Dir); +}; + +/* + * This is an abstract base class. + * All instances of struct gfs_dir_* should have this as its first member. + */ +struct gfs_dir { + struct gfs_dir_ops *ops; +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |