]>
Commit | Line | Data |
---|---|---|
f85f8ebb BP |
1 | /* Copyright (c) 2009 Nicira Networks |
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 "ovsdb.h" | |
19 | ||
f85f8ebb BP |
20 | #include "json.h" |
21 | #include "ovsdb-error.h" | |
22 | #include "ovsdb-parser.h" | |
23 | #include "table.h" | |
24 | #include "transaction.h" | |
25 | ||
f85f8ebb BP |
26 | struct ovsdb_schema * |
27 | ovsdb_schema_create(const char *name, const char *comment) | |
28 | { | |
29 | struct ovsdb_schema *schema; | |
30 | ||
31 | schema = xzalloc(sizeof *schema); | |
32 | schema->name = xstrdup(name); | |
33 | schema->comment = comment ? xstrdup(comment) : NULL; | |
34 | shash_init(&schema->tables); | |
35 | ||
36 | return schema; | |
37 | } | |
38 | ||
39 | void | |
40 | ovsdb_schema_destroy(struct ovsdb_schema *schema) | |
41 | { | |
42 | struct shash_node *node; | |
43 | ||
44 | SHASH_FOR_EACH (node, &schema->tables) { | |
45 | ovsdb_table_schema_destroy(node->data); | |
46 | } | |
47 | shash_destroy(&schema->tables); | |
48 | free(schema->comment); | |
49 | free(schema->name); | |
50 | free(schema); | |
51 | } | |
52 | ||
53 | struct ovsdb_error * | |
54 | ovsdb_schema_from_file(const char *file_name, struct ovsdb_schema **schemap) | |
55 | { | |
56 | struct ovsdb_schema *schema; | |
57 | struct ovsdb_error *error; | |
58 | struct json *json; | |
59 | ||
60 | *schemap = NULL; | |
61 | json = json_from_file(file_name); | |
62 | if (json->type == JSON_STRING) { | |
63 | error = ovsdb_error("failed to read schema", | |
64 | "\"%s\" could not be read as JSON (%s)", | |
65 | file_name, json_string(json)); | |
66 | json_destroy(json); | |
67 | return error; | |
68 | } | |
69 | ||
70 | error = ovsdb_schema_from_json(json, &schema); | |
71 | if (error) { | |
72 | json_destroy(json); | |
73 | return ovsdb_wrap_error(error, | |
74 | "failed to parse \"%s\" as ovsdb schema", | |
75 | file_name); | |
76 | } | |
77 | ||
78 | *schemap = schema; | |
79 | return NULL; | |
80 | } | |
81 | ||
82 | struct ovsdb_error * | |
83 | ovsdb_schema_from_json(struct json *json, struct ovsdb_schema **schemap) | |
84 | { | |
85 | struct ovsdb_schema *schema; | |
86 | const struct json *name, *comment, *tables; | |
87 | struct ovsdb_error *error; | |
88 | struct shash_node *node; | |
89 | struct ovsdb_parser parser; | |
90 | ||
91 | *schemap = NULL; | |
92 | ||
93 | ovsdb_parser_init(&parser, json, "database schema"); | |
94 | name = ovsdb_parser_member(&parser, "name", OP_ID); | |
95 | comment = ovsdb_parser_member(&parser, "comment", OP_STRING | OP_OPTIONAL); | |
96 | tables = ovsdb_parser_member(&parser, "tables", OP_OBJECT); | |
97 | error = ovsdb_parser_finish(&parser); | |
98 | if (error) { | |
99 | return error; | |
100 | } | |
101 | ||
102 | schema = ovsdb_schema_create(json_string(name), | |
103 | comment ? json_string(comment) : NULL); | |
104 | SHASH_FOR_EACH (node, json_object(tables)) { | |
105 | struct ovsdb_table_schema *table; | |
106 | ||
107 | if (node->name[0] == '_') { | |
108 | error = ovsdb_syntax_error(json, NULL, "names beginning with " | |
109 | "\"_\" are reserved"); | |
b966380b BP |
110 | } else if (!ovsdb_parser_is_id(node->name)) { |
111 | error = ovsdb_syntax_error(json, NULL, "name must be a valid id"); | |
f85f8ebb BP |
112 | } else { |
113 | error = ovsdb_table_schema_from_json(node->data, node->name, | |
114 | &table); | |
115 | } | |
116 | if (error) { | |
117 | ovsdb_schema_destroy(schema); | |
118 | return error; | |
119 | } | |
120 | ||
121 | shash_add(&schema->tables, table->name, table); | |
122 | } | |
123 | *schemap = schema; | |
124 | return 0; | |
125 | } | |
126 | ||
127 | struct json * | |
128 | ovsdb_schema_to_json(const struct ovsdb_schema *schema) | |
129 | { | |
130 | struct json *json, *tables; | |
131 | struct shash_node *node; | |
132 | ||
133 | json = json_object_create(); | |
134 | json_object_put_string(json, "name", schema->name); | |
135 | if (schema->comment) { | |
136 | json_object_put_string(json, "comment", schema->comment); | |
137 | } | |
138 | ||
139 | tables = json_object_create(); | |
140 | ||
141 | SHASH_FOR_EACH (node, &schema->tables) { | |
142 | struct ovsdb_table_schema *table = node->data; | |
143 | json_object_put(tables, table->name, | |
144 | ovsdb_table_schema_to_json(table)); | |
145 | } | |
146 | json_object_put(json, "tables", tables); | |
147 | ||
148 | return json; | |
149 | } | |
150 | \f | |
151 | struct ovsdb * | |
bd06962a | 152 | ovsdb_create(struct ovsdb_schema *schema) |
f85f8ebb BP |
153 | { |
154 | struct shash_node *node; | |
155 | struct ovsdb *db; | |
156 | ||
157 | db = xmalloc(sizeof *db); | |
158 | db->schema = schema; | |
bd06962a | 159 | list_init(&db->replicas); |
f85f8ebb BP |
160 | list_init(&db->triggers); |
161 | db->run_triggers = false; | |
162 | ||
163 | shash_init(&db->tables); | |
164 | SHASH_FOR_EACH (node, &schema->tables) { | |
165 | struct ovsdb_table_schema *ts = node->data; | |
166 | shash_add(&db->tables, node->name, ovsdb_table_create(ts)); | |
167 | } | |
168 | ||
169 | return db; | |
170 | } | |
171 | ||
f85f8ebb BP |
172 | void |
173 | ovsdb_destroy(struct ovsdb *db) | |
174 | { | |
175 | if (db) { | |
176 | struct shash_node *node; | |
177 | ||
bd06962a BP |
178 | /* Remove all the replicas. */ |
179 | while (!list_is_empty(&db->replicas)) { | |
180 | struct ovsdb_replica *r | |
181 | = CONTAINER_OF(list_pop_back(&db->replicas), | |
182 | struct ovsdb_replica, node); | |
183 | ovsdb_remove_replica(db, r); | |
184 | } | |
185 | ||
f85f8ebb BP |
186 | /* Delete all the tables. This also deletes their schemas. */ |
187 | SHASH_FOR_EACH (node, &db->tables) { | |
188 | struct ovsdb_table *table = node->data; | |
189 | ovsdb_table_destroy(table); | |
190 | } | |
191 | shash_destroy(&db->tables); | |
192 | ||
1248fcd2 BP |
193 | /* The schemas, but not the table that points to them, were deleted in |
194 | * the previous step, so we need to clear out the table. We can't | |
195 | * destroy the table, because ovsdb_schema_destroy() will do that. */ | |
196 | shash_clear(&db->schema->tables); | |
f85f8ebb BP |
197 | |
198 | ovsdb_schema_destroy(db->schema); | |
f85f8ebb BP |
199 | free(db); |
200 | } | |
201 | } | |
202 | ||
203 | struct ovsdb_table * | |
204 | ovsdb_get_table(const struct ovsdb *db, const char *name) | |
205 | { | |
206 | return shash_find_data(&db->tables, name); | |
207 | } | |
bd06962a BP |
208 | \f |
209 | void | |
210 | ovsdb_replica_init(struct ovsdb_replica *r, | |
211 | const struct ovsdb_replica_class *class) | |
212 | { | |
213 | r->class = class; | |
214 | } | |
215 | ||
216 | void | |
217 | ovsdb_add_replica(struct ovsdb *db, struct ovsdb_replica *r) | |
218 | { | |
219 | list_push_back(&db->replicas, &r->node); | |
220 | } | |
221 | ||
222 | void | |
223 | ovsdb_remove_replica(struct ovsdb *db UNUSED, struct ovsdb_replica *r) | |
224 | { | |
225 | list_remove(&r->node); | |
226 | (r->class->destroy)(r); | |
227 | } |