blob: ae13d917b901e874e972b1b5dfb51f76e249ce54 [file] [log] [blame]
Zhenkai Zhu772c7072012-12-30 12:40:23 -08001#include "object-db-file.h"
2#include <assert.h>
3
4void
5writeBytes(ostream &out, const Bytes &bytes)
6{
7 int size = bytes.size();
8 writeInt(out, size);
9 out.write(head(bytes), size);
10}
11
12void
13readBytes(istream &in, Bytes &bytes)
14{
15 int size;
16 readInt(in, size);
17 bytes.reserve(size);
18 in.read(head(bytes), size);
19}
20
21ObjectDBFile::ObjectDBFile(const string &filename)
22 : m_size(0)
23 , m_cap(0)
24 , m_index(0)
25 , m_initialized(false)
26 , m_writable(false)
27 , m_filename(filename)
28{
29 m_istream.open(m_filename, ios_base::binary);
30 int magic;
31 ReadLock(m_lock);
32 readInt(m_istream, magic);
33 if (magic == MAGIC_NUM)
34 {
35 m_initialized = true;
36 readInt(m_istream, m_cap);
37 readInt(m_istream, m_size);
38 m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
39 }
40}
41
42ObjectDBFile::~ObjectDBFile()
43{
44 m_istream.close();
45 if (m_writable)
46 {
47 m_ostream.close();
48 }
49}
50
51void
52ObjectDBFile::init(int capacity)
53{
54 WriteLock(m_lock);
55 if (m_initialized)
56 {
57 throwException("Trying to init already initialized ObjectDBFile object" + m_filename);
58 }
59
60 if (!m_writable)
61 {
62 prepareWrite();
63 }
64
65 m_cap = capacity;
66 m_size = 0;
67
68 int magic = MAGIC_NUM;
69 writeInt(m_ostream, magic);
70 writeInt(m_ostream, m_cap);
71 writeInt(m_ostream, m_size);
72 m_initialized = true;
73
74 int count = size;
75 int offset = 0;
76 while (count-- > 0)
77 {
78 writeInt(m_ostream, offset);
79 }
80
81 // prepare read pos
82 m_istream.seekg(m_ostream.tellp(), ios::beg);
83
84 // DEBUG
85 assert(m_ostream.tellp() == ((3 + m_cap) * sizeof(int)));
86
87}
88
89// Append is not super efficient as it needs to seek and update the pos for the
90// Content object. However, in our app, it is the case the these objects are wrote
91// once and read multiple times, so it's not a big problem.
92void
93ObjectDBFile::append(const Bytes &co)
94{
95 WriteLock(m_lock);
96 checkInit("Trying to append to un-initialized ObjectDBFile: " + m_filename);
97
98 if (!m_writable)
99 {
100 prepareWrite();
101 }
102
103 if (m_size >= m_cap)
104 {
105 throwException("Exceed Maximum capacity: " + boost::lexical_cast<string>(m_cap));
106 }
107
108 // pos for this CO
109 int coPos = m_ostream.tellp();
110 // index field for this CO
111 int indexPos = (3 + m_size) * sizeof(int);
112
113 m_size++;
114
115 // Update size (is it necessary?) We'll do it for now anyway
116 m_ostream.seekp( 2 * sizeof(int), ios::beg);
117 writeInt(m_ostream, m_size);
118
119 // Write the pos for the CO
120 m_ostream.seekp(indexPos, ios::beg);
121 writeInt(m_ostream, coPos);
122
123 // write the content object
124 m_ostream.seekp(coPos, ios::beg);
125 writeBytes(m_ostream, co);
126
127 // By the end, the write pos is at the end of the file
128}
129
130Bytes
131ObjectDBFile::next()
132{
133}
134
135void
136ObjectDBFile::read(vector<Bytes> &vco, int n)
137{
138}
139
140int
141ObjectDBFile::size() const
142{
143 return m_size;
144}
145
146void
147ObjectDBFile::updateSzie()
148{
149 int pos = m_istream.tellg();
150 m_istream.seekg(2 * sizeof(int), ios::beg);
151 readInt(m_istream, m_size);
152 // recover the original pos
153 m_istream.seekg(pos, ios::beg);
154}
155
156int
157ObjectDBFile::fSize()
158{
159 ReadLock(m_lock);
160 updateSize();
161 return m_size;
162}
163
164int
165ObjectDBFile::index()
166{
167 ReadLock(m_lock);
168 return m_index;
169}
170
171bool
172ObjectDBFile::seek(int index)
173{
174 ReadLock(m_lock);
175 updateSize();
176 if (m_size <= index)
177 {
178 return false;
179 }
180 m_index = index;
181 m_istream.seekg( (3 + m_index) * sizeof(int), ios::beg);
182 int pos;
183 readInt(m_istream, pos);
184 m_istream.seekg(pos, ios::beg);
185 return true;
186}
187
188void
189rewind()
190{
191 ReadLock(m_lock);
192 m_index = 0;
193 // point to the start of the CO fields
194 m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
195}
196
197void
198ObjectDBFile::checkInit(const string &msg)
199{
200 if (!m_initialized)
201 {
202 throwException(msg);
203 }
204}
205
206void
207ObjectDBFile::prepareWrite()
208{
209 ios_base::openmode mode = ios_base::app | ios_base::binary;
210 // discard any content if the object is considered uninitialized
211 if (!m_initialized)
212 {
213 mode |= ios_base::trunc;
214 }
215
216 m_ostream.open(m_filename, mode);
217 m_writable = m_ostream.is_open();
218 if (!m_writable)
219 {
220 throwException("Unable to open file for write: " + m_filename);
221 }
222}