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 struct dnet_session
*s
= dnet_session_create(n
);
513 dnet_session_set_groups(s
, (int *)&id
->group_id
, 1);
515 err
= dnet_write_data_wait(s
, &ctl
, &result
);
531 static int blob_file_info(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
)
533 struct eblob_backend
*b
= c
->eblob
;
534 struct eblob_key key
;
535 uint64_t offset
, size
;
538 memcpy(key
.id
, cmd
->id
.id
, EBLOB_ID_SIZE
);
539 err
= eblob_read(b
, &key
, &fd
, &offset
, &size
, cmd
->id
.type
);
541 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-file-info: info-read: %d: %s.\n",
542 dnet_dump_id(&cmd
->id
), err
, strerror(-err
));
548 dnet_backend_log(DNET_LOG_INFO
, "%s: EBLOB: blob-file-info: info-read: ZERO-SIZE-FILE.\n",
549 dnet_dump_id(&cmd
->id
));
553 err
= dnet_send_file_info(state
, cmd
, fd
, offset
, size
);
559 static int blob_bulk_read(struct eblob_backend_config
*c
, void *state
, struct dnet_cmd
*cmd
, void *data
)
562 struct dnet_io_attr
*io
= data
;
563 struct dnet_io_attr
*ios
= io
+1;
567 dnet_convert_io_attr(io
);
568 count
= io
->size
/ sizeof(struct dnet_io_attr
);
570 for (i
= 0; i
< count
; i
++) {
571 ret
= blob_read(c
, state
, cmd
, &ios
[i
]);
581 static int eblob_backend_checksum(struct dnet_node
*n
, void *priv
, struct dnet_id
*id
, void *csum
, int *csize
) {
582 struct eblob_backend_config
*c
= priv
;
583 struct eblob_backend
*b
= c
->eblob
;
584 uint64_t offset
, size
;
585 struct eblob_key key
;
588 memcpy(key
.id
, id
->id
, EBLOB_ID_SIZE
);
589 err
= eblob_read(b
, &key
, &fd
, &offset
, &size
, EBLOB_TYPE_DATA
);
591 dnet_backend_log(DNET_LOG_ERROR
, "%s: EBLOB: blob-checksum: read: type: %d: %d: %s.\n",
592 dnet_dump_id_str(id
->id
), id
->type
, err
, strerror(-err
));
597 memset(csum
, 0, *csize
);
599 err
= dnet_checksum_fd(n
, csum
, csize
, fd
, offset
, size
);
605 static int blob_start_defrag(struct eblob_backend_config
*c
)
607 return eblob_start_defrag(c
->eblob
);
610 static int eblob_backend_command_handler(void *state
, void *priv
, struct dnet_cmd
*cmd
, void *data
)
613 struct eblob_backend_config
*c
= priv
;
617 case DNET_CMD_LOOKUP
:
618 err
= blob_file_info(c
, state
, cmd
);
621 err
= blob_write(c
, state
, cmd
, data
);
624 err
= blob_read(c
, state
, cmd
, data
);
626 case DNET_CMD_READ_RANGE
:
627 case DNET_CMD_DEL_RANGE
:
628 err
= blob_read_range(c
, state
, cmd
, data
);
631 path
= strdup(c
->data
.file
);
637 p
= strrchr(path
, '/');
645 err
= backend_stat(state
, path
, cmd
);
649 err
= blob_del(c
, cmd
);
651 case DNET_CMD_BULK_READ
:
652 err
= blob_bulk_read(c
, state
, cmd
, data
);
654 case DNET_CMD_DEFRAG
:
655 err
= blob_start_defrag(c
);
665 static int dnet_blob_set_sync(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
667 struct eblob_backend_config
*c
= b
->data
;
669 c
->data
.sync
= atoi(value
);
673 static int dnet_blob_set_data(struct dnet_config_backend
*b
, char *key __unused
, char *file
)
675 struct eblob_backend_config
*c
= b
->data
;
678 err
= backend_storage_size(b
, file
);
680 char root
[strlen(file
)+1], *ptr
;
682 snprintf(root
, sizeof(root
), "%s", file
);
683 ptr
= strrchr(root
, '/');
686 err
= backend_storage_size(b
, root
);
694 c
->data
.file
= strdup(file
);
701 static int dnet_blob_set_block_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
703 struct eblob_backend_config
*c
= b
->data
;
705 c
->data
.bsize
= strtoul(value
, NULL
, 0);
709 static int dnet_blob_set_blob_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
711 struct eblob_backend_config
*c
= b
->data
;
712 uint64_t val
= strtoul(value
, NULL
, 0);
714 if (strchr(value
, 'T'))
715 val
*= 1024*1024*1024*1024ULL;
716 else if (strchr(value
, 'G'))
717 val
*= 1024*1024*1024ULL;
718 else if (strchr(value
, 'M'))
720 else if (strchr(value
, 'K'))
723 c
->data
.blob_size
= val
;
727 static int dnet_blob_set_records_in_blob(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
729 struct eblob_backend_config
*c
= b
->data
;
730 uint64_t val
= strtoul(value
, NULL
, 0);
732 c
->data
.records_in_blob
= val
;
736 static int dnet_blob_set_blob_cache_size(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
738 struct eblob_backend_config
*c
= b
->data
;
740 c
->data
.cache_size
= strtoul(value
, NULL
, 0);
744 static int dnet_blob_set_defrag_timeout(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
746 struct eblob_backend_config
*c
= b
->data
;
748 c
->data
.defrag_timeout
= strtoul(value
, NULL
, 0);
752 static int dnet_blob_set_defrag_percentage(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
754 struct eblob_backend_config
*c
= b
->data
;
756 c
->data
.defrag_percentage
= strtoul(value
, NULL
, 0);
760 static int dnet_blob_set_iterate_thread_num(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
762 struct eblob_backend_config
*c
= b
->data
;
764 c
->data
.iterate_threads
= strtoul(value
, NULL
, 0);
768 static int dnet_blob_set_blob_flags(struct dnet_config_backend
*b
, char *key __unused
, char *value
)
770 struct eblob_backend_config
*c
= b
->data
;
772 c
->data
.blob_flags
= strtoul(value
, NULL
, 0);
776 int eblob_backend_storage_stat(void *priv
, struct dnet_stat
*st
)
779 struct eblob_backend_config
*r
= priv
;
781 memset(st
, 0, sizeof(struct dnet_stat
));
783 err
= backend_stat_low_level(r
->data
.file
, st
);
785 char root
[strlen(r
->data
.file
)+1], *ptr
;
787 snprintf(root
, sizeof(root
), "%s", r
->data
.file
);
788 ptr
= strrchr(root
, '/');
791 err
= backend_stat_low_level(root
, st
);
801 static void eblob_backend_cleanup(void *priv
)
803 struct eblob_backend_config
*c
= priv
;
805 eblob_cleanup(c
->eblob
);
810 static ssize_t
dnet_eblob_db_read(void *priv
, struct dnet_raw_id
*id
, void **datap
)
812 struct eblob_backend_config
*c
= priv
;
813 return dnet_db_read_raw(c
->eblob
, id
, datap
);
816 static int dnet_eblob_db_write(void *priv
, struct dnet_raw_id
*id
, void *data
, size_t size
)
818 struct eblob_backend_config
*c
= priv
;
819 return dnet_db_write_raw(c
->eblob
, id
, data
, size
);
822 static int dnet_eblob_db_remove(void *priv
, struct dnet_raw_id
*id
, int real_del
)
824 struct eblob_backend_config
*c
= priv
;
825 return dnet_db_remove_raw(c
->eblob
, id
, real_del
);
828 static long long dnet_eblob_db_total_elements(void *priv
)
830 struct eblob_backend_config
*c
= priv
;
831 return eblob_total_elements(c
->eblob
);
834 static int dnet_eblob_db_iterate(struct dnet_iterate_ctl
*ctl
)
836 struct eblob_backend_config
*c
= ctl
->iterate_private
;
837 return dnet_db_iterate(c
->eblob
, ctl
);
840 static int dnet_blob_config_init(struct dnet_config_backend
*b
, struct dnet_config
*cfg
)
842 struct eblob_backend_config
*c
= b
->data
;
846 dnet_backend_log(DNET_LOG_ERROR
, "blob: no data file present. Exiting.\n");
851 c
->data
.log
= (struct eblob_log
*)b
->log
;
853 c
->eblob
= eblob_init(&c
->data
);
860 cfg
->storage_size
= b
->storage_size
;
861 cfg
->storage_free
= b
->storage_free
;
862 b
->cb
.storage_stat
= eblob_backend_storage_stat
;
864 b
->cb
.command_private
= c
;
865 b
->cb
.command_handler
= eblob_backend_command_handler
;
866 b
->cb
.send
= eblob_send
;
867 b
->cb
.backend_cleanup
= eblob_backend_cleanup
;
868 b
->cb
.checksum
= eblob_backend_checksum
;
870 b
->cb
.meta_read
= dnet_eblob_db_read
;
871 b
->cb
.meta_write
= dnet_eblob_db_write
;
872 b
->cb
.meta_remove
= dnet_eblob_db_remove
;
873 b
->cb
.meta_total_elements
= dnet_eblob_db_total_elements
;
874 b
->cb
.meta_iterate
= dnet_eblob_db_iterate
;
882 static void dnet_blob_config_cleanup(struct dnet_config_backend
*b
)
884 struct eblob_backend_config
*c
= b
->data
;
886 eblob_backend_cleanup(c
);
889 static struct dnet_config_entry dnet_cfg_entries_blobsystem
[] = {
890 {"sync", dnet_blob_set_sync
},
891 {"data", dnet_blob_set_data
},
892 {"data_block_size", dnet_blob_set_block_size
},
893 {"blob_flags", dnet_blob_set_blob_flags
},
894 {"iterate_thread_num", dnet_blob_set_iterate_thread_num
},
895 {"blob_size", dnet_blob_set_blob_size
},
896 {"records_in_blob", dnet_blob_set_records_in_blob
},
897 {"blob_cache_size", dnet_blob_set_blob_cache_size
},
898 {"defrag_timeout", dnet_blob_set_defrag_timeout
},
899 {"defrag_percentage", dnet_blob_set_defrag_percentage
},
902 static struct dnet_config_backend dnet_eblob_backend
= {
904 .ent
= dnet_cfg_entries_blobsystem
,
905 .num
= ARRAY_SIZE(dnet_cfg_entries_blobsystem
),
906 .size
= sizeof(struct eblob_backend_config
),
907 .init
= dnet_blob_config_init
,
908 .cleanup
= dnet_blob_config_cleanup
,
911 int dnet_eblob_backend_init(void)
913 return dnet_backend_register(&dnet_eblob_backend
);
916 void dnet_eblob_backend_exit(void)
918 /* cleanup routing will be called explicitly through backend->cleanup() callback */