2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #define _XOPEN_SOURCE 600
18 #include <sys/types.h>
20 #include <sys/socket.h>
34 #include <eblob/blob.h>
36 #include "elliptics/packet.h"
37 #include "elliptics/interface.h"
43 #define __unused __attribute__ ((unused))
46 struct eblob_backend_config
{
47 struct eblob_config data
;
48 struct eblob_backend
*eblob
;
51 #if EBLOB_ID_SIZE != DNET_ID_SIZE
52 #error "EBLOB_ID_SIZE must be equal to DNET_ID_SIZE"
55 static int blob_write(struct eblob_backend_config
*c
, void *state __unused
, struct dnet_cmd
*cmd __unused
, void *data
)
58 struct dnet_io_attr
*io
= data
;
59 struct eblob_write_control wc
;
61 uint64_t flags
= BLOB_DISK_CTL_WRITE_RETURN
;
63 dnet_backend_log(DNET_LOG_NOTICE
, "%s: EBLOB: blob-write: WRITE: start: offset: %llu, size: %llu, ioflags: %x, type: %d.\n",
64 dnet_dump_id_str(io
->id
), (unsigned long long)io
->offset
, (unsigned long long)io
->size
, io
->flags
, io
->type
);
66 memset(&wc
, 0, sizeof(struct eblob_write_control
));
69 dnet_convert_io_attr(io
);
71 data
+= sizeof(struct dnet_io_attr
);
73 if (io
->flags
& DNET_IO_FLAGS_COMPRESS
)
74 flags
|= BLOB_DISK_CTL_COMPRESS
;
76 if (io
->flags
& DNET_IO_FLAGS_APPEND
)
77 flags
|= BLOB_DISK_CTL_APPEND
;
79 if (io
->flags
& DNET_IO_FLAGS_OVERWRITE
)
80 flags
|= BLOB_DISK_CTL_OVERWRITE
;
82 if (io
->flags
& DNET_IO_FLAGS_NOCSUM
)
83 flags
|= BLOB_DISK_CTL_NOCSUM
;
85 memcpy(key
.id
, io
->id
, EBLOB_ID_SIZE
);
87 if ((io
->type
== EBLOB_TYPE_META
) && !(io
->flags
& DNET_IO_FLAGS_META
)) {
88 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: meta-check: COLUMN %d IS RESERVED FOR METADATA\n",
89 dnet_dump_id_str(io
->id
), io
->type
);
94 if (io
->flags
& DNET_IO_FLAGS_PREPARE
) {
100 err
= eblob_write_prepare(c
->eblob
, &key
, &wc
);
102 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: eblob_write_prepare: size: %llu: type: %d: %s %d\n",
103 dnet_dump_id_str(io
->id
), (unsigned long long)io
->num
, io
->type
, strerror(-err
), err
);
107 dnet_backend_log(DNET_LOG_NOTICE
, "%s: EBLOB: blob-write: eblob_write_prepare: size: %llu: type: %d: Ok\n",
108 dnet_dump_id_str(io
->id
), (unsigned long long)io
->num
, io
->type
);
112 if (io
->flags
& DNET_IO_FLAGS_PLAIN_WRITE
) {
113 err
= eblob_plain_write(c
->eblob
, &key
, data
, io
->offset
, io
->size
, io
->type
);
115 err
= eblob_write(c
->eblob
, &key
, data
, io
->offset
, io
->size
, flags
, io
->type
);
117 if (io
->size
>= sizeof(struct eblob_write_control
)) {
118 memcpy(&wc
, data
, sizeof(struct eblob_write_control
));
124 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: WRITE: %d: %s\n",
125 dnet_dump_id_str(io
->id
), err
, strerror(-err
));
129 dnet_backend_log(DNET_LOG_NOTICE
, "%s: EBLOB: blob-write: WRITE: Ok: offset: %llu, size: %llu, type: %d.\n",
130 dnet_dump_id_str(io
->id
), (unsigned long long)io
->offset
, (unsigned long long)io
->size
, io
->type
);
133 if (io
->flags
& DNET_IO_FLAGS_COMMIT
) {
139 err
= eblob_write_commit(c
->eblob
, &key
, NULL
, 0, &wc
);
141 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: eblob_write_commit: size: %llu: type: %d: %s %d\n",
142 dnet_dump_id_str(io
->id
), (unsigned long long)io
->num
, io
->type
, strerror(-err
), err
);
146 dnet_backend_log(DNET_LOG_NOTICE
, "%s: EBLOB: blob-write: eblob_write_commit: size: %llu: type: %d: Ok\n",
147 dnet_dump_id_str(io
->id
), (unsigned long long)io
->num
, io
->type
);
150 if (!err
&& wc
.data_fd
== -1) {
151 err
= eblob_read_nocsum(c
->eblob
, &key
, &wc
.data_fd
, &wc
.offset
, &wc
.size
, io
->type
);
153 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: eblob_read: "
154 "size: %llu: type: %d: %s %d\n",
155 dnet_dump_id_str(io
->id
), (unsigned long long)io
->num
, io
->type
, strerror(-err
), err
);
159 /* data is compressed, but we only care about header */
165 err
= dnet_send_file_info(state
, cmd
, wc
.data_fd
, wc
.offset
, wc
.size
);
167 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-write: dnet_send_file_info: "
168 "fd: %d, offset: %llu, size: %llu: type: %d: %s %d\n",
169 dnet_dump_id_str(io
->id
), wc
.data_fd
,(unsigned long long)wc
.offset
,
170 (unsigned long long)wc
.size
, io
->type
, strerror(-err
), err
);
178 static int blob_read(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
, void *data
)
180 struct dnet_io_attr
*io
= data
;
181 struct eblob_backend
*b
= c
->eblob
;
182 uint64_t offset
, size
, orig_offset
, orig_size
;
183 struct eblob_key key
;
184 char *read_data
= NULL
;
187 dnet_convert_io_attr(io
);
189 memcpy(key
.id
, io
->id
, EBLOB_ID_SIZE
);
191 if (io
->flags
& DNET_IO_FLAGS_NOCSUM
) {
192 err
= eblob_read_nocsum(b
, &key
, &fd
, &orig_offset
, &orig_size
, io
->type
);
194 err
= eblob_read(b
, &key
, &fd
, &orig_offset
, &orig_size
, io
->type
);
198 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-read-fd: READ: %d: %s\n",
199 dnet_dump_id_str(io
->id
), err
, strerror(-err
));
201 } else if (err
> 0) {
202 /* data is compressed */
205 err
= eblob_read_data(b
, &key
, io
->offset
, &read_data
, &size
, io
->type
);
207 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-read-data: READ: %d: %s\n",
208 dnet_dump_id_str(io
->id
), err
, strerror(-err
));
212 offset
= 0; /* to shut up compiler - offset is not used when there is data */
215 if (io
->offset
>= orig_size
) {
220 offset
= orig_offset
+ io
->offset
;
221 size
= orig_size
- io
->offset
;
223 if (io
->size
&& size
> io
->size
)
228 err
= dnet_send_read_data(state
, cmd
, io
, read_data
, fd
, offset
, 0);
230 /* free compressed data */
236 struct eblob_read_range_priv
{
238 struct dnet_cmd
*cmd
;
239 struct eblob_range_request
*keys
;
245 static int blob_cmp_range_request(const void *req1
, const void *req2
)
247 return memcmp(((struct eblob_range_request
*)(req1
))->record_key
, ((struct eblob_range_request
*)(req2
))->record_key
, EBLOB_ID_SIZE
);
250 static int blob_read_range_callback(struct eblob_range_request
*req
)
252 struct eblob_read_range_priv
*p
= req
->priv
;
253 struct dnet_io_attr io
;
256 if (req
->requested_offset
> req
->record_size
) {
261 if (!(p
->flags
& DNET_IO_FLAGS_NODATA
)) {
263 io
.size
= req
->record_size
- req
->requested_offset
;
264 io
.offset
= req
->requested_offset
;
265 io
.type
= req
->requested_type
;
267 memcpy(io
.id
, req
->record_key
, DNET_ID_SIZE
);
268 memcpy(io
.parent
, req
->end
, DNET_ID_SIZE
);
270 err
= dnet_send_read_data(p
->state
, p
->cmd
, &io
, NULL
, req
->record_fd
,
271 req
->record_offset
+ req
->requested_offset
, 0);
283 static int blob_del_range_callback(struct eblob_backend_config
*c
, struct dnet_io_attr
*io
, struct eblob_range_request
*req
)
285 //struct eblob_read_range_priv *p = req->priv;
286 struct eblob_key key
;
289 dnet_backend_log(DNET_LOG_DEBUG
, "%s: EBLOB: blob-read-range: DEL\n",dnet_dump_id_str(req
->record_key
));
290 memcpy(key
.id
, req
->record_key
, EBLOB_ID_SIZE
);
291 err
= eblob_remove(c
->eblob
, &key
, io
->type
);
293 dnet_backend_log(DNET_LOG_DEBUG
, "%s: EBLOB: blob-read-range: DEL: err: %d\n",dnet_dump_id_str(req
->record_key
), err
);
299 static int blob_range_callback(struct eblob_range_request
*req
)
301 struct eblob_read_range_priv
*p
= req
->priv
;
303 char start_id
[len
*2+1], end_id
[len
*2+1], cur_id
[2*len
+1];
306 dnet_dump_id_len_raw(req
->start
, len
, start_id
);
307 dnet_dump_id_len_raw(req
->end
, len
, end_id
);
308 dnet_dump_id_len_raw(req
->record_key
, len
, cur_id
);
310 dnet_backend_log(DNET_LOG_NOTICE
, "%s: EBLOB: blob-range: limit: %llu [%llu, %llu]: "
311 "start: %s, end: %s: io record/requested: offset: %llu/%llu, size: %llu/%llu, type: %d\n",
313 (unsigned long long)req
->current_pos
,
314 (unsigned long long)req
->requested_limit_start
, (unsigned long long)req
->requested_limit_num
,
316 (unsigned long long)req
->record_offset
, (unsigned long long)req
->requested_offset
,
317 (unsigned long long)req
->record_size
, (unsigned long long)req
->requested_size
,
318 req
->requested_type
);
320 if (req
->requested_offset
> req
->record_size
) {
326 p
->keys
= (struct eblob_range_request
*)malloc(sizeof(struct eblob_range_request
) * 1000);
329 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-del-range: can't allocate memory\n", cur_id
);
335 if (p
->keys_size
== p
->keys_cnt
) {
336 p
->keys
= (struct eblob_range_request
*)realloc(p
->keys
, sizeof(struct eblob_range_request
) * p
->keys_size
* 2);
339 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-del-range: can't re-allocate memory, new size: %llu\n",
340 cur_id
, (unsigned long long)(p
->keys_size
* 2));
346 memcpy(&p
->keys
[p
->keys_cnt
], req
, sizeof(struct eblob_range_request
));
347 dnet_dump_id_len_raw(p
->keys
[p
->keys_cnt
].record_key
, len
, cur_id
);
348 dnet_backend_log(DNET_LOG_DEBUG
, "%s: count: %llu\n", cur_id
, (unsigned long long)(p
->keys_cnt
));
357 static int blob_read_range(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
, void *data
)
359 struct eblob_read_range_priv p
;
360 struct dnet_io_attr
*io
= data
;
361 struct eblob_backend
*b
= c
->eblob
;
362 struct eblob_range_request req
;
363 uint64_t i
, start_from
= 0;
366 memset(&p
, 0, sizeof(p
));
375 dnet_convert_io_attr(io
);
377 memset(&req
, 0, sizeof(req
));
379 memcpy(req
.start
, io
->id
, EBLOB_ID_SIZE
);
380 memcpy(req
.end
, io
->parent
, EBLOB_ID_SIZE
);
381 req
.requested_offset
= io
->offset
;
382 req
.requested_size
= io
->size
;
383 req
.requested_limit_start
= 0;
384 req
.requested_limit_num
= ~0ULL;
385 req
.requested_type
= io
->type
;
387 req
.callback
= blob_range_callback
;
391 err
= eblob_read_range(&req
);
393 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-read-range: %d: %s\n",
394 dnet_dump_id_str(io
->id
), err
, strerror(-err
));
398 if ((cmd
->cmd
== DNET_CMD_READ_RANGE
) && (cmd
->flags
& DNET_ATTR_SORT
)) {
399 dnet_backend_log(DNET_LOG_DEBUG
, "Sorting keys before sending\n");
400 qsort(p
.keys
, p
.keys_cnt
, sizeof(struct eblob_range_request
), &blob_cmp_range_request
);
403 if (cmd
->cmd
== DNET_CMD_READ_RANGE
) {
404 start_from
= io
->start
;
407 for (i
= start_from
; i
< p
.keys_cnt
; ++i
) {
409 case DNET_CMD_READ_RANGE
:
410 if ((io
->num
> 0) && (i
>= (io
->num
+ start_from
)))
412 dnet_backend_log(DNET_LOG_DEBUG
, "%s: EBLOB: blob-read-range: READ\n",dnet_dump_id_str(p
.keys
[i
].record_key
));
413 err
= blob_read_range_callback(&p
.keys
[i
]);
415 case DNET_CMD_DEL_RANGE
:
416 dnet_backend_log(DNET_LOG_DEBUG
, "%s: EBLOB: blob-read-range: DEL\n",dnet_dump_id_str(p
.keys
[i
].record_key
));
417 err
= blob_del_range_callback(c
, io
, &p
.keys
[i
]);
422 dnet_backend_log(DNET_LOG_DEBUG
, "%s: EBLOB: blob-read-range: err: %d\n",dnet_dump_id_str(p
.keys
[i
].record_key
), err
);
427 if (req
.current_pos
) {
428 struct dnet_io_attr r
;
430 memcpy(&r
, io
, sizeof(struct dnet_io_attr
));
431 r
.num
= req
.current_pos
- start_from
;
432 r
.offset
= r
.size
= 0;
434 err
= dnet_send_read_data(state
, cmd
, &r
, NULL
, -1, 0, 0);
444 static int blob_del(struct eblob_backend_config
*c
, struct dnet_cmd
*cmd
)
446 struct eblob_key key
;
449 memcpy(key
.id
, cmd
->id
.id
, EBLOB_ID_SIZE
);
451 if (cmd
->id
.type
!= -1) {
452 err
= eblob_remove(c
->eblob
, &key
, cmd
->id
.type
);
454 err
= eblob_remove_all(c
->eblob
, &key
);
458 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-del: REMOVE: type: %d: %d: %s\n",
459 dnet_dump_id_str(cmd
->id
.id
), cmd
->id
.type
, err
, strerror(-err
));
465 static int eblob_send(void *state
, void *priv
, struct dnet_id
*id
)
467 struct dnet_node
*n
= dnet_get_node_from_state(state
);
468 struct eblob_backend_config
*c
= priv
;
469 struct eblob_backend
*b
= c
->eblob
;
470 uint64_t offset
, size
;
471 struct eblob_key key
;
472 int *types
, types_num
, i
;
475 memcpy(key
.id
, id
->id
, EBLOB_ID_SIZE
);
477 if (id
->type
== -1) {
478 types_num
= eblob_get_types(b
, &types
);
489 for (i
= 0; i
< types_num
; ++i
) {
490 if (types
[i
] == EBLOB_TYPE_META
)
493 dnet_backend_log(DNET_LOG_DEBUG
, "trying to send type %d\n", types
[i
]);
494 ret
= eblob_read(b
, &key
, &fd
, &offset
, &size
, types
[i
]);
496 struct dnet_io_control ctl
;
499 memset(&ctl
, 0, sizeof(ctl
));
502 ctl
.local_offset
= offset
;
504 memcpy(&ctl
.id
, id
, sizeof(struct dnet_id
));
505 ctl
.id
.type
= types
[i
];
509 ctl
.io
.type
= types
[i
];
512 err
= dnet_write_data_wait(n
, &ctl
, &result
);
528 static int blob_file_info(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
)
530 struct eblob_backend
*b
= c
->eblob
;
531 struct eblob_key key
;
532 uint64_t offset
, size
;
535 memcpy(key
.id
, cmd
->id
.id
, EBLOB_ID_SIZE
);
536 err
= eblob_read(b
, &key
, &fd
, &offset
, &size
, cmd
->id
.type
);
538 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-file-info: info-read: %d: %s.\n",
539 dnet_dump_id(&cmd
->id
), err
, strerror(-err
));
545 dnet_backend_log(DNET_LOG_INFO
, "%s: EBLOB: blob-file-info: info-read: ZERO-SIZE-FILE.\n",
546 dnet_dump_id(&cmd
->id
));
550 err
= dnet_send_file_info(state
, cmd
, fd
, offset
, size
);
556 static int blob_bulk_read(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
, void *data
)
559 struct dnet_io_attr
*io
= data
;
560 struct dnet_io_attr
*ios
= io
+1;
564 dnet_convert_io_attr(io
);
565 count
= io
->size
/ sizeof(struct dnet_io_attr
);
567 for (i
= 0; i
< count
; i
++) {
568 ret
= blob_read(c
, state
, cmd
, &ios
[i
]);
578 static int blob_start_defrag(struct eblob_backend_config
*c
)
580 return eblob_start_defrag(c
->eblob
);
583 static int eblob_backend_command_handler(void *state
, void *priv
, struct dnet_cmd
*cmd
, void *data
)
586 struct eblob_backend_config
*c
= priv
;
590 case DNET_CMD_LOOKUP
:
591 err
= blob_file_info(c
, state
, cmd
);
594 err
= blob_write(c
, state
, cmd
, data
);
597 err
= blob_read(c
, state
, cmd
, data
);
599 case DNET_CMD_READ_RANGE
:
600 case DNET_CMD_DEL_RANGE
:
601 err
= blob_read_range(c
, state
, cmd
, data
);
604 path
= strdup(c
->data
.file
);
610 p
= strrchr(path
, '/');
618 err
= backend_stat(state
, path
, cmd
);
622 err
= blob_del(c
, cmd
);
624 case DNET_CMD_BULK_READ
:
625 err
= blob_bulk_read(c
, state
, cmd
, data
);
627 case DNET_CMD_DEFRAG
:
628 err
= blob_start_defrag(c
);
638 static int dnet_blob_set_sync(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
640 struct eblob_backend_config
*c
= b
->data
;
642 c
->data
.sync
= atoi(value
);
646 static int dnet_blob_set_data(struct dnet_config_backend
*b
, char *key __unused
, char *file
)
648 struct eblob_backend_config
*c
= b
->data
;
651 err
= backend_storage_size(b
, file
);
653 char root
[strlen(file
)+1], *ptr
;
655 snprintf(root
, sizeof(root
), "%s", file
);
656 ptr
= strrchr(root
, '/');
659 err
= backend_storage_size(b
, root
);
667 c
->data
.file
= strdup(file
);
674 static int dnet_blob_set_block_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
676 struct eblob_backend_config
*c
= b
->data
;
678 c
->data
.bsize
= strtoul(value
, NULL
, 0);
682 static int dnet_blob_set_blob_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
684 struct eblob_backend_config
*c
= b
->data
;
685 uint64_t val
= strtoul(value
, NULL
, 0);
687 if (strchr(value
, 'T'))
688 val
*= 1024*1024*1024*1024ULL;
689 else if (strchr(value
, 'G'))
690 val
*= 1024*1024*1024ULL;
691 else if (strchr(value
, 'M'))
693 else if (strchr(value
, 'K'))
696 c
->data
.blob_size
= val
;
700 static int dnet_blob_set_records_in_blob(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
702 struct eblob_backend_config
*c
= b
->data
;
703 uint64_t val
= strtoul(value
, NULL
, 0);
705 c
->data
.records_in_blob
= val
;
709 static int dnet_blob_set_blob_cache_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
711 struct eblob_backend_config
*c
= b
->data
;
713 c
->data
.cache_size
= strtoul(value
, NULL
, 0);
717 static int dnet_blob_set_defrag_timeout(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
719 struct eblob_backend_config
*c
= b
->data
;
721 c
->data
.defrag_timeout
= strtoul(value
, NULL
, 0);
725 static int dnet_blob_set_defrag_percentage(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
727 struct eblob_backend_config
*c
= b
->data
;
729 c
->data
.defrag_percentage
= strtoul(value
, NULL
, 0);
733 static int dnet_blob_set_iterate_thread_num(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
735 struct eblob_backend_config
*c
= b
->data
;
737 c
->data
.iterate_threads
= strtoul(value
, NULL
, 0);
741 static int dnet_blob_set_blob_flags(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
743 struct eblob_backend_config
*c
= b
->data
;
745 c
->data
.blob_flags
= strtoul(value
, NULL
, 0);
749 int eblob_backend_storage_stat(void *priv
, struct dnet_stat
*st
)
752 struct eblob_backend_config
*r
= priv
;
754 memset(st
, 0, sizeof(struct dnet_stat
));
756 err
= backend_stat_low_level(r
->data
.file
, st
);
758 char root
[strlen(r
->data
.file
)+1], *ptr
;
760 snprintf(root
, sizeof(root
), "%s", r
->data
.file
);
761 ptr
= strrchr(root
, '/');
764 err
= backend_stat_low_level(root
, st
);
774 static void eblob_backend_cleanup(void *priv
)
776 struct eblob_backend_config
*c
= priv
;
778 eblob_cleanup(c
->eblob
);
783 static ssize_t
dnet_eblob_db_read(void *priv
, struct dnet_raw_id
*id
, void **datap
)
785 struct eblob_backend_config
*c
= priv
;
786 return dnet_db_read_raw(c
->eblob
, id
, datap
);
789 static int dnet_eblob_db_write(void *priv
, struct dnet_raw_id
*id
, void *data
, size_t size
)
791 struct eblob_backend_config
*c
= priv
;
792 return dnet_db_write_raw(c
->eblob
, id
, data
, size
);
795 static int dnet_eblob_db_remove(void *priv
, struct dnet_raw_id
*id
, int real_del
)
797 struct eblob_backend_config
*c
= priv
;
798 return dnet_db_remove_raw(c
->eblob
, id
, real_del
);
801 static long long dnet_eblob_db_total_elements(void *priv
)
803 struct eblob_backend_config
*c
= priv
;
804 return eblob_total_elements(c
->eblob
);
807 static int dnet_eblob_db_iterate(struct dnet_iterate_ctl
*ctl
)
809 struct eblob_backend_config
*c
= ctl
->iterate_private
;
810 return dnet_db_iterate(c
->eblob
, ctl
);
813 static int dnet_blob_config_init(struct dnet_config_backend
*b
, struct dnet_config
*cfg
)
815 struct eblob_backend_config
*c
= b
->data
;
819 dnet_backend_log(DNET_LOG_ERROR
, "blob: no data file present. Exiting.\n");
824 c
->data
.log
= (struct eblob_log
*)b
->log
;
826 c
->eblob
= eblob_init(&c
->data
);
833 cfg
->storage_size
= b
->storage_size
;
834 cfg
->storage_free
= b
->storage_free
;
835 b
->cb
.storage_stat
= eblob_backend_storage_stat
;
837 b
->cb
.command_private
= c
;
838 b
->cb
.command_handler
= eblob_backend_command_handler
;
839 b
->cb
.send
= eblob_send
;
840 b
->cb
.backend_cleanup
= eblob_backend_cleanup
;
842 b
->cb
.meta_read
= dnet_eblob_db_read
;
843 b
->cb
.meta_write
= dnet_eblob_db_write
;
844 b
->cb
.meta_remove
= dnet_eblob_db_remove
;
845 b
->cb
.meta_total_elements
= dnet_eblob_db_total_elements
;
846 b
->cb
.meta_iterate
= dnet_eblob_db_iterate
;
854 static void dnet_blob_config_cleanup(struct dnet_config_backend
*b
)
856 struct eblob_backend_config
*c
= b
->data
;
858 eblob_backend_cleanup(c
);
861 static struct dnet_config_entry dnet_cfg_entries_blobsystem
[] = {
862 {"sync", dnet_blob_set_sync
},
863 {"data", dnet_blob_set_data
},
864 {"data_block_size", dnet_blob_set_block_size
},
865 {"blob_flags", dnet_blob_set_blob_flags
},
866 {"iterate_thread_num", dnet_blob_set_iterate_thread_num
},
867 {"blob_size", dnet_blob_set_blob_size
},
868 {"records_in_blob", dnet_blob_set_records_in_blob
},
869 {"blob_cache_size", dnet_blob_set_blob_cache_size
},
870 {"defrag_timeout", dnet_blob_set_defrag_timeout
},
871 {"defrag_percentage", dnet_blob_set_defrag_percentage
},
874 static struct dnet_config_backend dnet_eblob_backend
= {
876 .ent
= dnet_cfg_entries_blobsystem
,
877 .num
= ARRAY_SIZE(dnet_cfg_entries_blobsystem
),
878 .size
= sizeof(struct eblob_backend_config
),
879 .init
= dnet_blob_config_init
,
880 .cleanup
= dnet_blob_config_cleanup
,
883 int dnet_eblob_backend_init(void)
885 return dnet_backend_register(&dnet_eblob_backend
);
888 void dnet_eblob_backend_exit(void)
890 /* cleanup routing will be called explicitly through backend->cleanup() callback */