From 1a0cf7dc85967387fe2c458914409b888fc86235 Mon Sep 17 00:00:00 2001 From: Shehjar Tikoo Date: Thu, 28 May 2009 04:42:58 +0000 Subject: libglusterfsclient: Add dirent pre-fetching and caching The fop interface is such that we're able to extract more than 1 dirent in a readdir fop. This commit now enables libglusterfsclient to read multiple entries on a glusterfs_readdir call. Once these have been pre-fetched, they're cached till either glusterfs_closedir ,glusterfs_rewinddir or glusterfs_seekdir are called. The current implementation is beneficial for sequential directory reading and probably indifferent to applications that do a lot of seekdir and rewinddir after opening the directory. This is because both these calls result in dirent cache invalidation. Signed-off-by: Anand V. Avati --- .../src/libglusterfsclient-internals.h | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'libglusterfsclient/src/libglusterfsclient-internals.h') diff --git a/libglusterfsclient/src/libglusterfsclient-internals.h b/libglusterfsclient/src/libglusterfsclient-internals.h index 42ce5d4ca..fc79a539d 100755 --- a/libglusterfsclient/src/libglusterfsclient-internals.h +++ b/libglusterfsclient/src/libglusterfsclient-internals.h @@ -79,6 +79,34 @@ typedef struct { struct stat stbuf; } libglusterfs_client_inode_ctx_t; +/* Our dirent cache is very simplistic when it comes to directory + * reading workloads. It assumes that all directory traversal operations happen + * sequentially and that readdir callers dont go jumping around the directory + * using seekdir, rewinddir. Thats why you'll notice that seekdir, rewinddir + * API in libglusterfsclient only set the offset. The consequence is that when + * libgf_dcache_readdir finds that the offset presented to it, is not + * the same as the offset of the previous dirent returned by dcache (..stored + * in struct direntcache->prev_off..), it realises that a non-sequential + * directory read is in progress and returns 0 to signify that the cache is + * not valid. + * This could be made a bit more intelligent by using a data structure like + * a hash-table or a balanced binary tree that allows us to search for the + * existence of particular offsets in the cache without performing a list or + * array traversal. + * Dont use a simple binary search tree because + * there is no guarantee that offsets in a sequential reading of the directory + * will be just random integers. If for some reason they are sequential, a BST + * will end up becoming a list. + */ +struct direntcache { + gf_dirent_t entries; /* Head of list of cached dirents. */ + gf_dirent_t *next; /* Pointer to the next entry that + * should be sent by readdir */ + uint64_t prev_off; /* Offset where the next read will + * happen. + */ +}; + typedef struct { pthread_mutex_t lock; off_t offset; @@ -88,6 +116,8 @@ typedef struct { * handle. */ struct dirent dirp; + struct direntcache *dcache; + } libglusterfs_client_fd_ctx_t; typedef struct libglusterfs_client_async_local { -- cgit