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>
20 #include <sys/syscall.h>
33 #include <netinet/in.h>
35 #include <elliptics/packet.h>
36 #include <elliptics/interface.h>
40 #define DNET_CONF_COMMENT '#'
41 #define DNET_CONF_DELIM '='
42 #define DNET_CONF_TIME_DELIM '.'
44 int dnet_parse_groups(char *value
, int **groupsp
)
46 int len
= strlen(value
), i
, num
= 0, start
= 0, pos
= 0;
50 if (sscanf(value
, "auto%d", &num
) == 1) {
55 for (i
=0; i
<len
; ++i
) {
56 if (value
[i
] == DNET_CONF_ADDR_DELIM
)
65 fprintf(stderr
, "no groups found\n");
69 groups
= malloc(sizeof(int) * num
);
73 memset(groups
, 0, num
* sizeof(int));
76 for (i
=0; i
<len
; ++i
) {
77 if (value
[i
] == DNET_CONF_ADDR_DELIM
) {
80 groups
[pos
] = atoi(ptr
);
91 groups
[pos
] = atoi(ptr
);
99 int dnet_parse_numeric_id(char *value
, unsigned char *id
)
102 unsigned int i
, len
= strlen(value
);
104 memset(id
, 0, DNET_ID_SIZE
);
106 if (len
/2 > DNET_ID_SIZE
)
107 len
= DNET_ID_SIZE
* 2;
112 for (i
=0; i
<len
/ 2; i
++) {
113 ch
[2] = value
[2*i
+ 0];
114 ch
[3] = value
[2*i
+ 1];
116 id
[i
] = (unsigned char)strtol((const char *)ch
, NULL
, 16);
120 ch
[2] = value
[2*i
+ 0];
123 id
[i
] = (unsigned char)strtol((const char *)ch
, NULL
, 16);
129 void dnet_common_log(void *priv
, int level
, const char *msg
)
139 gettimeofday(&tv
, NULL
);
140 localtime_r((time_t *)&tv
.tv_sec
, &tm
);
141 strftime(str
, sizeof(str
), "%F %R:%S", &tm
);
143 fprintf(stream
, "%s.%06lu %ld/%4d %1d: %s", str
, tv
.tv_usec
, dnet_get_id(), getpid(), level
, msg
);
147 void dnet_syslog(void *priv
__attribute__ ((unused
)), int level
, const char *msg
)
149 int prio
= LOG_DEBUG
;
154 if (level
== DNET_LOG_ERROR
)
156 if (level
== DNET_LOG_INFO
)
159 gettimeofday(&tv
, NULL
);
160 localtime_r((time_t *)&tv
.tv_sec
, &tm
);
161 strftime(str
, sizeof(str
), "%F %R:%S", &tm
);
163 syslog(prio
, "%s.%06lu %ld/%4d %1x: %s", str
, tv
.tv_usec
, dnet_get_id(), getpid(), level
, msg
);
166 int dnet_common_add_remote_addr(struct dnet_node
*n
, struct dnet_config
*main_cfg
, char *orig_addr
)
171 struct dnet_config cfg
;
176 a
= strdup(orig_addr
);
185 p
= strchr(addr
, ' ');
189 memcpy(&cfg
, main_cfg
, sizeof(struct dnet_config
));
191 err
= dnet_parse_addr(addr
, &cfg
);
193 dnet_log_raw(n
, DNET_LOG_ERROR
, "Failed to parse addr '%s': %d.\n", addr
, err
);
197 err
= dnet_add_state(n
, &cfg
);
209 while (addr
&& *addr
&& isspace(*addr
))
217 dnet_log_raw(n
, DNET_LOG_ERROR
, "No remote addresses added. Continue to work though.\n");
227 int dnet_common_prepend_data(struct timespec
*ts
, uint64_t size
, void *buf
, int *bufsize
)
230 struct dnet_common_embed
*e
= buf
;
231 uint64_t *edata
= (uint64_t *)e
->data
;
233 if (*bufsize
< (int)(sizeof(struct dnet_common_embed
) + sizeof(uint64_t)) * 2)
236 e
->size
= sizeof(uint64_t) * 2;
237 e
->type
= DNET_FCGI_EMBED_TIMESTAMP
;
239 dnet_common_convert_embedded(e
);
241 edata
[0] = dnet_bswap64(ts
->tv_sec
);
242 edata
[1] = dnet_bswap64(ts
->tv_nsec
);
244 buf
+= sizeof(struct dnet_common_embed
) + sizeof(uint64_t) * 2;
248 e
->type
= DNET_FCGI_EMBED_DATA
;
250 dnet_common_convert_embedded(e
);
252 buf
+= sizeof(struct dnet_common_embed
);
254 *bufsize
= buf
- orig
;
258 #define dnet_map_log(n, level, fmt, a...) do { if ((n)) dnet_log_raw((n), level, fmt, ##a); else fprintf(stderr, fmt, ##a); } while (0)
260 int dnet_map_history(struct dnet_node
*n
, char *file
, struct dnet_history_map
*map
)
265 map
->fd
= open(file
, O_RDWR
| O_CLOEXEC
);
268 dnet_map_log(n
, DNET_LOG_ERROR
, "Failed to open history file '%s': %s [%d].\n",
269 file
, strerror(errno
), errno
);
273 err
= fstat(map
->fd
, &st
);
276 dnet_map_log(n
, DNET_LOG_ERROR
, "Failed to stat history file '%s': %s [%d].\n",
277 file
, strerror(errno
), errno
);
281 if (st
.st_size
% (int)sizeof(struct dnet_history_entry
)) {
282 dnet_map_log(n
, DNET_LOG_ERROR
, "Corrupted history file '%s', "
283 "its size %llu must be multiple of %zu.\n",
284 file
, (unsigned long long)st
.st_size
,
285 sizeof(struct dnet_history_entry
));
289 map
->size
= st
.st_size
;
291 map
->ent
= mmap(NULL
, map
->size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, map
->fd
, 0);
292 if (map
->ent
== MAP_FAILED
) {
294 dnet_map_log(n
, DNET_LOG_ERROR
, "Failed to mmap history file '%s': %s [%d].\n",
295 file
, strerror(errno
), errno
);
299 map
->num
= map
->size
/ sizeof(struct dnet_history_entry
);
301 dnet_map_log(n
, DNET_LOG_NOTICE
, "Mapped %ld entries in '%s'.\n", map
->num
, file
);
311 void dnet_unmap_history(struct dnet_node
*n
__attribute((unused
)), struct dnet_history_map
*map
)
313 munmap(map
->ent
, map
->size
);
317 struct dnet_meta
* dnet_meta_search_cust(struct dnet_meta_container
*mc
, uint32_t type
)
319 void *data
= mc
->data
;
320 uint32_t size
= mc
->size
;
321 struct dnet_meta m
, *found
= NULL
;
324 if (size
< sizeof(struct dnet_meta
)) {
325 fprintf(stderr
, "Metadata size %u is too small, min %zu, searching for 0x%x.\n",
326 size
, sizeof(struct dnet_meta
), type
);
330 m
= *(struct dnet_meta
*)data
;
331 dnet_convert_meta(&m
);
333 if (m
.size
+ sizeof(struct dnet_meta
) > size
) {
334 fprintf(stderr
, "Metadata entry broken: entry size %u, type: 0x%x, struct size: %zu, "
335 "total size left: %u, searching for 0x%x.\n",
336 m
.size
, m
.type
, sizeof(struct dnet_meta
), size
, type
);
340 if (m
.type
== type
) {
345 data
+= m
.size
+ sizeof(struct dnet_meta
);
346 size
-= m
.size
+ sizeof(struct dnet_meta
);
352 int dnet_background(void)
359 fprintf(stderr
, "Failed to fork to background: %s.\n", strerror(errno
));
364 printf("Daemon pid: %d.\n", pid
);
374 fd
= open("/dev/null", O_RDWR
);
377 fprintf(stderr
, "Can not open /dev/null: %d\n", fd
);