blob: d294b23217ba1d4fd2e14a54883e7046626b1ecc [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)
Zhenkai Zhu772c7072012-12-30 12:40:23 -080026 , m_filename(filename)
Zhenkai Zhu427bed42012-12-30 23:57:48 -080027 // This ensures file with filename exists (assuming having write permission)
28 // This is needed as file_lock only works with existing file
29 , m_ostream(m_filename, ios_base::binary | ios_base::app)
30 , m_istream(m_filename, ios_base::binary | ios_base::in)
31 , m_filelock(m_filename)
Zhenkai Zhu772c7072012-12-30 12:40:23 -080032{
Zhenkai Zhu772c7072012-12-30 12:40:23 -080033 int magic;
Zhenkai Zhu427bed42012-12-30 23:57:48 -080034 ReadLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -080035 readInt(m_istream, magic);
36 if (magic == MAGIC_NUM)
37 {
38 m_initialized = true;
39 readInt(m_istream, m_cap);
40 readInt(m_istream, m_size);
41 m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
42 }
43}
44
45ObjectDBFile::~ObjectDBFile()
46{
47 m_istream.close();
Zhenkai Zhu427bed42012-12-30 23:57:48 -080048 m_ostream.close();
Zhenkai Zhu772c7072012-12-30 12:40:23 -080049}
50
51void
52ObjectDBFile::init(int capacity)
53{
Zhenkai Zhu427bed42012-12-30 23:57:48 -080054 WriteLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -080055 if (m_initialized)
56 {
57 throwException("Trying to init already initialized ObjectDBFile object" + m_filename);
58 }
59
Zhenkai Zhu772c7072012-12-30 12:40:23 -080060 m_cap = capacity;
61 m_size = 0;
62
63 int magic = MAGIC_NUM;
64 writeInt(m_ostream, magic);
65 writeInt(m_ostream, m_cap);
66 writeInt(m_ostream, m_size);
67 m_initialized = true;
68
69 int count = size;
70 int offset = 0;
71 while (count-- > 0)
72 {
73 writeInt(m_ostream, offset);
74 }
75
76 // prepare read pos
77 m_istream.seekg(m_ostream.tellp(), ios::beg);
78
79 // DEBUG
80 assert(m_ostream.tellp() == ((3 + m_cap) * sizeof(int)));
81
82}
83
84// Append is not super efficient as it needs to seek and update the pos for the
85// Content object. However, in our app, it is the case the these objects are wrote
86// once and read multiple times, so it's not a big problem.
87void
88ObjectDBFile::append(const Bytes &co)
89{
Zhenkai Zhu427bed42012-12-30 23:57:48 -080090 WriteLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -080091 checkInit("Trying to append to un-initialized ObjectDBFile: " + m_filename);
92
Zhenkai Zhu772c7072012-12-30 12:40:23 -080093 if (m_size >= m_cap)
94 {
95 throwException("Exceed Maximum capacity: " + boost::lexical_cast<string>(m_cap));
96 }
97
98 // pos for this CO
99 int coPos = m_ostream.tellp();
100 // index field for this CO
101 int indexPos = (3 + m_size) * sizeof(int);
102
103 m_size++;
104
105 // Update size (is it necessary?) We'll do it for now anyway
106 m_ostream.seekp( 2 * sizeof(int), ios::beg);
107 writeInt(m_ostream, m_size);
108
109 // Write the pos for the CO
110 m_ostream.seekp(indexPos, ios::beg);
111 writeInt(m_ostream, coPos);
112
113 // write the content object
114 m_ostream.seekp(coPos, ios::beg);
115 writeBytes(m_ostream, co);
116
117 // By the end, the write pos is at the end of the file
118}
119
120Bytes
121ObjectDBFile::next()
122{
123}
124
125void
126ObjectDBFile::read(vector<Bytes> &vco, int n)
127{
128}
129
130int
131ObjectDBFile::size() const
132{
133 return m_size;
134}
135
136void
137ObjectDBFile::updateSzie()
138{
139 int pos = m_istream.tellg();
140 m_istream.seekg(2 * sizeof(int), ios::beg);
141 readInt(m_istream, m_size);
142 // recover the original pos
143 m_istream.seekg(pos, ios::beg);
144}
145
146int
147ObjectDBFile::fSize()
148{
Zhenkai Zhu427bed42012-12-30 23:57:48 -0800149 ReadLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -0800150 updateSize();
151 return m_size;
152}
153
154int
155ObjectDBFile::index()
156{
Zhenkai Zhu427bed42012-12-30 23:57:48 -0800157 ReadLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -0800158 return m_index;
159}
160
161bool
162ObjectDBFile::seek(int index)
163{
Zhenkai Zhu427bed42012-12-30 23:57:48 -0800164 ReadLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -0800165 updateSize();
166 if (m_size <= index)
167 {
168 return false;
169 }
170 m_index = index;
171 m_istream.seekg( (3 + m_index) * sizeof(int), ios::beg);
172 int pos;
173 readInt(m_istream, pos);
174 m_istream.seekg(pos, ios::beg);
175 return true;
176}
177
178void
179rewind()
180{
Zhenkai Zhu427bed42012-12-30 23:57:48 -0800181 ReadLock(m_filelock);
Zhenkai Zhu772c7072012-12-30 12:40:23 -0800182 m_index = 0;
183 // point to the start of the CO fields
184 m_istream.seekg( (3 + m_cap) * sizeof(int), ios::beg);
185}
186
187void
188ObjectDBFile::checkInit(const string &msg)
189{
190 if (!m_initialized)
191 {
192 throwException(msg);
193 }
194}