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 #include <sys/types.h>
18 #include <sys/socket.h>
29 #include "elliptics.h"
31 #include "elliptics/packet.h"
32 #include "elliptics/interface.h"
34 #define dnet_map_log(n, level, fmt, a...) do { if ((n)) dnet_log((n), level, fmt, ##a); else fprintf(stderr, fmt, ##a); } while (0)
36 int dnet_update_ts_metadata_raw(struct dnet_meta_container
*mc
, uint64_t flags_set
, uint64_t flags_clear
)
39 void *data
= mc
->data
;
40 uint32_t size
= mc
->size
;
41 struct dnet_meta_update
*mu
;
44 if (size
< sizeof(struct dnet_meta
)) {
48 m
= *(struct dnet_meta
*)data
;
49 dnet_convert_meta(&m
);
51 if (m
.size
+ sizeof(struct dnet_meta
) > size
) {
55 if (m
.type
== DNET_META_UPDATE
) {
56 mu
= (struct dnet_meta_update
*)(data
+ sizeof(struct dnet_meta
));
58 dnet_convert_meta_update(mu
);
60 dnet_current_time(&mu
->tm
);
61 mu
->flags
|= flags_set
;
62 mu
->flags
&= ~flags_clear
;
64 dnet_convert_meta_update(mu
);
67 data
+= m
.size
+ sizeof(struct dnet_meta
);
68 size
-= m
.size
+ sizeof(struct dnet_meta
);
74 void dnet_create_meta_update(struct dnet_meta
*m
, struct timespec
*ts
, uint64_t flags_set
, uint64_t flags_clear
)
76 struct dnet_meta_update
*mu
= (struct dnet_meta_update
*)m
->data
;
78 m
->size
= sizeof(struct dnet_meta_update
);
79 m
->type
= DNET_META_UPDATE
;
82 dnet_current_time(&mu
->tm
);
84 mu
->tm
.tsec
= ts
->tv_sec
;
85 mu
->tm
.tnsec
= ts
->tv_nsec
;
89 mu
->flags
|= flags_set
;
90 mu
->flags
&= ~flags_clear
;
92 dnet_convert_meta_update(mu
);
96 struct dnet_meta_update
*dnet_get_meta_update(struct dnet_node
*n
, struct dnet_meta_container
*mc
,
97 struct dnet_meta_update
*meta_update
)
100 void *data
= mc
->data
;
101 uint32_t size
= mc
->size
;
102 struct dnet_meta_update
*mu
;
106 if (size
< sizeof(struct dnet_meta
)) {
107 dnet_log(n
, DNET_LOG_ERROR
, "Metadata size %u is too small, min %zu, searching for type 0x%x.\n",
108 size
, sizeof(struct dnet_meta
), DNET_META_UPDATE
);
112 m
= *(struct dnet_meta
*)data
;
113 dnet_convert_meta(&m
);
115 if (m
.size
+ sizeof(struct dnet_meta
) > size
) {
116 dnet_log(n
, DNET_LOG_ERROR
, "Metadata entry broken: entry size %u, type: 0x%x, struct size: %zu, "
117 "total size left: %u, searching for type: 0x%x.\n",
118 m
.size
, m
.type
, sizeof(struct dnet_meta
), size
, DNET_META_UPDATE
);
122 if (m
.type
== DNET_META_UPDATE
) {
123 mu
= (struct dnet_meta_update
*)(data
+ sizeof(struct dnet_meta
));
125 num
= m
.size
/ sizeof(struct dnet_meta_update
);
128 memcpy(meta_update
, &mu
[0], sizeof(struct dnet_meta_update
));
129 dnet_convert_meta_update(meta_update
);
135 data
+= m
.size
+ sizeof(struct dnet_meta
);
136 size
-= m
.size
+ sizeof(struct dnet_meta
);
141 struct dnet_meta
*dnet_meta_search(struct dnet_node
*n
, struct dnet_meta_container
*mc
, uint32_t type
)
143 void *data
= mc
->data
;
144 uint32_t size
= mc
->size
;
145 struct dnet_meta m
, *found
= NULL
;
148 if (size
< sizeof(struct dnet_meta
)) {
149 dnet_map_log(n
, DNET_LOG_ERROR
, "Metadata size %u is too small, min %zu, searching for type 0x%x.\n",
150 size
, sizeof(struct dnet_meta
), type
);
154 m
= *(struct dnet_meta
*)data
;
155 dnet_convert_meta(&m
);
157 if (m
.size
+ sizeof(struct dnet_meta
) > size
) {
158 dnet_map_log(n
, DNET_LOG_ERROR
, "Metadata entry broken: entry size %u, type: 0x%x, struct size: %zu, "
159 "total size left: %u, searching for type: 0x%x.\n",
160 m
.size
, m
.type
, sizeof(struct dnet_meta
), size
, type
);
164 if (m
.type
== type
) {
169 data
+= m
.size
+ sizeof(struct dnet_meta
);
170 size
-= m
.size
+ sizeof(struct dnet_meta
);
176 void dnet_convert_metadata(struct dnet_node
*n __unused
, void *data
, int size
)
184 ptr
+= sizeof(struct dnet_meta
) + m
->size
;
185 size
-= sizeof(struct dnet_meta
) + m
->size
;
187 dnet_convert_meta(m
);
191 int dnet_write_metadata(struct dnet_node
*n
, struct dnet_meta_container
*mc
, int convert
, uint64_t cflags
)
193 struct dnet_io_control ctl
;
197 if (n
->flags
& DNET_CFG_NO_META
)
201 dnet_convert_metadata(n
, mc
->data
, mc
->size
);
203 memset(&ctl
, 0, sizeof(ctl
));
208 ctl
.io
.size
= mc
->size
;
209 ctl
.io
.flags
= DNET_IO_FLAGS_META
;
212 memcpy(&ctl
.id
, &mc
->id
, sizeof(struct dnet_id
));
213 ctl
.id
.type
= ctl
.io
.type
= EBLOB_TYPE_META
;
215 err
= dnet_write_data_wait(n
, &ctl
, &result
);
224 int dnet_create_write_metadata_strings(struct dnet_node
*n
, const void *remote
, unsigned int remote_len
,
225 struct dnet_id
*id
, struct timespec
*ts
, uint64_t cflags
)
227 struct dnet_metadata_control mc
;
232 pthread_mutex_lock(&n
->group_lock
);
233 group_num
= n
->group_num
;
234 groups
= alloca(group_num
* sizeof(int));
236 memcpy(groups
, n
->groups
, group_num
* sizeof(int));
237 pthread_mutex_unlock(&n
->group_lock
);
239 memset(&mc
, 0, sizeof(mc
));
243 mc
.group_num
= group_num
;
252 gettimeofday(&tv
, NULL
);
253 mc
.ts
.tv_sec
= tv
.tv_sec
;
254 mc
.ts
.tv_nsec
= tv
.tv_usec
* 1000;
257 err
= dnet_create_write_metadata(n
, &mc
);
259 dnet_log(n
, DNET_LOG_ERROR
, "%s: failed to write metadata: %d\n", dnet_dump_id(id
), err
);
265 int dnet_create_metadata(struct dnet_node
*n
, struct dnet_metadata_control
*ctl
, struct dnet_meta_container
*mc
)
267 struct dnet_meta_check_status
*c
;
269 int size
= 0, err
, nsize
= 0;
272 size
+= sizeof(struct dnet_meta_check_status
) + sizeof(struct dnet_meta
);
274 if (ctl
->obj
&& ctl
->len
)
275 size
+= ctl
->len
+ sizeof(struct dnet_meta
);
277 if (ctl
->groups
&& ctl
->group_num
)
278 size
+= ctl
->group_num
* sizeof(int) + sizeof(struct dnet_meta
);
280 size
+= sizeof(struct dnet_meta_update
) + sizeof(struct dnet_meta
);
282 ns
= dnet_node_get_ns(n
, &nsize
);
284 size
+= nsize
+ sizeof(struct dnet_meta
);
291 mc
->data
= malloc(size
);
296 memset(mc
->data
, 0, size
);
298 m
= (struct dnet_meta
*)(mc
->data
);
300 c
= (struct dnet_meta_check_status
*)m
->data
;
301 m
->size
= sizeof(struct dnet_meta_check_status
);
302 m
->type
= DNET_META_CHECK_STATUS
;
304 /* Check status is undefined for now, it will be filled during actual check */
305 memset(c
, 0, sizeof(struct dnet_meta_check_status
));
307 m
= (struct dnet_meta
*)(m
->data
+ m
->size
);
308 dnet_create_meta_update(m
, ctl
->ts
.tv_sec
? &ctl
->ts
: NULL
, 0, 0);
310 m
= (struct dnet_meta
*)(m
->data
+ m
->size
);
312 if (ctl
->obj
&& ctl
->len
) {
314 m
->type
= DNET_META_PARENT_OBJECT
;
315 memcpy(m
->data
, ctl
->obj
, ctl
->len
);
317 m
= (struct dnet_meta
*)(m
->data
+ m
->size
);
320 if (ctl
->groups
&& ctl
->group_num
) {
321 m
->size
= ctl
->group_num
* sizeof(int);
322 m
->type
= DNET_META_GROUPS
;
323 memcpy(m
->data
, ctl
->groups
, ctl
->group_num
* sizeof(int));
325 m
= (struct dnet_meta
*)(m
->data
+ m
->size
);
330 m
->type
= DNET_META_NAMESPACE
;
331 memcpy(m
->data
, ns
, nsize
);
333 m
= (struct dnet_meta
*)(m
->data
+ m
->size
);
337 memcpy(&mc
->id
, &ctl
->id
, sizeof(struct dnet_id
));
344 int dnet_create_write_metadata(struct dnet_node
*n
, struct dnet_metadata_control
*ctl
)
346 struct dnet_meta_container mc
;
349 memset(&mc
, 0, sizeof(struct dnet_meta_container
));
351 err
= dnet_create_metadata(n
, ctl
, &mc
);
355 err
= dnet_write_metadata(n
, &mc
, 1, ctl
->cflags
);
365 static char *dnet_meta_types
[__DNET_META_MAX
] = {
366 [DNET_META_PARENT_OBJECT
] = "DNET_META_PARENT_OBJECT",
367 [DNET_META_GROUPS
] = "DNET_META_GROUPS",
368 [DNET_META_CHECK_STATUS
] = "DNET_META_CHECK_STATUS",
369 [DNET_META_NAMESPACE
] = "DNET_META_NAMESPACE",
370 [DNET_META_UPDATE
] = "DNET_META_UPDATE",
371 [DNET_META_CHECKSUM
] = "DNET_META_CHECKSUM",
374 void dnet_meta_print(struct dnet_node
*n
, struct dnet_meta_container
*mc
)
385 dnet_log(n
, DNET_LOG_DATA
, "%s: size: %u\n", dnet_dump_id_len(&mc
->id
, DNET_ID_SIZE
), mc
->size
);
390 dnet_convert_meta(m
);
392 if (m
->type
>= __DNET_META_MAX
|| m
->type
< DNET_META_PARENT_OBJECT
) {
393 dnet_log(n
, DNET_LOG_ERROR
, "%s: incorrect meta type %d\n", dnet_dump_id(&mc
->id
), m
->type
);
397 if (m
->type
== DNET_META_PARENT_OBJECT
) {
398 char name
[m
->size
+ 1];
400 memcpy(name
, m
->data
, m
->size
);
401 name
[m
->size
] = '\0';
402 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, name: '%s'\n",
403 dnet_meta_types
[m
->type
], m
->type
, m
->size
, name
);
404 } else if (m
->type
== DNET_META_GROUPS
) {
405 int *groups
= (int *)m
->data
;
406 int gnum
= m
->size
/ sizeof(int);
407 char str
[gnum
* 36 + 1], *ptr
;
410 memset(str
, 0, sizeof(str
));
414 for (i
=0; i
<gnum
; ++i
) {
415 err
= snprintf(ptr
, rest
, "%d:", groups
[i
]);
426 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, groups: %s\n",
427 dnet_meta_types
[m
->type
], m
->type
, m
->size
, str
);
428 } else if (m
->type
== DNET_META_CHECK_STATUS
) {
429 struct dnet_meta_check_status
*s
= (struct dnet_meta_check_status
*)m
->data
;
431 dnet_convert_meta_check_status(s
);
433 localtime_r((time_t *)&s
->tm
.tsec
, &tm
);
434 strftime(tstr
, sizeof(tstr
), "%F %R:%S %Z", &tm
);
436 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, check status: %d, ts: %s: %lld.%lld\n",
437 dnet_meta_types
[m
->type
],
438 m
->type
, m
->size
, s
->status
, tstr
,
439 (unsigned long long)s
->tm
.tsec
,
440 (unsigned long long)s
->tm
.tnsec
);
441 } else if (m
->type
== DNET_META_UPDATE
) {
442 struct dnet_meta_update
*mu
= (struct dnet_meta_update
*)m
->data
;
444 dnet_convert_meta_update(mu
);
446 localtime_r((time_t *)&mu
->tm
.tsec
, &tm
);
447 strftime(tstr
, sizeof(tstr
), "%F %R:%S %Z", &tm
);
449 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, flags: %llx, ts: %s %lld.%lld\n",
450 dnet_meta_types
[m
->type
], m
->type
, m
->size
,
451 (unsigned long long)mu
->flags
, tstr
,
452 (unsigned long long)mu
->tm
.tsec
, (unsigned long long)mu
->tm
.tnsec
);
453 } else if (m
->type
== DNET_META_NAMESPACE
) {
454 char str
[m
->size
+ 1];
455 memcpy(str
, m
->data
, m
->size
);
458 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, namespace: %s\n",
459 dnet_meta_types
[m
->type
], m
->type
, m
->size
, str
);
460 } else if (m
->type
== DNET_META_CHECKSUM
) {
461 struct dnet_meta_checksum
*cs
= (struct dnet_meta_checksum
*)m
->data
;
462 char str
[2*DNET_CSUM_SIZE
+1];
464 localtime_r((time_t *)&cs
->tm
.tsec
, &tm
);
465 strftime(tstr
, sizeof(tstr
), "%F %R:%S %Z", &tm
);
467 dnet_dump_id_len_raw(cs
->checksum
, DNET_CSUM_SIZE
, str
);
468 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u, csum: %s, ts: %s %lld.%lld\n",
469 dnet_meta_types
[m
->type
], m
->type
, m
->size
, str
, tstr
,
470 (unsigned long long)cs
->tm
.tsec
, (unsigned long long)cs
->tm
.tnsec
);
472 dnet_log(n
, DNET_LOG_DATA
, "%s: type: %u, size: %u\n",
473 dnet_meta_types
[m
->type
], m
->type
, m
->size
);
476 data
+= m
->size
+ sizeof(*m
);
477 size
-= m
->size
+ sizeof(*m
);
481 int dnet_read_meta(struct dnet_node
*n
, struct dnet_meta_container
*mc
,
482 const void *remote
, unsigned int remote_len
, struct dnet_id
*id
)
484 struct dnet_io_attr io
;
489 io
.flags
= DNET_IO_FLAGS_META
;
493 io
.start
= io
.num
= 0;
501 dnet_transform(n
, remote
, remote_len
, &raw
);
506 memcpy(io
.id
, id
->id
, DNET_ID_SIZE
);
507 memcpy(io
.parent
, id
->id
, DNET_ID_SIZE
);
509 data
= dnet_read_data_wait(n
, id
, &io
, 0, &err
);
513 memcpy(io
.id
, id
->id
, DNET_ID_SIZE
);
514 memcpy(io
.parent
, id
->id
, DNET_ID_SIZE
);
516 data
= dnet_read_data_wait_raw(n
, id
, &io
, DNET_CMD_READ
, 0, &err
);
520 io
.size
-= sizeof(struct dnet_io_attr
);
522 mc
->data
= malloc(io
.size
);
528 memcpy(mc
->data
, data
+ sizeof(struct dnet_io_attr
), io
.size
);
530 memcpy(&mc
->id
, id
, sizeof(struct dnet_id
));
540 int dnet_meta_update_check_status_raw(struct dnet_node
*n
, struct dnet_meta_container
*mc
)
542 struct dnet_meta
*m
= NULL
;
543 struct dnet_meta_check_status
*meta_check
;
546 m
= dnet_meta_search(n
, mc
, DNET_META_CHECK_STATUS
);
549 mc
->data
= realloc(mc
->data
, mc
->size
+ sizeof(struct dnet_meta
) + sizeof(struct dnet_meta_check_status
));
555 m
= mc
->data
+ mc
->size
;
556 mc
->size
+= sizeof(struct dnet_meta
) + sizeof(struct dnet_meta_check_status
);
558 m
->type
= DNET_META_CHECK_STATUS
;
559 m
->size
= sizeof(struct dnet_meta_check_status
);
560 dnet_convert_meta(m
);
563 meta_check
= (struct dnet_meta_check_status
*)m
->data
;
564 meta_check
->status
= 0;
566 dnet_current_time(&meta_check
->tm
);
568 dnet_convert_meta_check_status(meta_check
);
577 int dnet_meta_update_check_status(struct dnet_node
*n
, struct dnet_meta_container
*mc
)
579 struct dnet_raw_id id
;
582 err
= dnet_meta_update_check_status_raw(n
, mc
);
585 dnet_log(n
, DNET_LOG_ERROR
, "%s: failed to update DNET_META_CHECK_STATUS, err=%d\n",
586 dnet_dump_id(&mc
->id
), err
);
589 memcpy(&id
.id
, &mc
->id
.id
, DNET_ID_SIZE
);
590 err
= n
->cb
->meta_write(n
->cb
->command_private
, &id
, mc
->data
, mc
->size
);
592 dnet_log(n
, DNET_LOG_ERROR
, "%s: failed to write meta, err=%d\n",
593 dnet_dump_id(&mc
->id
), err
);