1 /* Blue Sky: File Systems in the Cloud
3 * Copyright (C) 2009 The Regents of the University of California
4 * Written by Michael Vrable <mvrable@cs.ucsd.edu>
14 /* Core filesystem. Different proxies, such as the NFSv3 one, interface to
15 * this, but the core actually tracks the data which is stored. So far we just
16 * implement an in-memory filesystem, but eventually this will be state which
17 * is persisted to the cloud. */
20 /* Hash a filename for a directory lookup. The string is hashed to a 64-bit
22 uint64_t bluesky_directory_hash(gchar *name)
24 GChecksum *csum = g_checksum_new(G_CHECKSUM_MD5);
25 g_checksum_update(csum, (guchar *)name, -1);
28 gsize hashsize = sizeof(hashbytes);
29 g_checksum_get_digest(csum, (guint8 *)hashbytes, &hashsize);
30 return GUINT64_FROM_LE(hashbytes[0]);
33 /* Return the current time, in microseconds since the epoch. */
34 int64_t bluesky_get_current_time()
37 g_get_current_time(&t);
38 return t.tv_sec * 1000000 + t.tv_usec;
41 /* Allocate a fresh inode number which has not been used before within a
43 uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs)
47 g_mutex_lock(fs->lock);
50 g_mutex_unlock(fs->lock);
55 BlueSkyInode *bluesky_new_inode(uint64_t inum)
57 BlueSkyInode *i = g_new0(BlueSkyInode, 1);
59 i->lock = g_mutex_new();
65 void bluesky_dirent_destroy(BlueSkyDirent *dirent)
71 gint bluesky_dirent_compare(gconstpointer a, gconstpointer b,
74 /* We can't simply subtract the hash values, since they are 64-bit and the
75 * result could overflow when converted to a gint. */
76 uint64_t hash1 = ((const BlueSkyDirent *)a)->hash;
77 uint64_t hash2 = ((const BlueSkyDirent *)b)->hash;
81 else if (hash1 > hash2)
87 /* Perform a lookup for a file name within a directory. Returns the inode
88 * number if found, or 0 if not (0 is never a valid inode number). Should be
89 * called with the inode lock already held. */
90 uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name)
92 g_return_val_if_fail(inode->type != BLUESKY_DIRECTORY, 0);
93 g_return_val_if_fail(inode->dirents != NULL, 0);
95 /* First, construct a hash of the file name. Search the directory for a
96 * match, then check to see if it does really match. */
97 uint64_t hash = bluesky_directory_hash(name);
99 BlueSkyDirent d = {name, hash, 0};
100 GSequenceIter *i = g_sequence_search(inode->dirents, &d,
101 bluesky_dirent_compare, NULL);
103 if (g_sequence_iter_is_end(i))
105 BlueSkyDirent *dirent = g_sequence_get(i);
106 if (dirent->hash != hash)
108 if (g_strcmp0(name, dirent->name) != 0)