-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextent_server.cc
211 lines (162 loc) · 6.22 KB
/
extent_server.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// the extent server implementation
#include "extent_server.h"
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
extent_server::extent_server()
{
int r;
if (create(0x00000001, r) != extent_protocol::OK)
{
// crash on failure
printf("ERROR: Can't create root directory on the extent server. Peacefully crashing...\n");
exit(0);
}
}
int extent_server::create(extent_protocol::extentid_t id, int &)
{
printf("extent_server::create(id=%lld)\n", id);
if (m_dataBlocks.find(id) != m_dataBlocks.end())
// TODO: what should we do if the extent exists already?
return extent_protocol::IOERR;
// create structure for the new extent
extent_t e;
e.data = std::string();
e.attrs.mtime = e.attrs.atime = e.attrs.ctime = time(NULL);
e.attrs.size = 0;
// save structure to the extent map
m_dataBlocks[id] = e;
return extent_protocol::OK;
}
int extent_server::update(extent_protocol::extentid_t id, std::string buf, unsigned offset, unsigned size, int & bytesWritten)
{
printf("extent_server::update(id=%lld, buf=%s, offset=%d, size=%d)\n", id, buf.c_str(), offset, size);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// resize string
if (offset + size > m_dataBlocks[id].data.size())
{
reallocateString(m_dataBlocks[id].data, offset + size);
m_dataBlocks[id].attrs.size = offset + size;
}
// update data in the extent
m_dataBlocks[id].data.replace(offset, size, buf);
// setting modification time
m_dataBlocks[id].attrs.mtime = time(NULL);
// return number of actual bytes written
bytesWritten = size;
return extent_protocol::OK;
}
int extent_server::updateAll(extent_protocol::extentid_t id, std::string buf, int &)
{
printf("extent_server::updateAll(id=%lld, buf=%s)\n", id, buf.c_str());
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// update data in the extent
m_dataBlocks[id].data = buf;
m_dataBlocks[id].attrs.size = buf.size();
// setting modification times
m_dataBlocks[id].attrs.mtime = time(NULL);
m_dataBlocks[id].attrs.ctime = time(NULL);
return extent_protocol::OK;
}
int extent_server::retrieve(extent_protocol::extentid_t id, unsigned offset, unsigned size, std::string &buf)
{
printf("extent_server::retrieve(id=%lld, offset=%d, size=%d)\n", id, offset, size);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// check if offset is correctly specified
if (offset > m_dataBlocks[id].attrs.size)
// TODO: should we change size instead?
return extent_protocol::IOERR;
// check if size is correctly specified
if (offset + size > m_dataBlocks[id].attrs.size)
// TODO: should we still return string of specified size
// filled with '\0' at positions beyond the file?
size = m_dataBlocks[id].attrs.size - offset;
// get data from the extent map
buf = m_dataBlocks[id].data.substr(offset, size);
// update access time (simulate relatime behaviour since this is default for
// Linux since kernel version 2.6.30)
time_t now = time(NULL);
if (m_dataBlocks[id].attrs.atime < m_dataBlocks[id].attrs.ctime ||
m_dataBlocks[id].attrs.atime < m_dataBlocks[id].attrs.mtime ||
m_dataBlocks[id].attrs.atime < now - 24*60*60)
m_dataBlocks[id].attrs.atime = now;
return extent_protocol::OK;
}
int extent_server::retrieveAll(extent_protocol::extentid_t id, std::string &buf)
{
printf("extent_server::retrieveAll(id=%lld)\n", id);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
return retrieve(id, 0, m_dataBlocks[id].attrs.size, buf);
}
int extent_server::getattr(extent_protocol::extentid_t id, extent_protocol::attr &a)
{
printf("extent_server::getattr(id=%lld)\n", id);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// get attributes for the extent
a = m_dataBlocks[id].attrs;
printf(" --> a.size=%d\n", a.size);
return extent_protocol::OK;
}
int extent_server::setattr(extent_protocol::extentid_t id, extent_protocol::attr a, int &)
{
printf("extent_server::setattr(id=%lld,a.size=%d)\n", id, a.size);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// reallocate data buffer if size have changed
if (a.size != m_dataBlocks[id].attrs.size)
reallocateString(m_dataBlocks[id].data, a.size);
// get attributes for the extent
m_dataBlocks[id].attrs = a;
// setting modification time
m_dataBlocks[id].attrs.mtime = time(NULL);
return extent_protocol::OK;
}
int extent_server::remove(extent_protocol::extentid_t id, int &)
{
printf("extent_server::remove(id=%lld)\n", id);
// check if extent exists
if (m_dataBlocks.find(id) == m_dataBlocks.end())
return extent_protocol::NOENT;
// remove it from the extent map
m_dataBlocks.erase(id);
return extent_protocol::OK;
}
void extent_server::reallocateString(std::string &str, unsigned newSize)
{
printf("exten_server::reallocateString, oldSize=%u, newSize=%u", str.size(), newSize);
if (str.size() > newSize)
str = std::string(str, 0, newSize);
else if (str.size() < newSize)
{
std::string newStr = std::string(newSize, '\0');
newStr.replace(0, str.size(), str);
str = newStr;
}
printf(", updatedSize=%u\n", str.size());
}
int extent_server::put(extent_protocol::extentid_t id, std::string buf, extent_protocol::attr a, int &)
{
printf("extent_server::put(id=%lld, buf=%s)\n", id, buf.c_str());
// update data in the extent
m_dataBlocks[id].data = buf;
m_dataBlocks[id].attrs.size = a.size;
// setting modification times
m_dataBlocks[id].attrs.mtime = a.mtime;
m_dataBlocks[id].attrs.ctime = a.ctime;
m_dataBlocks[id].attrs.atime = a.atime;
return extent_protocol::OK;
}