properly handle ladishd crashes
[ladish.git] / daemon / cqueue.c
blobf1f0519b4e341718e80cb6e8b90182f20c16b0be
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains interface to the command queue
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "cmd.h"
29 void ladish_cqueue_init(struct ladish_cqueue * queue_ptr)
31 queue_ptr->cancel = false;
32 INIT_LIST_HEAD(&queue_ptr->queue);
35 void ladish_cqueue_run(struct ladish_cqueue * queue_ptr)
37 struct list_head * node_ptr;
38 struct ladish_command * cmd_ptr;
40 loop:
41 if (list_empty(&queue_ptr->queue))
43 return;
46 node_ptr = queue_ptr->queue.next;
47 cmd_ptr = list_entry(node_ptr, struct ladish_command, siblings);
49 ASSERT(cmd_ptr->run != NULL);
50 ASSERT(cmd_ptr->state == LADISH_COMMAND_STATE_PENDING || cmd_ptr->state == LADISH_COMMAND_STATE_WAITING);
52 if (cmd_ptr->state == LADISH_COMMAND_STATE_PENDING)
53 { /* if this is a new command, put a separator so its impact is clearly visible in the log */
54 log_info("-------");
57 if (!cmd_ptr->run(cmd_ptr->context))
59 ladish_cqueue_clear(queue_ptr);
60 return;
63 switch (cmd_ptr->state)
65 case LADISH_COMMAND_STATE_DONE:
66 break;
67 case LADISH_COMMAND_STATE_WAITING:
68 return;
69 default:
70 log_error("unexpected cmd state %u after run()", cmd_ptr->state);
71 ASSERT_NO_PASS;
72 ladish_cqueue_clear(queue_ptr);
73 return;
76 list_del(node_ptr);
78 if (cmd_ptr->destructor != NULL)
80 cmd_ptr->destructor(cmd_ptr->context);
83 free(cmd_ptr);
85 if (queue_ptr->cancel && list_empty(&queue_ptr->queue));
87 queue_ptr->cancel = false;
90 goto loop;
93 void ladish_cqueue_cancel(struct ladish_cqueue * queue_ptr)
95 struct list_head * node_ptr;
96 struct ladish_command * cmd_ptr;
98 if (list_empty(&queue_ptr->queue))
99 { /* nothing to cancel */
100 return;
103 node_ptr = queue_ptr->queue.next; /* current command */
104 cmd_ptr = list_entry(node_ptr, struct ladish_command, siblings);
105 if (cmd_ptr->state != LADISH_COMMAND_STATE_WAITING)
107 ladish_cqueue_clear(queue_ptr);
108 return;
111 /* clear all commands except currently waiting one */
112 while (queue_ptr->queue.next != queue_ptr->queue.prev)
114 node_ptr = queue_ptr->queue.prev;
115 list_del(node_ptr);
117 cmd_ptr = list_entry(node_ptr, struct ladish_command, siblings);
119 if (cmd_ptr->destructor != NULL)
121 cmd_ptr->destructor(cmd_ptr->context);
124 free(cmd_ptr);
127 queue_ptr->cancel = true;
128 cmd_ptr->cancel = true;
131 bool ladish_cqueue_add_command(struct ladish_cqueue * queue_ptr, struct ladish_command * cmd_ptr)
133 ASSERT(cmd_ptr->run != NULL);
135 if (queue_ptr->cancel)
137 return false;
140 ASSERT(cmd_ptr->state == LADISH_COMMAND_STATE_PREPARE);
141 cmd_ptr->state = LADISH_COMMAND_STATE_PENDING;
143 list_add_tail(&cmd_ptr->siblings, &queue_ptr->queue);
144 return true;
147 void ladish_cqueue_clear(struct ladish_cqueue * queue_ptr)
149 struct list_head * node_ptr;
150 struct ladish_command * cmd_ptr;
152 while (!list_empty(&queue_ptr->queue))
154 node_ptr = queue_ptr->queue.next;
155 list_del(node_ptr);
157 cmd_ptr = list_entry(node_ptr, struct ladish_command, siblings);
159 if (cmd_ptr->destructor != NULL)
161 cmd_ptr->destructor(cmd_ptr->context);
164 free(cmd_ptr);
167 queue_ptr->cancel = false;
170 void ladish_cqueue_drop_command(struct ladish_cqueue * queue_ptr)
172 struct list_head * node_ptr;
173 struct ladish_command * cmd_ptr;
175 ASSERT(!list_empty(&queue_ptr->queue)); /* there is nothing to drop */
177 /* remove the last command from the queue */
178 node_ptr = queue_ptr->queue.prev;
179 list_del(node_ptr);
180 cmd_ptr = list_entry(node_ptr, struct ladish_command, siblings);
182 ASSERT(cmd_ptr->run != NULL);
184 /* waiting commands are not supposed to be dropped */
185 /* commands that are not yet prepared and those that are already processed are not supposed to be in the queue */
186 ASSERT(cmd_ptr->state == LADISH_COMMAND_STATE_PENDING);
188 if (cmd_ptr->destructor != NULL)
190 cmd_ptr->destructor(cmd_ptr->context);
193 free(cmd_ptr);
196 void * ladish_command_new(size_t size)
198 struct ladish_command * cmd_ptr;
200 ASSERT(size >= sizeof(struct ladish_command));
202 cmd_ptr = malloc(size);
203 if (cmd_ptr == NULL)
205 log_error("malloc failed to allocate command with size %zu", size);
206 return NULL;
209 cmd_ptr->state = LADISH_COMMAND_STATE_PREPARE;
210 cmd_ptr->cancel = false;
212 cmd_ptr->context = cmd_ptr;
213 cmd_ptr->run = NULL;
214 cmd_ptr->destructor = NULL;
216 return cmd_ptr;