blob: daa2193963a548b618f4a74cfd22d3fdb7de5c68 [file] [log] [blame]
Zhenkai Zhu772c7072012-12-30 12:40:23 -08001#ifndef OBJECT_DB_FILE_H
2#define OBJECT_DB_FILE_H
3
4#include "object-db.h"
5#include <stdio.h>
6#include <fstream>
7#include <ifstream>
8#include <ofstream>
9#include <sstream>
10#include <boost/thread/locks.hpp>
Zhenkai Zhu772c7072012-12-30 12:40:23 -080011#include <boost/lexical_cast.hpp>
Zhenkai Zhu427bed42012-12-30 23:57:48 -080012#include <boost/interprocess/sync/file_lock.hpp>
13#include <boost/interprocess/sync/sharable_lock.hpp>
14#include <boost/interprocess/sync/scoped_lock.hpp>
Zhenkai Zhu772c7072012-12-30 12:40:23 -080015
16#define _OVERRIDE
17#ifdef __GNUC__
18#if __GNUC_MAJOR >= 4 && __GNUC_MINOR__ >= 7
19 #undef _OVERRIDE
20 #define _OVERRIDE override
21#endif // __GNUC__ version
22#endif // __GNUC__
23
24using namespace std;
25
26// This is a file based ObjectDB implementation
27// The assumption is, the Content Objects will be stored sequentially
28
29// To provide random access, we will have a table of "address" for each
30// ContentObject at the beginning of the file.
31// This also requires another assumption, that is the number of COs must
32// be know a priori. This requirement is reasonable for our dropbox-like
33// System, as the file we publish is static file and we can easily know
34// the number of COs before we store them into ObjectDB.
35
36/* How file looks like:
37 * |MAGIC_NUM|capacity|size|pos for each CO ...|1st CO|2nd CO| ... |
38 */
39
40class ObjectDBFile
41{
42public:
Zhenkai Zhu427bed42012-12-30 23:57:48 -080043 typedef boost::interprocess::file_lock Filelock;
44 typedef boost::interprocess::scoped_lock<Filelock> WriteLock;
45 typedef boost::interprocess::sharable_lock<Filelock> ReadLock;
Zhenkai Zhu772c7072012-12-30 12:40:23 -080046
47 ObjectDBFile(const string &filename);
48 virtual ~ObjectDBFile(){}
49
50 // reserve the "address" table for n COs; must reserve before
51 // write anything (unless reserved quota has not be consumed yet)
52 void
53 init(int capacity);
54
55 bool
56 initialized() const { return m_initialized; }
57
58 // assume sequential
59 virtual void
60 append(const Bytes &co) _OVERRIDE;
61
62 // get next CO
63 virtual Bytes
64 next() _OVERRIDE;
65
66 // get n COs; if the remaining number of COs < n, return all;
67 virtual void
68 read(vector<Bytes> &vco, int n) _OVERRIDE;
69
70 // size in terms of number of COs
71 // This is the lazy form of size, i.e. it returns the size cached in this object
72 // but that may not necessarily equal to the actual size kept in file
73 // This is enough if the caller knows for sure that no other thread is changing the
74 // file or the caller does not care about the new size.
75 virtual int
76 size() const _OVERRIDE;
77
78 // this returns the actual size (also update the size cache in this object), but it is more costly, and requires file IO
79 int
80 fSize();
81
82 // the index of the CO to be read
83 int
84 index();
85
86 // set the pos to be the desired CO
87 // return true if success
88 bool
89 seek(int index);
90
91 // reset pos to be zero
92 void
93 rewind();
94
95protected:
Zhenkai Zhu772c7072012-12-30 12:40:23 -080096 // read or write lock should have been grabbed already before the call
97 void
98 checkInit(const string &msg);
99
100 // read lock should have been grabbed already before the call
101 void
102 updateSize();
103
104 #define MAGIC_NUM 0xAAAAAAAA
105
106protected:
107 string m_filename;
108 ifstream m_istream;
109 ofstream m_ostream;
Zhenkai Zhu427bed42012-12-30 23:57:48 -0800110 Filelock m_filelock;
Zhenkai Zhu772c7072012-12-30 12:40:23 -0800111 bool m_initialized;
112 // capacity in terms of number of COs
113 int m_cap;
114 int m_size;
115 // the index (or seq) of the CO to be read
116 int m_index;
117};
118
119void inline
120writeInt(ostream &out, const int &x)
121{
122 out.write((const char *)&x, sizeof(int));
123}
124
125void inline
126readInt(istream &in, int &x)
127{
128 in.read((char *)&x, sizeof(int));
129}
130
131// write size and then the actual bytes
132// operator << overloading is not used to avoid confusion
133void
134writeBytes(ostream &out, const Bytes &bytes);
135
136// read size and then the actual bytes
137void
138readBytes(istream &in, Bytes &bytes);
139
140#endif