a93b84404eb91ec83d92e9449a5c897de7498c9c
[sliver-openvswitch.git] / ovsdb / trigger.c
1 /* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17
18 #include "trigger.h"
19
20 #include <assert.h>
21 #include <limits.h>
22
23 #include "json.h"
24 #include "jsonrpc.h"
25 #include "ovsdb.h"
26 #include "poll-loop.h"
27 #include "server.h"
28
29 static bool ovsdb_trigger_try(struct ovsdb_trigger *, long long int now);
30 static void ovsdb_trigger_complete(struct ovsdb_trigger *);
31
32 void
33 ovsdb_trigger_init(struct ovsdb_session *session, struct ovsdb *db,
34                    struct ovsdb_trigger *trigger,
35                    struct json *request, long long int now)
36 {
37     trigger->session = session;
38     trigger->db = db;
39     list_push_back(&trigger->db->triggers, &trigger->node);
40     trigger->request = request;
41     trigger->result = NULL;
42     trigger->created = now;
43     trigger->timeout_msec = LLONG_MAX;
44     ovsdb_trigger_try(trigger, now);
45 }
46
47 void
48 ovsdb_trigger_destroy(struct ovsdb_trigger *trigger)
49 {
50     list_remove(&trigger->node);
51     json_destroy(trigger->request);
52     json_destroy(trigger->result);
53 }
54
55 bool
56 ovsdb_trigger_is_complete(const struct ovsdb_trigger *trigger)
57 {
58     return trigger->result != NULL;
59 }
60
61 struct json *
62 ovsdb_trigger_steal_result(struct ovsdb_trigger *trigger)
63 {
64     struct json *result = trigger->result;
65     trigger->result = NULL;
66     return result;
67 }
68
69 void
70 ovsdb_trigger_run(struct ovsdb *db, long long int now)
71 {
72     struct ovsdb_trigger *t, *next;
73     bool run_triggers;
74
75     run_triggers = db->run_triggers;
76     db->run_triggers = false;
77     LIST_FOR_EACH_SAFE (t, next, node, &db->triggers) {
78         if (run_triggers || now - t->created >= t->timeout_msec) {
79             ovsdb_trigger_try(t, now);
80         }
81     }
82 }
83
84 void
85 ovsdb_trigger_wait(struct ovsdb *db, long long int now)
86 {
87     if (db->run_triggers) {
88         poll_immediate_wake();
89     } else {
90         long long int deadline = LLONG_MAX;
91         struct ovsdb_trigger *t;
92
93         LIST_FOR_EACH (t, node, &db->triggers) {
94             if (t->created < LLONG_MAX - t->timeout_msec) {
95                 long long int t_deadline = t->created + t->timeout_msec;
96                 if (deadline > t_deadline) {
97                     deadline = t_deadline;
98                     if (now >= deadline) {
99                         break;
100                     }
101                 }
102             }
103         }
104
105         if (deadline < LLONG_MAX) {
106             poll_timer_wait_until(deadline);
107         }
108     }
109 }
110
111 static bool
112 ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
113 {
114     t->result = ovsdb_execute(t->db, t->session,
115                               t->request, now - t->created, &t->timeout_msec);
116     if (t->result) {
117         ovsdb_trigger_complete(t);
118         return true;
119     } else {
120         return false;
121     }
122 }
123
124 static void
125 ovsdb_trigger_complete(struct ovsdb_trigger *t)
126 {
127     assert(t->result != NULL);
128     list_remove(&t->node);
129     list_push_back(&t->session->completions, &t->node);
130 }