2 Copyright (C) 2010 Proxmox Server Solutions GmbH
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Author: Dietmar Maurer <dietmar@proxmox.com>
21 #define G_LOG_DOMAIN "confdb"
23 #define CLUSTER_KEY "cluster"
27 #endif /* HAVE_CONFIG_H */
35 #include <corosync/confdb.h>
37 #include "cfs-utils.h"
42 confdb_handle_t handle
;
48 confdb_handle_t handle
,
51 unsigned int default_value
)
55 size_t value_len
= sizeof(value
);
56 if (confdb_key_get(handle
, parent
, key
, strlen(key
),
57 value
, &value_len
) == CS_OK
) {
66 confdb_handle_t handle
,
69 const char *default_value
)
74 size_t value_len
= sizeof(value
);
75 if (confdb_key_get(handle
, parent
, key
, strlen(key
),
76 value
, &value_len
) == CS_OK
) {
77 return g_strdup(value
);
81 return g_strdup(default_value
);
87 cman_read_clusternodes(
88 confdb_handle_t handle
,
89 hdb_handle_t nodes_handle
,
94 result
= confdb_object_find_start(handle
, nodes_handle
);
95 if (result
!= CS_OK
) {
96 cfs_critical("confdb_object_find_start failed %d", result
);
100 hdb_handle_t obj_handle
= 0;
101 while((result
= confdb_object_find(handle
, nodes_handle
, "clusternode",
102 strlen("clusternode"), &obj_handle
)) == CS_OK
) {
103 uint32_t nodeid
= confdb_get_int(handle
, obj_handle
, "nodeid", 0);
104 uint32_t votes
= confdb_get_int(handle
, obj_handle
, "votes", 0);
105 char *name
= confdb_get_string(handle
, obj_handle
, "name", NULL
);
107 if (name
&& nodeid
) {
108 cfs_clnode_t
*clnode
= cfs_clnode_new(name
, nodeid
, votes
);
109 cfs_clinfo_add_node(clinfo
, clnode
);
115 if (result
== CS_ERR_ACCESS
)
118 confdb_object_find_destroy(handle
, nodes_handle
);
125 confdb_handle_t handle
,
126 hdb_handle_t cluster_parent_handle
)
131 uint32_t cman_version
= confdb_get_int(handle
, cluster_parent_handle
, "config_version", 0);
133 char *clustername
= confdb_get_string(handle
, cluster_parent_handle
, "name", "unknown");
135 cfs_clinfo_t
*clinfo
= cfs_clinfo_new(clustername
, cman_version
);
139 result
= confdb_object_find_start(handle
, cluster_parent_handle
);
140 if (result
!= CS_OK
) {
141 cfs_critical("confdb_object_find_start failed %d", result
);
142 cfs_clinfo_destroy(clinfo
);
146 hdb_handle_t nodes_handle
= 0;
147 result
= confdb_object_find(handle
, cluster_parent_handle
, "clusternodes",
148 strlen("clusternodes"), &nodes_handle
);
149 if (result
== CS_OK
) {
150 cman_read_clusternodes(handle
, nodes_handle
, clinfo
);
151 cfs_status_set_clinfo(clinfo
);
153 cfs_clinfo_destroy(clinfo
);
154 cfs_critical("cant find clusternodes object %d", result
);
157 confdb_object_find_destroy(handle
, cluster_parent_handle
);
163 cman_read_config(confdb_handle_t handle
)
167 result
= confdb_object_find_start(handle
, OBJECT_PARENT_HANDLE
);
168 if (result
!= CS_OK
) {
169 cfs_critical("confdb_object_find_start failed %d", result
);
173 hdb_handle_t cluster_parent_handle
= 0;
174 result
= confdb_object_find(handle
, OBJECT_PARENT_HANDLE
, CLUSTER_KEY
,
175 strlen(CLUSTER_KEY
), &cluster_parent_handle
);
176 if (result
== CS_OK
) {
177 result
= cman_read_cluster(handle
, cluster_parent_handle
);
179 cfs_critical("cant find cluster object %d", result
);
182 confdb_object_find_destroy(handle
, OBJECT_PARENT_HANDLE
);
188 track_object(confdb_handle_t handle
)
191 hdb_handle_t obj_handle
= 0;
194 result
= confdb_object_find_start(handle
, OBJECT_PARENT_HANDLE
);
195 if (result
!= CS_OK
) {
196 cfs_critical("confdb_object_find_start failed %d", result
);
200 result
= confdb_object_find(handle
, OBJECT_PARENT_HANDLE
, CLUSTER_KEY
,
201 strlen(CLUSTER_KEY
), &obj_handle
);
202 if (result
!= CS_OK
) {
203 cfs_critical("cant find cluster object %d", result
);
207 result
= confdb_object_find_destroy(handle
, OBJECT_PARENT_HANDLE
);
208 if (result
!= CS_OK
) {
209 cfs_critical("confdb_object_find_destroy failed %d", result
);
213 result
= confdb_track_changes(handle
, obj_handle
, CONFDB_TRACK_DEPTH_RECURSIVE
);
219 confdb_key_change_notify(
220 confdb_handle_t handle
,
221 confdb_change_type_t change_type
,
222 hdb_handle_t parent_object_handle
,
223 hdb_handle_t object_handle
,
224 const void *object_name
,
225 size_t object_name_len
,
226 const void *key_name
,
228 const void *key_value
,
229 size_t key_value_len
)
232 cs_private_t
*private = NULL
;
234 result
= confdb_context_get(handle
, (gconstpointer
*)&private);
235 if (result
!= CS_OK
|| !private) {
236 cfs_critical("confdb_context_get error: %d (%p)", result
, private);
240 private->changes
= TRUE
;
244 confdb_object_create_notify(
245 confdb_handle_t handle
,
246 hdb_handle_t parent_object_handle
,
247 hdb_handle_t object_handle
,
252 cs_private_t
*private = NULL
;
254 result
= confdb_context_get(handle
, (gconstpointer
*)&private);
255 if (result
!= CS_OK
|| !private) {
256 cfs_critical("confdb_context_get error: %d (%p)", result
, private);
260 private->changes
= TRUE
;
264 confdb_object_delete_notify(
265 confdb_handle_t handle
,
266 hdb_handle_t parent_object_handle
,
271 cs_private_t
*private = NULL
;
273 result
= confdb_context_get(handle
, (gconstpointer
*)&private);
274 if (result
!= CS_OK
|| !private) {
275 cfs_critical("confdb_context_get error: %d (%p)", result
, private);
279 if (name_len
== strlen(CLUSTER_KEY
) &&
280 !strncmp(name_pt
, CLUSTER_KEY
, name_len
))
281 track_object(handle
);
283 private->changes
= TRUE
;
286 /* this does not work with current corosync - seems a bug
287 * that is why we listen to delete/change/create events instead
290 confdb_reload_notify(
291 confdb_handle_t handle
,
292 confdb_reload_type_t type
)
296 cs_private_t
*private = NULL
;
298 result
= confdb_context_get(handle
, (gconstpointer
*)&private);
299 if (result
!= CS_OK
|| !private) {
300 cfs_critical("confdb_context_get error: %d (%p)", result
, private);
304 private->changes
= TRUE
;
307 static confdb_callbacks_t confdb_callbacks
= {
308 .confdb_key_change_notify_fn
= confdb_key_change_notify
,
309 .confdb_object_create_change_notify_fn
= confdb_object_create_notify
,
310 .confdb_object_delete_change_notify_fn
= confdb_object_delete_notify
,
311 .confdb_reload_notify_fn
= confdb_reload_notify
,
315 service_confdb_finalize(
316 cfs_service_t
*service
,
319 g_return_val_if_fail(service
!= NULL
, FALSE
);
320 g_return_val_if_fail(context
!= NULL
, FALSE
);
322 cs_private_t
*private = (cs_private_t
*)context
;
323 confdb_handle_t handle
= private->handle
;
327 result
= confdb_finalize(handle
);
329 if (result
!= CS_OK
) {
330 cfs_critical("confdb_finalize failed: %d", result
);
338 service_confdb_initialize(
339 cfs_service_t
*service
,
342 g_return_val_if_fail(service
!= NULL
, FALSE
);
343 g_return_val_if_fail(context
!= NULL
, FALSE
);
345 cs_private_t
*private = (cs_private_t
*)context
;
347 confdb_handle_t handle
= private->handle
;
350 if (!private->handle
) {
352 result
= confdb_initialize(&handle
, &confdb_callbacks
);
353 if (result
!= CS_OK
) {
354 cfs_critical("confdb_initialize failed: %d", result
);
359 result
= confdb_context_set(handle
, private);
360 if (result
!= CS_OK
) {
361 cfs_critical("confdb_context_set failed: %d", result
);
362 confdb_finalize(handle
);
367 private->handle
= handle
;
370 result
= track_object(handle
);
371 if (result
== CS_ERR_LIBRARY
|| result
== CS_ERR_BAD_HANDLE
) {
372 cfs_critical("confdb_track_changes failed: %d - closing handle", result
);
373 confdb_finalize(handle
);
376 } else if (result
!= CS_OK
) {
377 cfs_critical("confdb_track_changes failed: %d - trying again", result
);
382 if ((result
= confdb_fd_get(handle
, &confdb_fd
)) != CS_OK
) {
383 cfs_critical("confdb_fd_get failed %d - trying again", result
);
387 cman_read_config(handle
);
393 service_confdb_dispatch(
394 cfs_service_t
*service
,
397 g_return_val_if_fail(service
!= NULL
, FALSE
);
398 g_return_val_if_fail(context
!= NULL
, FALSE
);
400 cs_private_t
*private = (cs_private_t
*)context
;
401 confdb_handle_t handle
= private->handle
;
405 private->changes
= FALSE
;
408 result
= confdb_dispatch(handle
, CS_DISPATCH_ALL
);
409 if (result
== CS_ERR_TRY_AGAIN
) {
412 if ((retries
% 100) == 0)
413 cfs_message("confdb_dispatch retry %d", retries
);
418 if (result
== CS_OK
|| result
== CS_ERR_TRY_AGAIN
) {
420 if (private->changes
) {
421 result
= cman_read_config(handle
);
426 cfs_critical("confdb_dispatch failed: %d", result
);
429 confdb_finalize(handle
);
434 static cfs_service_callbacks_t cfs_confdb_callbacks
= {
435 .cfs_service_initialize_fn
= service_confdb_initialize
,
436 .cfs_service_finalize_fn
= service_confdb_finalize
,
437 .cfs_service_dispatch_fn
= service_confdb_dispatch
,
441 service_confdb_new(void)
443 cfs_service_t
*service
;
445 cs_private_t
*private = g_new0(cs_private_t
, 1);
449 service
= cfs_service_new(&cfs_confdb_callbacks
, G_LOG_DOMAIN
, private);
455 service_confdb_destroy(cfs_service_t
*service
)
457 g_return_if_fail(service
!= NULL
);
459 cs_private_t
*private =
460 (cs_private_t
*)cfs_service_get_context(service
);