1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 #include "common.h"
4
5 #include "seafile-session.h"
6 #include "utils.h"
7 #include "seaf-utils.h"
8 #include "block-mgr.h"
9 #include "log.h"
10
11 #include <stdio.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <sys/types.h>
17 #include <dirent.h>
18 #include <glib/gstdio.h>
19
20 #include "block-backend.h"
21
22 #define SEAF_BLOCK_DIR "blocks"
23
24
25 extern BlockBackend *
26 block_backend_fs_new (const char *block_dir, const char *tmp_dir);
27
28
29 SeafBlockManager *
seaf_block_manager_new(struct _SeafileSession * seaf,const char * seaf_dir)30 seaf_block_manager_new (struct _SeafileSession *seaf,
31 const char *seaf_dir)
32 {
33 SeafBlockManager *mgr;
34
35 mgr = g_new0 (SeafBlockManager, 1);
36 mgr->seaf = seaf;
37
38 mgr->backend = block_backend_fs_new (seaf_dir, seaf->tmp_file_dir);
39 if (!mgr->backend) {
40 seaf_warning ("[Block mgr] Failed to load backend.\n");
41 goto onerror;
42 }
43
44 return mgr;
45
46 onerror:
47 g_free (mgr);
48
49 return NULL;
50 }
51
52 int
seaf_block_manager_init(SeafBlockManager * mgr)53 seaf_block_manager_init (SeafBlockManager *mgr)
54 {
55 return 0;
56 }
57
58
59 BlockHandle *
seaf_block_manager_open_block(SeafBlockManager * mgr,const char * store_id,int version,const char * block_id,int rw_type)60 seaf_block_manager_open_block (SeafBlockManager *mgr,
61 const char *store_id,
62 int version,
63 const char *block_id,
64 int rw_type)
65 {
66 if (!store_id || !is_uuid_valid(store_id) ||
67 !block_id || !is_object_id_valid(block_id))
68 return NULL;
69
70 return mgr->backend->open_block (mgr->backend,
71 store_id, version,
72 block_id, rw_type);
73 }
74
75 int
seaf_block_manager_read_block(SeafBlockManager * mgr,BlockHandle * handle,void * buf,int len)76 seaf_block_manager_read_block (SeafBlockManager *mgr,
77 BlockHandle *handle,
78 void *buf, int len)
79 {
80 return mgr->backend->read_block (mgr->backend, handle, buf, len);
81 }
82
83 int
seaf_block_manager_write_block(SeafBlockManager * mgr,BlockHandle * handle,const void * buf,int len)84 seaf_block_manager_write_block (SeafBlockManager *mgr,
85 BlockHandle *handle,
86 const void *buf, int len)
87 {
88 return mgr->backend->write_block (mgr->backend, handle, buf, len);
89 }
90
91 int
seaf_block_manager_close_block(SeafBlockManager * mgr,BlockHandle * handle)92 seaf_block_manager_close_block (SeafBlockManager *mgr,
93 BlockHandle *handle)
94 {
95 return mgr->backend->close_block (mgr->backend, handle);
96 }
97
98 void
seaf_block_manager_block_handle_free(SeafBlockManager * mgr,BlockHandle * handle)99 seaf_block_manager_block_handle_free (SeafBlockManager *mgr,
100 BlockHandle *handle)
101 {
102 return mgr->backend->block_handle_free (mgr->backend, handle);
103 }
104
105 int
seaf_block_manager_commit_block(SeafBlockManager * mgr,BlockHandle * handle)106 seaf_block_manager_commit_block (SeafBlockManager *mgr,
107 BlockHandle *handle)
108 {
109 return mgr->backend->commit_block (mgr->backend, handle);
110 }
111
seaf_block_manager_block_exists(SeafBlockManager * mgr,const char * store_id,int version,const char * block_id)112 gboolean seaf_block_manager_block_exists (SeafBlockManager *mgr,
113 const char *store_id,
114 int version,
115 const char *block_id)
116 {
117 if (!store_id || !is_uuid_valid(store_id) ||
118 !block_id || !is_object_id_valid(block_id))
119 return FALSE;
120
121 return mgr->backend->exists (mgr->backend, store_id, version, block_id);
122 }
123
124 int
seaf_block_manager_remove_block(SeafBlockManager * mgr,const char * store_id,int version,const char * block_id)125 seaf_block_manager_remove_block (SeafBlockManager *mgr,
126 const char *store_id,
127 int version,
128 const char *block_id)
129 {
130 if (!store_id || !is_uuid_valid(store_id) ||
131 !block_id || !is_object_id_valid(block_id))
132 return -1;
133
134 return mgr->backend->remove_block (mgr->backend, store_id, version, block_id);
135 }
136
137 BlockMetadata *
seaf_block_manager_stat_block(SeafBlockManager * mgr,const char * store_id,int version,const char * block_id)138 seaf_block_manager_stat_block (SeafBlockManager *mgr,
139 const char *store_id,
140 int version,
141 const char *block_id)
142 {
143 if (!store_id || !is_uuid_valid(store_id) ||
144 !block_id || !is_object_id_valid(block_id))
145 return NULL;
146
147 return mgr->backend->stat_block (mgr->backend, store_id, version, block_id);
148 }
149
150 BlockMetadata *
seaf_block_manager_stat_block_by_handle(SeafBlockManager * mgr,BlockHandle * handle)151 seaf_block_manager_stat_block_by_handle (SeafBlockManager *mgr,
152 BlockHandle *handle)
153 {
154 return mgr->backend->stat_block_by_handle (mgr->backend, handle);
155 }
156
157 int
seaf_block_manager_foreach_block(SeafBlockManager * mgr,const char * store_id,int version,SeafBlockFunc process,void * user_data)158 seaf_block_manager_foreach_block (SeafBlockManager *mgr,
159 const char *store_id,
160 int version,
161 SeafBlockFunc process,
162 void *user_data)
163 {
164 return mgr->backend->foreach_block (mgr->backend,
165 store_id, version,
166 process, user_data);
167 }
168
169 int
seaf_block_manager_copy_block(SeafBlockManager * mgr,const char * src_store_id,int src_version,const char * dst_store_id,int dst_version,const char * block_id)170 seaf_block_manager_copy_block (SeafBlockManager *mgr,
171 const char *src_store_id,
172 int src_version,
173 const char *dst_store_id,
174 int dst_version,
175 const char *block_id)
176 {
177 if (strcmp (block_id, EMPTY_SHA1) == 0)
178 return 0;
179 if (seaf_block_manager_block_exists (mgr, dst_store_id, dst_version, block_id)) {
180 return 0;
181 }
182
183 return mgr->backend->copy (mgr->backend,
184 src_store_id,
185 src_version,
186 dst_store_id,
187 dst_version,
188 block_id);
189 }
190
191 static gboolean
get_block_number(const char * store_id,int version,const char * block_id,void * data)192 get_block_number (const char *store_id,
193 int version,
194 const char *block_id,
195 void *data)
196 {
197 guint64 *n_blocks = data;
198
199 ++(*n_blocks);
200
201 return TRUE;
202 }
203
204 guint64
seaf_block_manager_get_block_number(SeafBlockManager * mgr,const char * store_id,int version)205 seaf_block_manager_get_block_number (SeafBlockManager *mgr,
206 const char *store_id,
207 int version)
208 {
209 guint64 n_blocks = 0;
210
211 seaf_block_manager_foreach_block (mgr, store_id, version,
212 get_block_number, &n_blocks);
213
214 return n_blocks;
215 }
216
217 gboolean
seaf_block_manager_verify_block(SeafBlockManager * mgr,const char * store_id,int version,const char * block_id,gboolean * io_error)218 seaf_block_manager_verify_block (SeafBlockManager *mgr,
219 const char *store_id,
220 int version,
221 const char *block_id,
222 gboolean *io_error)
223 {
224 BlockHandle *h;
225 char buf[10240];
226 int n;
227 SHA_CTX ctx;
228 guint8 sha1[20];
229 char check_id[41];
230
231 h = seaf_block_manager_open_block (mgr,
232 store_id, version,
233 block_id, BLOCK_READ);
234 if (!h) {
235 seaf_warning ("Failed to open block %s:%.8s.\n", store_id, block_id);
236 *io_error = TRUE;
237 return FALSE;
238 }
239
240 SHA1_Init (&ctx);
241 while (1) {
242 n = seaf_block_manager_read_block (mgr, h, buf, sizeof(buf));
243 if (n < 0) {
244 seaf_warning ("Failed to read block %s:%.8s.\n", store_id, block_id);
245 *io_error = TRUE;
246 return FALSE;
247 }
248 if (n == 0)
249 break;
250
251 SHA1_Update (&ctx, buf, n);
252 }
253
254 seaf_block_manager_close_block (mgr, h);
255 seaf_block_manager_block_handle_free (mgr, h);
256
257 SHA1_Final (sha1, &ctx);
258 rawdata_to_hex (sha1, check_id, 20);
259
260 if (strcmp (check_id, block_id) == 0)
261 return TRUE;
262 else
263 return FALSE;
264 }
265
266 int
seaf_block_manager_remove_store(SeafBlockManager * mgr,const char * store_id)267 seaf_block_manager_remove_store (SeafBlockManager *mgr,
268 const char *store_id)
269 {
270 return mgr->backend->remove_store (mgr->backend, store_id);
271 }
272