Elliptics version update: 2.19.2.6
[elliptics.git] / library / server.c
blob597a8ee5c88be8f68797dff6f845539358adb291
1 /*
2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
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/stat.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <signal.h>
24 #include "elliptics.h"
25 #include "elliptics/interface.h"
27 static int dnet_ids_generate(struct dnet_node *n, const char *file, unsigned long long storage_free)
29 int fd, err, size = 1024, i, num;
30 struct dnet_id id;
31 struct dnet_raw_id raw;
32 unsigned long long q = 100 * 1024 * 1024 * 1024ULL;
33 char *buf;
35 srand(time(NULL) + (unsigned long)n + (unsigned long)file + (unsigned long)&buf);
37 fd = open(file, O_RDWR | O_CREAT | O_TRUNC | O_APPEND | O_CLOEXEC, 0644);
38 if (fd < 0) {
39 err = -errno;
40 dnet_log_err(n, "failed to open/create ids file '%s'", file);
41 goto err_out_exit;
44 buf = malloc(size);
45 if (!buf) {
46 err = -ENOMEM;
47 goto err_out_close;
50 num = storage_free / q + 1;
51 for (i=0; i<num; ++i) {
52 int r = rand();
53 memcpy(buf, &n->addr, sizeof(struct dnet_addr));
54 memcpy(buf + sizeof(struct dnet_addr), &r, sizeof(r));
56 dnet_transform(n, buf, size, &id);
57 memcpy(&raw, id.id, sizeof(struct dnet_raw_id));
59 err = write(fd, &raw, sizeof(struct dnet_raw_id));
60 if (err != sizeof(struct dnet_raw_id)) {
61 dnet_log_err(n, "failed to write id into ids file '%s'", file);
62 goto err_out_unlink;
66 close(fd);
67 return 0;
69 err_out_unlink:
70 unlink(file);
71 err_out_close:
72 close(fd);
73 err_out_exit:
74 return err;
77 static struct dnet_raw_id *dnet_ids_init(struct dnet_node *n, const char *hdir, int *id_num, unsigned long long storage_free)
79 int fd, err, num;
80 const char *file = "ids";
81 char path[strlen(hdir) + 1 + strlen(file) + 1]; /* / + null-byte */
82 struct stat st;
83 struct dnet_raw_id *ids;
85 snprintf(path, sizeof(path), "%s/%s", hdir, file);
87 again:
88 fd = open(path, O_RDONLY | O_CLOEXEC);
89 if (fd < 0) {
90 err = -errno;
91 if (err == -ENOENT) {
92 err = dnet_ids_generate(n, path, storage_free);
93 if (err)
94 goto err_out_exit;
96 goto again;
99 dnet_log_err(n, "failed to open ids file '%s'", path);
100 goto err_out_exit;
103 err = fstat(fd, &st);
104 if (err)
105 goto err_out_close;
107 if (st.st_size % sizeof(struct dnet_raw_id)) {
108 dnet_log(n, DNET_LOG_ERROR, "Ids file size (%lu) is wrong, must be modulo of raw ID size (%zu).\n",
109 (unsigned long)st.st_size, sizeof(struct dnet_raw_id));
110 goto err_out_close;
113 num = st.st_size / sizeof(struct dnet_raw_id);
114 if (!num) {
115 dnet_log(n, DNET_LOG_ERROR, "No ids read, exiting.\n");
116 err = -EINVAL;
117 goto err_out_close;
120 ids = malloc(st.st_size);
121 if (!ids) {
122 err = -ENOMEM;
123 goto err_out_close;
126 err = read(fd, ids, st.st_size);
127 if (err != st.st_size) {
128 err = -errno;
129 dnet_log_err(n, "Failed to read ids file '%s'", path);
130 goto err_out_free;
133 close(fd);
135 *id_num = num;
136 return ids;
138 err_out_free:
139 free(ids);
140 err_out_close:
141 close(fd);
142 err_out_exit:
143 return NULL;
146 static int dnet_node_check_stack(struct dnet_node *n)
148 size_t stack_size;
149 int err;
151 err = pthread_attr_getstacksize(&n->attr, &stack_size);
152 if (err) {
153 err = -err;
154 dnet_log_err(n, "Failed to get stack size: %d", err);
155 goto err_out_exit;
158 if (stack_size <= 1024 * 1024) {
159 dnet_log(n, DNET_LOG_ERROR, "Stack size (%zd bytes) is too small, exiting\n", stack_size);
160 err = -ENOMEM;
161 goto err_out_exit;
164 dnet_log(n, DNET_LOG_NOTICE, "Stack size: %zd bytes\n", stack_size);
166 err_out_exit:
167 return err;
170 struct dnet_node *dnet_server_node_create(struct dnet_config *cfg)
172 struct dnet_node *n;
173 struct dnet_raw_id *ids = NULL;
174 int id_num = 0;
175 int err = -ENOMEM;
177 n = dnet_node_create(cfg);
178 if (!n)
179 goto err_out_exit;
181 err = dnet_node_check_stack(n);
182 if (err)
183 goto err_out_node_destroy;
185 if (!n->notify_hash_size) {
186 n->notify_hash_size = DNET_DEFAULT_NOTIFY_HASH_SIZE;
188 err = dnet_notify_init(n);
189 if (err)
190 goto err_out_node_destroy;
192 dnet_log(n, DNET_LOG_NOTICE, "No notify hash size provided, using default %d.\n",
193 n->notify_hash_size);
196 err = dnet_cache_init(n);
197 if (err)
198 goto err_out_notify_exit;
200 if (cfg->flags & DNET_CFG_JOIN_NETWORK) {
201 int s;
203 err = dnet_locks_init(n, cfg->oplock_num);
204 if (err)
205 goto err_out_cache_cleanup;
207 ids = dnet_ids_init(n, cfg->history_env, &id_num, cfg->storage_free);
208 if (!ids)
209 goto err_out_locks_destroy;
211 n->addr.addr_len = sizeof(n->addr.addr);
212 err = dnet_socket_create(n, cfg, &n->addr, 1);
213 if (err < 0)
214 goto err_out_ids_cleanup;
216 s = err;
217 dnet_setup_id(&n->id, cfg->group_id, ids[0].id);
219 n->st = dnet_state_create(n, cfg->group_id, ids, id_num, &n->addr, s, &err, DNET_JOIN, dnet_state_accept_process);
220 if (!n->st) {
221 close(s);
222 goto err_out_state_destroy;
225 free(ids);
226 ids = NULL;
228 err = dnet_srw_init(n, cfg);
229 if (err) {
230 dnet_log(n, DNET_LOG_ERROR, "srw: initialization failure: %s %d\n", strerror(-err), err);
234 dnet_log(n, DNET_LOG_DEBUG, "New server node has been created at %s, ids: %d.\n",
235 dnet_dump_node(n), id_num);
237 return n;
239 err_out_state_destroy:
240 dnet_srw_cleanup(n);
241 dnet_state_put(n->st);
242 err_out_ids_cleanup:
243 free(ids);
244 err_out_locks_destroy:
245 dnet_locks_destroy(n);
246 err_out_cache_cleanup:
247 dnet_cache_cleanup(n);
248 err_out_notify_exit:
249 dnet_notify_exit(n);
250 err_out_node_destroy:
251 dnet_node_destroy(n);
252 err_out_exit:
253 return NULL;
256 void dnet_server_node_destroy(struct dnet_node *n)
258 dnet_log(n, DNET_LOG_DEBUG, "Destroying server node at %s, st: %p.\n",
259 dnet_dump_node(n), n->st);
261 dnet_srw_cleanup(n);
263 dnet_node_cleanup_common_resources(n);
265 if (n->cb && n->cb->backend_cleanup)
266 n->cb->backend_cleanup(n->cb->command_private);
268 dnet_locks_destroy(n);
269 dnet_notify_exit(n);
271 free(n);