]> git.proxmox.com Git - pve-cluster.git/blame - data/src/quorum.c
update to debian jessie
[pve-cluster.git] / data / src / quorum.c
CommitLineData
fe000966
DM
1/*
2 Copyright (C) 2010 Proxmox Server Solutions GmbH
3
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.
8
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.
13
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/>.
16
17 Author: Dietmar Maurer <dietmar@proxmox.com>
18
19*/
20
21#define G_LOG_DOMAIN "quorum"
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif /* HAVE_CONFIG_H */
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <unistd.h>
31#include <glib.h>
32
33#include <corosync/quorum.h>
34
35#include "cfs-utils.h"
36#include "loop.h"
37#include "status.h"
38
39typedef struct {
40 quorum_handle_t handle;
41} qs_private_t;
42
43static void quorum_notification_fn(
44 quorum_handle_t handle,
45 uint32_t quorate,
46 uint64_t ring_id,
47 uint32_t view_list_entries,
48 uint32_t *view_list)
49{
50 cs_error_t result;
51
52 cfs_debug("quorum notification called, quorate = %d, "
53 "number of nodes = %d", quorate, view_list_entries);
54
55 qs_private_t *private = NULL;
56
57 result = quorum_context_get(handle, (gconstpointer *)&private);
58 if (result != CS_OK || !private) {
59 cfs_critical("quorum_context_get error: %d (%p)", result, private);
60 return;
61 }
62
63 cfs_set_quorate(quorate, FALSE);
64}
65
66static quorum_callbacks_t quorum_callbacks = {
67 .quorum_notify_fn = quorum_notification_fn,
68};
69
70static gboolean service_quorum_finalize(
71 cfs_service_t *service,
72 gpointer context)
73{
74 g_return_val_if_fail(service != NULL, FALSE);
75 g_return_val_if_fail(context != NULL, FALSE);
76
77 qs_private_t *private = (qs_private_t *)context;
78 quorum_handle_t handle = private->handle;
79
80 cs_error_t result;
81
82 cfs_set_quorate(0, TRUE);
83
84 result = quorum_finalize(handle);
85 private->handle = 0;
86 if (result != CS_OK) {
87 cfs_critical("quorum_finalize failed: %d", result);
88 return FALSE;
89 }
90
91 return TRUE;
92}
93
94static int service_quorum_initialize(
95 cfs_service_t *service,
96 gpointer context)
97{
98 g_return_val_if_fail(service != NULL, FALSE);
99 g_return_val_if_fail(context != NULL, FALSE);
100
101 qs_private_t *private = (qs_private_t *)context;
102
103 quorum_handle_t handle = private->handle;
104 cs_error_t result;
105
106 if (!private->handle) {
89fde9ac
DM
107
108 uint32_t quorum_type;
109
110 result = quorum_initialize(&handle, &quorum_callbacks, &quorum_type);
111 if (result != CS_OK) {
112 cfs_critical("quorum_initialize failed: %d", result);
113 private->handle = 0;
114 return -1;
115 }
fe000966 116
89fde9ac
DM
117 if (quorum_type != QUORUM_SET) {
118 cfs_critical("quorum_initialize returned wron quorum_type: %d", quorum_type);
119 quorum_finalize(handle);
fe000966
DM
120 private->handle = 0;
121 return -1;
122 }
123
124 result = quorum_context_set(handle, private);
125 if (result != CS_OK) {
126 cfs_critical("quorum_context_set failed: %d", result);
127 quorum_finalize(handle);
128 private->handle = 0;
129 return -1;
130 }
131
132 private->handle = handle;
133 }
134
135
136 result = quorum_trackstart(handle, CS_TRACK_CHANGES);
137 if (result == CS_ERR_LIBRARY || result == CS_ERR_BAD_HANDLE) {
138 cfs_critical("quorum_trackstart failed: %d - closing handle", result);
139 quorum_finalize(handle);
140 private->handle = 0;
141 return -1;
142 } else if (result != CS_OK) {
143 cfs_critical("quorum_trackstart failed: %d - trying again", result);
144 return -1;
145 }
146
147 int quorum_fd = -1;
148 if ((result = quorum_fd_get(handle, &quorum_fd)) != CS_OK) {
149 cfs_critical("quorum_fd_get failed %d - trying again", result);
150 return -1;
151 }
152
153 return quorum_fd;
154}
155
156static gboolean service_quorum_dispatch(
157 cfs_service_t *service,
158 gpointer context)
159{
160 g_return_val_if_fail(service != NULL, FALSE);
161 g_return_val_if_fail(context != NULL, FALSE);
162
163 qs_private_t *private = (qs_private_t *)context;
164 quorum_handle_t handle = private->handle;
165
166 cs_error_t result;
167
168 int retries = 0;
169loop:
89fde9ac
DM
170 result = quorum_dispatch(handle, CS_DISPATCH_ALL);
171 if (result == CS_ERR_TRY_AGAIN) {
fe000966
DM
172 usleep(100000);
173 ++retries;
174 if ((retries % 100) == 0)
175 cfs_message("quorum_dispatch retry %d", retries);
176 goto loop;
177 }
178
179
180 if (result == CS_OK || result == CS_ERR_TRY_AGAIN)
181 return TRUE;
182
183 cfs_critical("quorum_dispatch failed: %d", result);
184
185 quorum_finalize(handle);
186 private->handle = 0;
187 return FALSE;
188}
189
190static cfs_service_callbacks_t cfs_quorum_callbacks = {
191 .cfs_service_initialize_fn = service_quorum_initialize,
192 .cfs_service_finalize_fn = service_quorum_finalize,
193 .cfs_service_dispatch_fn = service_quorum_dispatch,
194};
195
196cfs_service_t *service_quorum_new(void)
197{
198 cfs_service_t *service;
199
200 qs_private_t *private = g_new0(qs_private_t, 1);
201 if (!private)
202 return NULL;
203
204 service = cfs_service_new(&cfs_quorum_callbacks, G_LOG_DOMAIN, private);
205
206 return service;
207}
208
209void service_quorum_destroy(cfs_service_t *service)
210{
211 g_return_if_fail(service != NULL);
212
213 qs_private_t *private =
214 (qs_private_t *)cfs_service_get_context(service);
215
216 g_free(private);
217 g_free(service);
218}