Some test work with using Berkeley DB for a local disk cache.
[bluesky.git] / bluesky / localstore.c
1 /* Blue Sky: File Systems in the Cloud
2  *
3  * Copyright (C) 2009  The Regents of the University of California
4  * Written by Michael Vrable <mvrable@cs.ucsd.edu>
5  *
6  * TODO: Licensing
7  */
8
9 #include <stdint.h>
10 #include <glib.h>
11 #include <string.h>
12 #include <db.h>
13
14 #include "bluesky-private.h"
15
16 /* Management of the filesystem log/cache stored on local disk.  This is used
17  * as a buffer for queueing writes to the cloud, a cache for satisfying reads,
18  * and is also used to provide durability for the filesystem across crashes
19  * even if data has not been flushed to the cloud.
20  *
21  * We use Berkeley DB since it provides durability of writes after a crash. */
22
23 void bluesky_localstore_init()
24 {
25     int res;
26     DB_ENV *env;
27     DB *db;
28
29     res = db_env_create(&env, 0);
30
31     if (res != 0)
32     {
33         cerr << db_strerror(res) << endl;
34         throw std::runtime_error("db_env_create fail");
35     }
36
37     /* Set Cache Size To Total Memory */
38     if (true)
39     {
40         double use_fraction = 0.1;
41         uint64_t pages = sysconf(_SC_PHYS_PAGES);
42         uint64_t page_size = sysconf(_SC_PAGE_SIZE);
43
44         uint64_t bytes = pages * page_size * use_fraction / num_dbs;
45
46         uint32_t gbytes = bytes / (1024uLL * 1024uLL * 1024uLL);
47         uint32_t nbytes = bytes % (1024uLL * 1024uLL * 1024uLL);
48         uint32_t ncache = bytes / (1024uLL * 1024uLL * 1024uLL * 4uLL) + 1;
49
50         res = env->set_cachesize(env, gbytes, nbytes, ncache);
51
52         if (res != 0)
53         {
54             cerr << db_strerror(res) << endl;
55             throw std::runtime_error("set_cachesize");
56         }
57     }
58
59     if (log_in_memory)
60     {
61         res = env->set_flags(env, DB_LOG_IN_MEMORY, 1);
62
63         if (res != 0)
64         {
65             cerr << db_strerror(res) << endl;
66             throw std::runtime_error("BDB ENV DB_LOG_IN_MEMORY");
67         }
68
69     }
70
71     res = env->set_flags(env, DB_LOG_AUTO_REMOVE, 1);
72
73     if (res != 0)
74     {
75         cerr << db_strerror(res) << endl;
76         throw std::runtime_error("BDB ENV DB_LOG_AUTO_REMOVE");
77     }
78
79     res = env->open(env, _path.c_str(),
80                     DB_CREATE | DB_RECOVER | DB_INIT_LOCK | DB_INIT_LOG
81                      | DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD,
82                     0644);
83
84     if (res != 0)
85     {
86         cerr << db_strerror(res) << endl;
87         throw std::runtime_error("BDB ENV Open Fail");
88     }
89
90     string dbfilename = _path + "/test.db";
91
92     /* Flush */
93     if (flush)
94     {
95         res = env->dbremove(env, NULL, dbfilename.c_str(), "test", 0);
96
97         if (res != 0 && res != ENOENT)
98         {
99             cerr << db_strerror(res) << endl;
100             throw std::runtime_error("db remove failed");
101         }
102     }
103
104     res = db_create(&_db, env, 0);
105
106     if (res != 0)
107     {
108         cerr << db_strerror(res) << endl;
109         throw std::runtime_error("db_create fail");
110     }
111
112     uint32_t flags = DB_CREATE | DB_THREAD | DB_AUTO_COMMIT;
113
114     res = _db->open(_db,
115                    NULL, /* TXN */
116                    dbfilename.c_str(),
117                    "test",
118                    DB_BTREE,
119                    flags,
120                    0644);
121
122     if (res != 0)
123     {
124         cerr << db_strerror(res) << endl;
125         throw std::runtime_error("BDB Open Fail");
126     }
127
128 }