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>
35 #include "elliptics/packet.h"
36 #include "elliptics/interface.h"
41 #ifdef HAVE_SMACK_SUPPORT
42 int dnet_smack_backend_init(void);
43 void dnet_smack_backend_exit(void);
46 #ifdef HAVE_LEVELDB_SUPPORT
47 int dnet_leveldb_backend_init(void);
48 void dnet_leveldb_backend_exit(void);
53 #define __unused __attribute__ ((unused))
57 * Config parser is single-threaded.
58 * No locks and simultaneous access from different threads.
61 #define DNET_CONF_COMMENT '#'
62 #define DNET_CONF_DELIMITER '='
64 static char *dnet_skip_line(char *line
)
66 int len
= strlen(line
), i
;
68 for (i
=0; i
<len
; ++i
) {
69 if (line
[i
] == DNET_CONF_COMMENT
)
80 static struct dnet_log dnet_backend_logger
;
81 char *dnet_logger_value
;
83 static struct dnet_config dnet_cfg_state
;
84 static char *dnet_cfg_remotes
;
85 static int dnet_daemon_mode
;
87 static int dnet_simple_set(struct dnet_config_backend
*b __unused
, char *key
, char *str
)
89 unsigned long value
= strtoul(str
, NULL
, 0);
91 if (!strcmp(key
, "log_level"))
92 dnet_backend_logger
.log_level
= value
;
93 else if (!strcmp(key
, "wait_timeout"))
94 dnet_cfg_state
.wait_timeout
= value
;
95 else if (!strcmp(key
, "check_timeout"))
96 dnet_cfg_state
.check_timeout
= value
;
97 else if (!strcmp(key
, "stall_count"))
98 dnet_cfg_state
.stall_count
= value
;
99 else if (!strcmp(key
, "join"))
100 dnet_cfg_state
.flags
|= value
? DNET_CFG_JOIN_NETWORK
: 0;
101 else if (!strcmp(key
, "flags"))
102 dnet_cfg_state
.flags
|= (value
& ~DNET_CFG_JOIN_NETWORK
);
103 else if (!strcmp(key
, "daemon"))
104 dnet_daemon_mode
= value
;
105 else if (!strcmp(key
, "io_thread_num"))
106 dnet_cfg_state
.io_thread_num
= value
;
107 else if (!strcmp(key
, "nonblocking_io_thread_num"))
108 dnet_cfg_state
.nonblocking_io_thread_num
= value
;
109 else if (!strcmp(key
, "net_thread_num"))
110 dnet_cfg_state
.net_thread_num
= value
;
111 else if (!strcmp(key
, "bg_ionice_class"))
112 dnet_cfg_state
.bg_ionice_class
= value
;
113 else if (!strcmp(key
, "bg_ionice_prio"))
114 dnet_cfg_state
.bg_ionice_prio
= value
;
115 else if (!strcmp(key
, "removal_delay"))
116 dnet_cfg_state
.removal_delay
= value
;
117 else if (!strcmp(key
, "server_net_prio"))
118 dnet_cfg_state
.server_prio
= value
;
119 else if (!strcmp(key
, "client_net_prio"))
120 dnet_cfg_state
.client_prio
= value
;
121 else if (!strcmp(key
, "oplock_num"))
122 dnet_cfg_state
.oplock_num
= value
;
129 static int dnet_set_group(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
131 dnet_cfg_state
.group_id
= strtoul(value
, NULL
, 0);
135 static int dnet_set_addr(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
137 return dnet_parse_addr(value
, &dnet_cfg_state
);
140 static int dnet_set_remote_addrs(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
142 dnet_cfg_remotes
= strdup(value
);
143 if (!dnet_cfg_remotes
)
149 static int dnet_set_srw(struct dnet_config_backend
*b __unused
, char *key
, char *value
)
153 if (!strcmp(key
, "srw_config"))
154 ptr
= &dnet_cfg_state
.srw
.config
;
158 *ptr
= strdup(value
);
166 static int dnet_set_malloc_options(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
168 int err
, thr
= atoi(value
);
170 err
= mallopt(M_MMAP_THRESHOLD
, thr
);
172 dnet_backend_log(DNET_LOG_ERROR
, "Failed to set mmap threshold to %d: %s\n", thr
, strerror(errno
));
176 dnet_backend_log(DNET_LOG_INFO
, "Set mmap threshold to %d.\n", thr
);
180 static int dnet_set_auth_cookie(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
182 snprintf(dnet_cfg_state
.cookie
, DNET_AUTH_COOKIE_SIZE
, "%s", value
);
186 static int dnet_set_backend(struct dnet_config_backend
*b
, char *key __unused
, char *value
);
188 int dnet_set_log(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
196 if (dnet_logger_value
)
197 free(dnet_logger_value
);
199 dnet_logger_value
= tmp
;
201 if (!strcmp(dnet_logger_value
, "syslog")) {
202 openlog("elliptics", 0, LOG_USER
);
204 dnet_backend_logger
.log_private
= NULL
;
205 dnet_backend_logger
.log
= dnet_syslog
;
207 FILE *log
, *old
= dnet_backend_logger
.log_private
;
210 log
= fopen(dnet_logger_value
, "a");
213 fprintf(stderr
, "cnf: failed to open log file '%s': %s\n", dnet_logger_value
, strerror(errno
));
217 dnet_backend_logger
.log_private
= log
;
218 dnet_backend_logger
.log
= dnet_common_log
;
220 dnet_common_log(log
, 0xff, "Reopened log file\n");
223 dnet_common_log(old
, 0xff, "Reopened log file\n");
228 dnet_cfg_state
.log
= &dnet_backend_logger
;
232 static int dnet_set_history_env(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
234 snprintf(dnet_cfg_state
.history_env
, sizeof(dnet_cfg_state
.history_env
), "%s", value
);
238 static int dnet_set_cache_size(struct dnet_config_backend
*b __unused
, char *key __unused
, char *value
)
240 dnet_cfg_state
.cache_size
= strtoull(value
, NULL
, 0);
244 static struct dnet_config_entry dnet_cfg_entries
[] = {
245 {"mallopt_mmap_threshold", dnet_set_malloc_options
},
246 {"log_level", dnet_simple_set
},
247 {"wait_timeout", dnet_simple_set
},
248 {"check_timeout", dnet_simple_set
},
249 {"stall_count", dnet_simple_set
},
250 {"group", dnet_set_group
},
251 {"addr", dnet_set_addr
},
252 {"remote", dnet_set_remote_addrs
},
253 {"join", dnet_simple_set
},
254 {"flags", dnet_simple_set
},
255 {"backend", dnet_set_backend
},
256 {"daemon", dnet_simple_set
},
257 {"log", dnet_set_log
},
258 {"history", dnet_set_history_env
},
259 {"io_thread_num", dnet_simple_set
},
260 {"nonblocking_io_thread_num", dnet_simple_set
},
261 {"net_thread_num", dnet_simple_set
},
262 {"bg_ionice_class", dnet_simple_set
},
263 {"bg_ionice_prio", dnet_simple_set
},
264 {"removal_delay", dnet_simple_set
},
265 {"auth_cookie", dnet_set_auth_cookie
},
266 {"server_net_prio", dnet_simple_set
},
267 {"client_net_prio", dnet_simple_set
},
268 {"oplock_num", dnet_simple_set
},
269 {"srw_config", dnet_set_srw
},
270 {"cache_size", dnet_set_cache_size
},
273 static struct dnet_config_entry
*dnet_cur_cfg_entries
= dnet_cfg_entries
;
274 static int dnet_cur_cfg_size
= ARRAY_SIZE(dnet_cfg_entries
);
276 static struct dnet_config_backend
*dnet_cfg_backend
, *dnet_cfg_current_backend
;
277 static int dnet_cfg_backend_num
;
279 static int dnet_set_backend(struct dnet_config_backend
*current_backend __unused
, char *key __unused
, char *value
)
281 struct dnet_config_backend
*b
;
284 for (i
=0; i
<dnet_cfg_backend_num
; ++i
) {
285 b
= &dnet_cfg_backend
[i
];
287 if (!strcmp(value
, b
->name
)) {
289 b
->data
= malloc(b
->size
);
292 memset(b
->data
, 0, b
->size
);
295 b
->log
= dnet_cfg_state
.log
;
297 dnet_cur_cfg_entries
= b
->ent
;
298 dnet_cur_cfg_size
= b
->num
;
299 dnet_cfg_current_backend
= b
;
308 int dnet_backend_register(struct dnet_config_backend
*b
)
310 dnet_cfg_backend
= realloc(dnet_cfg_backend
, (dnet_cfg_backend_num
+ 1) * sizeof(struct dnet_config_backend
));
311 if (!dnet_cfg_backend
)
314 memcpy(&dnet_cfg_backend
[dnet_cfg_backend_num
], b
, sizeof(struct dnet_config_backend
));
315 dnet_cfg_backend_num
++;
320 struct dnet_node
*dnet_parse_config(char *file
, int mon
)
323 int buf_size
= 1024 * 1024;
324 char *buf
, *ptr
, *value
, *key
;
331 pthread_sigmask(SIG_BLOCK
, &sig
, NULL
);
332 sigprocmask(SIG_BLOCK
, &sig
, NULL
);
334 f
= fopen(file
, "r");
337 fprintf(stderr
, "cnf: failed to open config file '%s': %s.\n", file
, strerror(errno
));
341 buf
= malloc(buf_size
);
347 dnet_backend_logger
.log_level
= DNET_LOG_DEBUG
;
348 dnet_backend_logger
.log
= dnet_common_log
;
349 dnet_cfg_state
.log
= &dnet_backend_logger
;
351 err
= dnet_file_backend_init();
353 goto err_out_free_buf
;
355 err
= dnet_eblob_backend_init();
357 goto err_out_file_exit
;
359 #ifdef HAVE_SMACK_SUPPORT
360 err
= dnet_smack_backend_init();
362 goto err_out_eblob_exit
;
364 #ifdef HAVE_LEVELDB_SUPPORT
365 err
= dnet_leveldb_backend_init();
367 goto err_out_smack_exit
;
370 ptr
= fgets(buf
, buf_size
, f
);
376 dnet_backend_log(DNET_LOG_ERROR
, "cnf: failed to read config file '%s': %s.\n", file
, strerror(errno
));
382 ptr
= dnet_skip_line(ptr
);
389 if (ptr
[len
- 1] == '\r' || ptr
[len
- 1] == '\n') {
396 if (ptr
[len
- 2] == '\r' || ptr
[len
- 2] == '\n') {
404 for (i
=0; i
<len
; ++i
) {
405 if (isspace(ptr
[i
])) {
417 if (ptr
[i
] == DNET_CONF_DELIMITER
) {
423 if (ptr
[i
] == DNET_CONF_COMMENT
) {
436 fprintf(stderr
, "cnf: error in line %d: %s.\n", line_num
, ptr
);
445 for (i
=0; i
<dnet_cur_cfg_size
; ++i
) {
446 if (!strcmp(key
, dnet_cur_cfg_entries
[i
].key
)) {
447 err
= dnet_cur_cfg_entries
[i
].callback(dnet_cfg_current_backend
, key
, value
);
448 dnet_backend_log(DNET_LOG_INFO
, "backend: %s, key: %s, value: %s, err: %d\n",
449 (dnet_cfg_current_backend
) ? dnet_cfg_current_backend
->name
: "root level",
459 if (!dnet_cfg_current_backend
) {
464 if (dnet_daemon_mode
&& !mon
)
467 err
= dnet_cfg_current_backend
->init(dnet_cfg_current_backend
, &dnet_cfg_state
);
474 n
= dnet_server_node_create(&dnet_cfg_state
);
476 /* backend cleanup is already called */
480 err
= dnet_common_add_remote_addr(n
, &dnet_cfg_state
, dnet_cfg_remotes
);
482 goto err_out_node_destroy
;
486 err_out_node_destroy
:
487 dnet_server_node_destroy(n
);
489 free(dnet_cfg_remotes
);
491 #ifdef HAVE_LEVELDB_SUPPORT
492 dnet_leveldb_backend_exit();
495 #ifdef HAVE_SMACK_SUPPORT
496 dnet_smack_backend_exit();
499 dnet_eblob_backend_exit();
501 dnet_file_backend_exit();
511 int dnet_backend_check_log_level(int level
)
513 struct dnet_log
*l
= dnet_cfg_state
.log
;
515 return (l
->log
&& (l
->log_level
>= level
));
518 void dnet_backend_log_raw(int level
, const char *format
, ...)
522 struct dnet_log
*l
= dnet_cfg_state
.log
;
523 int buflen
= sizeof(buf
);
525 if (!dnet_backend_check_log_level(level
))
528 va_start(args
, format
);
529 vsnprintf(buf
, buflen
, format
, args
);
530 buf
[buflen
-1] = '\0';
531 l
->log(l
->log_private
, level
, buf
);