From 0bd83631d5ed24fe948a273e8a4d4bd8f128a86c Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 28 Nov 2006 12:43:54 -0500 Subject: [svn-r12990] Description: When using the latest version of the file format, move the "modification time" information into the object header prefix, which is more efficient. Also add "access time" and "change time" (for metadata) fields, all of which take about the same space as the previous modification time header message. Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2) --- src/H5O.c | 105 +++++++++++++++++++++++++++++++++----------------------- src/H5Ocache.c | 13 +++++++ src/H5Opkg.h | 20 +++++++++-- src/H5Opublic.h | 2 ++ src/H5private.h | 1 + src/H5timer.c | 36 +++++++++++++++++++ test/stab.c | 8 ++--- 7 files changed, 136 insertions(+), 49 deletions(-) diff --git a/src/H5O.c b/src/H5O.c index 0ef5b43..c74e34e 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -43,10 +43,6 @@ #include "H5Opkg.h" /* Object headers */ #include "H5SMprivate.h" /* Shared object header messages */ -#ifdef H5_HAVE_GETTIMEOFDAY -#include -#endif /* H5_HAVE_GETTIMEOFDAY */ - /****************/ /* Local Macros */ /****************/ @@ -849,6 +845,12 @@ H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size, H5O_loc_t *loc/*out*/, oh->nlink = 0; oh->skipped_mesg_size = 0; + /* Initialize version-specific fields */ + if(oh->version > H5O_VERSION_1) { + /* Initialize time fields */ + oh->atime = oh->mtime = oh->ctime = H5_now(); + } /* end if */ + /* Compute total size of initial object header */ /* (i.e. object header prefix and first chunk) */ oh_size = H5O_SIZEOF_HDR_OH(oh) + chunk_size; @@ -2253,7 +2255,6 @@ H5O_touch_oh(H5F_t *f, unsigned * oh_flags_ptr) { time_t now; /* Current time */ - unsigned idx; /* Index of modification time message to update */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_touch_oh) @@ -2261,46 +2262,50 @@ H5O_touch_oh(H5F_t *f, HDassert(oh); HDassert(oh_flags_ptr); - /* Look for existing message */ - for(idx = 0; idx < oh->nmesgs; idx++) - if(H5O_MSG_MTIME == oh->mesg[idx].type || H5O_MSG_MTIME_NEW == oh->mesg[idx].type) - break; + /* Get current time */ + now = H5_now(); -#ifdef H5_HAVE_GETTIMEOFDAY - { - struct timeval now_tv; + /* Check version, to determine how to store time information */ + if(oh->version == H5O_VERSION_1) { + unsigned idx; /* Index of modification time message to update */ - HDgettimeofday(&now_tv, NULL); - now = now_tv.tv_sec; - } -#else /* H5_HAVE_GETTIMEOFDAY */ - now = HDtime(NULL); -#endif /* H5_HAVE_GETTIMEOFDAY */ + /* Look for existing message */ + for(idx = 0; idx < oh->nmesgs; idx++) + if(H5O_MSG_MTIME == oh->mesg[idx].type || H5O_MSG_MTIME_NEW == oh->mesg[idx].type) + break; - /* Create a new message, if necessary */ - if(idx == oh->nmesgs) { - size_t size; /* New modification time message size */ + /* Create a new message, if necessary */ + if(idx == oh->nmesgs) { + size_t size; /* New modification time message size */ - /* If we have to create a new message, but we aren't 'forcing' it, get out now */ - if(!force) - HGOTO_DONE(SUCCEED); /*nothing to do*/ + /* If we would have to create a new message, but we aren't 'forcing' it, get out now */ + if(!force) + HGOTO_DONE(SUCCEED); /*nothing to do*/ - size = (H5O_MSG_MTIME_NEW->raw_size)(f, &now); - if((idx = H5O_alloc(f, dxpl_id, oh, H5O_MSG_MTIME_NEW, size, oh_flags_ptr)) == UFAIL) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message") - } /* end if */ + size = (H5O_MSG_MTIME_NEW->raw_size)(f, &now); + if((idx = H5O_alloc(f, dxpl_id, oh, H5O_MSG_MTIME_NEW, size, oh_flags_ptr)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message") + } /* end if */ - /* Allocate 'native' space, if necessary */ - if(NULL == oh->mesg[idx].native) { - if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message") - } /* end if */ + /* Allocate 'native' space, if necessary */ + if(NULL == oh->mesg[idx].native) { + if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message") + } /* end if */ - /* Update the message */ - *((time_t *)(oh->mesg[idx].native)) = now; + /* Update the message */ + *((time_t *)(oh->mesg[idx].native)) = now; - /* Mark the message & object header as dirty */ - oh->mesg[idx].dirty = TRUE; + /* Mark the message as dirty */ + oh->mesg[idx].dirty = TRUE; + } /* end if */ + else { + /* XXX: For now, update access time & change fields in the object header */ + /* (will need to add some code to update modification time appropriately) */ + oh->atime = oh->ctime = now; + } /* end else */ + + /* Mark the object header as dirty */ *oh_flags_ptr |= H5AC__DIRTIED_FLAG; done: @@ -3852,13 +3857,29 @@ H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id) oinfo->rc = oh->nlink; /* Get modification time for object */ - if(NULL == H5O_read_real(oloc->file, oh, H5O_MTIME_ID, 0, &oinfo->mtime, dxpl_id)) { - H5E_clear_stack(NULL); - if(NULL == H5O_read_real(oloc->file, oh, H5O_MTIME_NEW_ID, 0, &oinfo->mtime, dxpl_id)) { + if(oh->version > H5O_VERSION_1) { + oinfo->atime = oh->atime; + oinfo->mtime = oh->mtime; + oinfo->ctime = oh->ctime; + } /* end if */ + else { + /* No information for access & modification fields */ + /* (we stopped updating the "modification time" header message for + * raw data changes, so the "modification time" header message + * is closest to the 'change time', in POSIX terms - QAK) + */ + oinfo->atime = 0; + oinfo->mtime = 0; + + /* Might be information for modification time */ + if(NULL == H5O_read_real(oloc->file, oh, H5O_MTIME_ID, 0, &oinfo->mtime, dxpl_id)) { H5E_clear_stack(NULL); - oinfo->mtime = 0; + if(NULL == H5O_read_real(oloc->file, oh, H5O_MTIME_NEW_ID, 0, &oinfo->mtime, dxpl_id)) { + H5E_clear_stack(NULL); + oinfo->ctime = 0; + } /* end if */ } /* end if */ - } /* end if */ + } /* end else */ /* Set the version for the object header */ oinfo->hdr.version = oh->version; diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 8ebb6c2..defc14f 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -273,6 +273,14 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* Link count */ UINT32DECODE(p, oh->nlink); + /* Version-specific fields */ + if(oh->version > H5O_VERSION_1) { + /* Time fields */ + UINT32DECODE(p, oh->atime); + UINT32DECODE(p, oh->mtime); + UINT32DECODE(p, oh->ctime); + } /* end if */ + /* First chunk size */ UINT32DECODE(p, chunk_size); @@ -574,6 +582,11 @@ H5O_assert(oh); /* Link count */ UINT32ENCODE(p, oh->nlink); + /* Time fields */ + UINT32ENCODE(p, oh->atime); + UINT32ENCODE(p, oh->mtime); + UINT32ENCODE(p, oh->ctime); + /* Chunk size */ UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh))); } /* end if */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 679e021..18a0804 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -85,12 +85,15 @@ 4 + /*reference count */ \ 4) /*header data size */ \ : \ - (H5O_SIZEOF_MAGIC + /*magic number */ \ + (H5O_SIZEOF_MAGIC + /*magic number */ \ 1 + /*version number */ \ 2 + /*number of messages */ \ 4 + /*reference count */ \ + 4 + /*access time */ \ + 4 + /*modification time */ \ + 4 + /*change time */ \ 4 + /*header data size */ \ - H5O_SIZEOF_CHKSUM) /*checksum size */ \ + H5O_SIZEOF_CHKSUM) /*checksum size */ \ ) #define H5O_SIZEOF_HDR_OH(O) \ H5O_SIZEOF_HDR_VERS((O)->version) @@ -184,12 +187,23 @@ typedef struct H5O_chunk_t { struct H5O_t { H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ /* first field in structure */ + + /* General information */ unsigned version; /*version number */ unsigned nlink; /*link count */ - size_t skipped_mesg_size; /*size of skipped messages (for sanity checking) */ + + /* Time information */ + time_t atime; /*access time */ + time_t mtime; /*modification time */ + time_t ctime; /*change time */ + + /* Message management */ size_t nmesgs; /*number of messages */ size_t alloc_nmesgs; /*number of message slots */ H5O_mesg_t *mesg; /*array of messages */ + size_t skipped_mesg_size; /*size of skipped messages (for sanity checking) */ + + /* Chunk management */ size_t nchunks; /*number of chunks */ size_t alloc_nchunks; /*chunks allocated */ H5O_chunk_t *chunk; /*array of chunks */ diff --git a/src/H5Opublic.h b/src/H5Opublic.h index 4591120..b1fa767 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -86,7 +86,9 @@ typedef struct H5O_info_t { haddr_t addr; /* Object address in file */ H5O_type_t type; /* Basic object type (group, dataset, etc.) */ unsigned rc; /* Reference count of object */ + time_t atime; /* Access time */ time_t mtime; /* Modification time */ + time_t ctime; /* Change time */ hsize_t num_attrs; /* # of attributes attached to object */ struct { unsigned version; /* Version number of header format in file */ diff --git a/src/H5private.h b/src/H5private.h index 77fd02b..2d5cbdb 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -511,6 +511,7 @@ H5_DLL void H5_timer_begin (H5_timer_t *timer); H5_DLL void H5_timer_end (H5_timer_t *sum/*in,out*/, H5_timer_t *timer/*in,out*/); H5_DLL void H5_bandwidth(char *buf/*out*/, double nbytes, double nseconds); +H5_DLL time_t H5_now(void); /* Depth of object copy */ typedef enum { diff --git a/src/H5timer.c b/src/H5timer.c index 128c03f..cbbef3f 100644 --- a/src/H5timer.c +++ b/src/H5timer.c @@ -38,6 +38,10 @@ # include #endif +#ifdef H5_HAVE_GETTIMEOFDAY +#include +#endif /* H5_HAVE_GETTIMEOFDAY */ + /****************/ /* Local Macros */ @@ -246,3 +250,35 @@ H5_bandwidth(char *buf/*out*/, double nbytes, double nseconds) } } /* end H5_bandwidth() */ + +/*------------------------------------------------------------------------- + * Function: H5_now + * + * Purpose: Retrieves the current time, as seconds after the UNIX epoch. + * + * Return: # of seconds from the epoch (can't fail) + * + * Programmer: Quincey Koziol + * Tuesday, November 28, 2006 + * + *------------------------------------------------------------------------- + */ +time_t +H5_now(void) +{ + time_t now; /* Current time */ + +#ifdef H5_HAVE_GETTIMEOFDAY + { + struct timeval now_tv; + + HDgettimeofday(&now_tv, NULL); + now = now_tv.tv_sec; + } +#else /* H5_HAVE_GETTIMEOFDAY */ + now = HDtime(NULL); +#endif /* H5_HAVE_GETTIMEOFDAY */ + + return(now); +} /* end H5_now() */ + diff --git a/test/stab.c b/test/stab.c index e23a5f4..1f8528d 100644 --- a/test/stab.c +++ b/test/stab.c @@ -426,9 +426,9 @@ lifecycle(hid_t fapl) /* Check that the object header is only one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 205) TEST_ERROR + if(obj_stat.ohdr.size != 217) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 197) TEST_ERROR + if(obj_stat.ohdr.size != 209) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 0) TEST_ERROR if(obj_stat.ohdr.nmesgs != 6) TEST_ERROR @@ -452,9 +452,9 @@ lifecycle(hid_t fapl) /* Check that the object header is still one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 205) TEST_ERROR + if(obj_stat.ohdr.size != 217) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 197) TEST_ERROR + if(obj_stat.ohdr.size != 209) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 116) TEST_ERROR if(obj_stat.ohdr.nmesgs != 3) TEST_ERROR -- cgit v0.12