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