Add case-insensitive lookup support to BlueSky core.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 8 Oct 2009 22:04:28 +0000 (15:04 -0700)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 8 Oct 2009 22:04:28 +0000 (15:04 -0700)
bluesky/bluesky.h
bluesky/dir.c
bluesky/inode.c
nfs3/nfs3.c

index 5524c44..f37a537 100644 (file)
@@ -149,6 +149,7 @@ typedef struct {
     /* Directory-specific fields */
     GSequence *dirents;         /* List of entries for READDIR */
     GHashTable *dirhash;        /* Hash table by name for LOOKUP */
+    GHashTable *dirhash_folded; /* As above, but case-folded */
     uint64_t parent_inum;       /* inode for ".."; 0 if the root directory */
 } BlueSkyInode;
 
@@ -159,6 +160,7 @@ typedef struct {
  * is used to provide a stable key for restarting a READDIR call. */
 typedef struct {
     gchar *name;
+    gchar *name_folded;         /* Name, folded for case-insensitive lookup */
     uint32_t cookie;
     uint64_t inum;
 } BlueSkyDirent;
@@ -194,6 +196,7 @@ void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode);
 void bluesky_dirent_destroy(gpointer dirent);
 uint64_t bluesky_directory_hash(gchar *name);
 uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name);
+uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name);
 gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name,
                                   uint64_t inum);
 void bluesky_directory_dump(BlueSkyInode *dir);
index 14eb6eb..82f3baa 100644 (file)
@@ -18,6 +18,7 @@ void bluesky_dirent_destroy(gpointer data)
 {
     BlueSkyDirent *dirent = (BlueSkyDirent *)data;
     g_free(dirent->name);
+    g_free(dirent->name_folded);
     g_free(dirent);
 }
 
@@ -50,6 +51,22 @@ uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name)
         return d->inum;
 }
 
+/* Case-insensitive lookup. */
+uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name)
+{
+    g_return_val_if_fail(inode->type == BLUESKY_DIRECTORY, 0);
+    g_return_val_if_fail(inode->dirhash_folded != NULL, 0);
+
+    name = bluesky_lowercase(name);
+    BlueSkyDirent *d = g_hash_table_lookup(inode->dirhash_folded, name);
+    g_free(name);
+
+    if (d == NULL)
+        return 0;
+    else
+        return d->inum;
+}
+
 /* Insert a new entry into a directory.  Should be called with the inode lock
  * already held. */
 gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum)
@@ -62,6 +79,7 @@ gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum)
 
     BlueSkyDirent *d = g_new(BlueSkyDirent, 1);
     d->name = g_strdup(name);
+    d->name_folded = bluesky_lowercase(name);
     d->inum = inum;
 
     GSequence *dirents = dir->dirents;
@@ -94,6 +112,7 @@ gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum)
     /* Add the directory entry to both indices. */
     g_sequence_insert_sorted(dirents, d, bluesky_dirent_compare, NULL);
     g_hash_table_insert(dir->dirhash, d->name, d);
+    g_hash_table_insert(dir->dirhash_folded, d->name_folded, d);
 
     bluesky_inode_update_ctime(dir, 1);
     bluesky_inode_flush(dir->fs, dir);
@@ -112,7 +131,8 @@ gboolean bluesky_directory_remove(BlueSkyInode *dir, gchar *name)
         return FALSE;
     }
 
-    g_hash_table_remove(dir->dirhash, name);
+    g_hash_table_remove(dir->dirhash, d->name);
+    g_hash_table_remove(dir->dirhash_folded, d->name_folded);
 
     GSequenceIter *i = g_sequence_search(dir->dirents, d,
                                          bluesky_dirent_compare, NULL);
index f3f3198..b62870d 100644 (file)
@@ -117,6 +117,7 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs,
     case BLUESKY_DIRECTORY:
         i->dirents = g_sequence_new(bluesky_dirent_destroy);
         i->dirhash = g_hash_table_new(g_str_hash, g_str_equal);
+        i->dirhash_folded = g_hash_table_new(g_str_hash, g_str_equal);
         break;
     case BLUESKY_BLOCK:
     case BLUESKY_CHARACTER:
index 593d660..cffad52 100644 (file)
@@ -572,7 +572,7 @@ nfsproc3_readdir_3_svc(readdir3args *argp, struct svc_req *rqstp)
     static entry3 dirents[MAX_READDIR_DIRENTS];
     int count = 0;
 
-    BlueSkyDirent start = {NULL, argp->cookie, 0};
+    BlueSkyDirent start = {NULL, NULL, argp->cookie, 0};
     GSequenceIter *i = g_sequence_search(dir->dirents, &start,
                                          bluesky_dirent_compare, NULL);