1 /*
2 * Copyright (c) 2015-2017 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include "qnet-config.h"
36 #include "qdevice-log.h"
37 #include "qdevice-net-cast-vote-timer.h"
38 #include "qdevice-votequorum.h"
39
40 static int
qdevice_net_cast_vote_timer_callback(void * data1,void * data2)41 qdevice_net_cast_vote_timer_callback(void *data1, void *data2)
42 {
43 struct qdevice_net_instance *instance;
44 int cast_vote;
45 int case_processed;
46
47 instance = (struct qdevice_net_instance *)data1;
48
49 if (instance->cast_vote_timer_paused) {
50 return (-1);
51 }
52
53 case_processed = 0;
54
55 switch (instance->cast_vote_timer_vote) {
56 case TLV_VOTE_ACK:
57 case_processed = 1;
58 cast_vote = 1;
59 break;
60 case TLV_VOTE_NACK:
61 case_processed = 1;
62 cast_vote = 0;
63 break;
64 case TLV_VOTE_ASK_LATER:
65 case TLV_VOTE_WAIT_FOR_REPLY:
66 case TLV_VOTE_NO_CHANGE:
67 case TLV_VOTE_UNDEFINED:
68 /*
69 * Shouldn't happen
70 */
71 break;
72 /*
73 * Default is not defined intentionally. Compiler shows warning when
74 * new tlv_vote is added.
75 */
76 }
77
78 if (!case_processed) {
79 qdevice_log(LOG_CRIT, "qdevice_net_timer_cast_vote: Unhandled cast_vote_timer_vote %u\n",
80 instance->cast_vote_timer_vote);
81 exit(1);
82 }
83
84 if (qdevice_votequorum_poll(instance->qdevice_instance_ptr, cast_vote) != 0) {
85 instance->disconnect_reason = QDEVICE_NET_DISCONNECT_REASON_CANT_SCHEDULE_VOTING_TIMER;
86 instance->schedule_disconnect = 1;
87 instance->cast_vote_timer = NULL;
88 return (0);
89 }
90
91 /*
92 * Schedule this function callback again
93 */
94 return (-1);
95 }
96
97 int
qdevice_net_cast_vote_timer_update(struct qdevice_net_instance * instance,enum tlv_vote vote)98 qdevice_net_cast_vote_timer_update(struct qdevice_net_instance *instance, enum tlv_vote vote)
99 {
100 int timer_needs_running;
101 int case_processed;
102
103 case_processed = 0;
104
105 switch (vote) {
106 case TLV_VOTE_UNDEFINED:
107 break;
108 case TLV_VOTE_ACK:
109 case TLV_VOTE_NACK:
110 case_processed = 1;
111 timer_needs_running = 1;
112 break;
113 case TLV_VOTE_WAIT_FOR_REPLY:
114 case TLV_VOTE_ASK_LATER:
115 case_processed = 1;
116 timer_needs_running = 0;
117 break;
118 case TLV_VOTE_NO_CHANGE:
119 case_processed = 1;
120 return (0);
121
122 break;
123 /*
124 * Default is not defined intentionally. Compiler shows warning when
125 * new tlv_vote is added.
126 */
127 }
128
129 if (!case_processed) {
130 qdevice_log(LOG_CRIT, "qdevice_net_cast_vote_timer_update_vote: Unhandled vote parameter %u\n",
131 vote);
132 exit(1);
133 }
134
135 instance->cast_vote_timer_vote = vote;
136
137 if (timer_needs_running) {
138 if (instance->cast_vote_timer == NULL) {
139 instance->cast_vote_timer = timer_list_add(&instance->main_timer_list,
140 instance->cast_vote_timer_interval,
141 qdevice_net_cast_vote_timer_callback, (void *)instance, NULL);
142
143 if (instance->cast_vote_timer == NULL) {
144 qdevice_log(LOG_ERR, "Can't schedule sending of "
145 "votequorum poll");
146
147 return (-1);
148 } else {
149 qdevice_log(LOG_DEBUG, "Cast vote timer is now scheduled every "
150 "%"PRIu32"ms voting %s.", instance->cast_vote_timer_interval,
151 tlv_vote_to_str(instance->cast_vote_timer_vote));
152 }
153 } else {
154 qdevice_log(LOG_DEBUG, "Cast vote timer remains scheduled every "
155 "%"PRIu32"ms voting %s.", instance->cast_vote_timer_interval,
156 tlv_vote_to_str(instance->cast_vote_timer_vote));
157 }
158
159 if (qdevice_net_cast_vote_timer_callback((void *)instance, NULL) != -1) {
160 return (-1);
161 }
162 } else {
163 if (instance->cast_vote_timer != NULL) {
164 timer_list_delete(&instance->main_timer_list, instance->cast_vote_timer);
165 instance->cast_vote_timer = NULL;
166 qdevice_log(LOG_DEBUG, "Cast vote timer is now stopped.");
167 } else {
168 qdevice_log(LOG_DEBUG, "Cast vote timer remains stopped.");
169 }
170 }
171
172 return (0);
173 }
174
175 void
qdevice_net_cast_vote_timer_set_paused(struct qdevice_net_instance * instance,int paused)176 qdevice_net_cast_vote_timer_set_paused(struct qdevice_net_instance *instance, int paused)
177 {
178
179 if (paused != instance->cast_vote_timer_paused) {
180 instance->cast_vote_timer_paused = paused;
181
182 if (instance->cast_vote_timer_paused) {
183 qdevice_log(LOG_DEBUG, "Cast vote timer is now paused.");
184 } else {
185 qdevice_log(LOG_DEBUG, "Cast vote timer is no longer paused.");
186 }
187 }
188 }
189