]>
Commit | Line | Data |
---|---|---|
bd76d25d | 1 | /* Copyright (c) 2009, 2010 Nicira Networks |
f85f8ebb BP |
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 "table.h" | |
19 | ||
20 | #include <assert.h> | |
87ab878c | 21 | #include <limits.h> |
f85f8ebb BP |
22 | |
23 | #include "json.h" | |
24 | #include "column.h" | |
25 | #include "ovsdb-error.h" | |
26 | #include "ovsdb-parser.h" | |
27 | #include "ovsdb-types.h" | |
28 | #include "row.h" | |
29 | ||
30 | static void | |
31 | add_column(struct ovsdb_table_schema *ts, struct ovsdb_column *column) | |
32 | { | |
33 | assert(!shash_find(&ts->columns, column->name)); | |
34 | column->index = shash_count(&ts->columns); | |
35 | shash_add(&ts->columns, column->name, column); | |
36 | } | |
37 | ||
38 | struct ovsdb_table_schema * | |
87ab878c BP |
39 | ovsdb_table_schema_create(const char *name, bool mutable, |
40 | unsigned int max_rows) | |
f85f8ebb BP |
41 | { |
42 | struct ovsdb_column *uuid, *version; | |
43 | struct ovsdb_table_schema *ts; | |
44 | ||
45 | ts = xzalloc(sizeof *ts); | |
46 | ts->name = xstrdup(name); | |
f85f8ebb BP |
47 | ts->mutable = mutable; |
48 | shash_init(&ts->columns); | |
87ab878c | 49 | ts->max_rows = max_rows; |
f85f8ebb | 50 | |
2e57b537 | 51 | uuid = ovsdb_column_create("_uuid", false, true, &ovsdb_type_uuid); |
f85f8ebb BP |
52 | add_column(ts, uuid); |
53 | assert(uuid->index == OVSDB_COL_UUID); | |
54 | ||
2e57b537 | 55 | version = ovsdb_column_create("_version", false, false, &ovsdb_type_uuid); |
f85f8ebb BP |
56 | add_column(ts, version); |
57 | assert(version->index == OVSDB_COL_VERSION); | |
58 | ||
59 | return ts; | |
60 | } | |
61 | ||
58985e09 BP |
62 | struct ovsdb_table_schema * |
63 | ovsdb_table_schema_clone(const struct ovsdb_table_schema *old) | |
64 | { | |
65 | struct ovsdb_table_schema *new; | |
66 | struct shash_node *node; | |
67 | ||
87ab878c | 68 | new = ovsdb_table_schema_create(old->name, old->mutable, old->max_rows); |
58985e09 BP |
69 | SHASH_FOR_EACH (node, &old->columns) { |
70 | const struct ovsdb_column *column = node->data; | |
71 | ||
72 | if (column->name[0] == '_') { | |
73 | /* Added automatically by ovsdb_table_schema_create(). */ | |
74 | continue; | |
75 | } | |
76 | ||
77 | add_column(new, ovsdb_column_clone(column)); | |
78 | } | |
79 | return new; | |
80 | } | |
81 | ||
f85f8ebb BP |
82 | void |
83 | ovsdb_table_schema_destroy(struct ovsdb_table_schema *ts) | |
84 | { | |
85 | struct shash_node *node; | |
86 | ||
87 | SHASH_FOR_EACH (node, &ts->columns) { | |
88 | ovsdb_column_destroy(node->data); | |
89 | } | |
90 | shash_destroy(&ts->columns); | |
f85f8ebb BP |
91 | free(ts->name); |
92 | free(ts); | |
93 | } | |
94 | ||
95 | struct ovsdb_error * | |
96 | ovsdb_table_schema_from_json(const struct json *json, const char *name, | |
97 | struct ovsdb_table_schema **tsp) | |
98 | { | |
99 | struct ovsdb_table_schema *ts; | |
87ab878c | 100 | const struct json *columns, *mutable, *max_rows; |
f85f8ebb BP |
101 | struct shash_node *node; |
102 | struct ovsdb_parser parser; | |
103 | struct ovsdb_error *error; | |
87ab878c | 104 | long long int n_max_rows; |
f85f8ebb BP |
105 | |
106 | *tsp = NULL; | |
107 | ||
108 | ovsdb_parser_init(&parser, json, "table schema for table %s", name); | |
f85f8ebb BP |
109 | columns = ovsdb_parser_member(&parser, "columns", OP_OBJECT); |
110 | mutable = ovsdb_parser_member(&parser, "mutable", | |
111 | OP_TRUE | OP_FALSE | OP_OPTIONAL); | |
87ab878c BP |
112 | max_rows = ovsdb_parser_member(&parser, "maxRows", |
113 | OP_INTEGER | OP_OPTIONAL); | |
f85f8ebb BP |
114 | error = ovsdb_parser_finish(&parser); |
115 | if (error) { | |
116 | return error; | |
117 | } | |
118 | ||
87ab878c BP |
119 | if (max_rows) { |
120 | if (json_integer(max_rows) <= 0) { | |
121 | return ovsdb_syntax_error(json, NULL, | |
122 | "maxRows must be at least 1"); | |
123 | } | |
124 | n_max_rows = max_rows->u.integer; | |
125 | } else { | |
126 | n_max_rows = UINT_MAX; | |
127 | } | |
128 | ||
f85f8ebb BP |
129 | if (shash_is_empty(json_object(columns))) { |
130 | return ovsdb_syntax_error(json, NULL, | |
131 | "table must have at least one column"); | |
132 | } | |
133 | ||
134 | ts = ovsdb_table_schema_create(name, | |
87ab878c BP |
135 | mutable ? json_boolean(mutable) : true, |
136 | MIN(n_max_rows, UINT_MAX)); | |
f85f8ebb BP |
137 | SHASH_FOR_EACH (node, json_object(columns)) { |
138 | struct ovsdb_column *column; | |
139 | ||
140 | if (node->name[0] == '_') { | |
141 | error = ovsdb_syntax_error(json, NULL, "names beginning with " | |
142 | "\"_\" are reserved"); | |
b966380b BP |
143 | } else if (!ovsdb_parser_is_id(node->name)) { |
144 | error = ovsdb_syntax_error(json, NULL, "name must be a valid id"); | |
f85f8ebb BP |
145 | } else { |
146 | error = ovsdb_column_from_json(node->data, node->name, &column); | |
147 | } | |
148 | if (error) { | |
149 | ovsdb_table_schema_destroy(ts); | |
150 | return error; | |
151 | } | |
152 | ||
153 | add_column(ts, column); | |
154 | } | |
155 | *tsp = ts; | |
156 | return 0; | |
157 | } | |
158 | ||
159 | struct json * | |
160 | ovsdb_table_schema_to_json(const struct ovsdb_table_schema *ts) | |
161 | { | |
162 | struct json *json, *columns; | |
163 | struct shash_node *node; | |
164 | ||
165 | json = json_object_create(); | |
f85f8ebb BP |
166 | if (!ts->mutable) { |
167 | json_object_put(json, "mutable", json_boolean_create(false)); | |
168 | } | |
169 | ||
170 | columns = json_object_create(); | |
171 | ||
172 | SHASH_FOR_EACH (node, &ts->columns) { | |
bd76d25d | 173 | const struct ovsdb_column *column = node->data; |
f85f8ebb BP |
174 | if (node->name[0] != '_') { |
175 | json_object_put(columns, column->name, | |
176 | ovsdb_column_to_json(column)); | |
177 | } | |
178 | } | |
179 | json_object_put(json, "columns", columns); | |
87ab878c BP |
180 | if (ts->max_rows != UINT_MAX) { |
181 | json_object_put(json, "maxRows", json_integer_create(ts->max_rows)); | |
182 | } | |
f85f8ebb BP |
183 | |
184 | return json; | |
185 | } | |
186 | ||
187 | const struct ovsdb_column * | |
188 | ovsdb_table_schema_get_column(const struct ovsdb_table_schema *ts, | |
189 | const char *name) | |
190 | { | |
191 | return shash_find_data(&ts->columns, name); | |
192 | } | |
193 | \f | |
194 | struct ovsdb_table * | |
195 | ovsdb_table_create(struct ovsdb_table_schema *ts) | |
196 | { | |
197 | struct ovsdb_table *table; | |
198 | ||
199 | table = xmalloc(sizeof *table); | |
200 | table->schema = ts; | |
71c93bd4 | 201 | table->txn_table = NULL; |
f85f8ebb BP |
202 | hmap_init(&table->rows); |
203 | ||
204 | return table; | |
205 | } | |
206 | ||
207 | void | |
208 | ovsdb_table_destroy(struct ovsdb_table *table) | |
209 | { | |
210 | if (table) { | |
211 | struct ovsdb_row *row, *next; | |
212 | ||
213 | HMAP_FOR_EACH_SAFE (row, next, struct ovsdb_row, hmap_node, | |
214 | &table->rows) { | |
215 | ovsdb_row_destroy(row); | |
216 | } | |
217 | hmap_destroy(&table->rows); | |
218 | ||
219 | ovsdb_table_schema_destroy(table->schema); | |
220 | free(table); | |
221 | } | |
222 | } | |
223 | ||
629cd2f1 BP |
224 | const struct ovsdb_row * |
225 | ovsdb_table_get_row(const struct ovsdb_table *table, const struct uuid *uuid) | |
f85f8ebb BP |
226 | { |
227 | struct ovsdb_row *row; | |
228 | ||
629cd2f1 | 229 | HMAP_FOR_EACH_WITH_HASH (row, struct ovsdb_row, hmap_node, uuid_hash(uuid), |
f85f8ebb BP |
230 | &table->rows) { |
231 | if (uuid_equals(ovsdb_row_get_uuid(row), uuid)) { | |
232 | return row; | |
233 | } | |
234 | } | |
235 | ||
236 | return NULL; | |
237 | } | |
238 | ||
f85f8ebb BP |
239 | /* This is probably not the function you want. Use ovsdb_txn_row_modify() |
240 | * instead. */ | |
241 | bool | |
242 | ovsdb_table_put_row(struct ovsdb_table *table, struct ovsdb_row *row) | |
243 | { | |
244 | const struct uuid *uuid = ovsdb_row_get_uuid(row); | |
629cd2f1 BP |
245 | if (!ovsdb_table_get_row(table, uuid)) { |
246 | hmap_insert(&table->rows, &row->hmap_node, uuid_hash(uuid)); | |
f85f8ebb BP |
247 | return true; |
248 | } else { | |
249 | return false; | |
250 | } | |
251 | } |