]>
git.proxmox.com Git - mirror_ovs.git/blob - ovsdb/column.c
1 /* Copyright (c) 2009, 2010, 2011, 2016 Nicira, Inc.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "ovsdb/column.h"
23 #include "openvswitch/dynamic-string.h"
24 #include "openvswitch/json.h"
25 #include "ovsdb-error.h"
26 #include "ovsdb-parser.h"
31 ovsdb_column_create(const char *name
,
32 bool mutable, bool persistent
,
33 const struct ovsdb_type
*type
)
35 /* Doesn't set the new column's 'index': the caller must do that. */
36 struct ovsdb_column
*column
;
38 column
= xzalloc(sizeof *column
);
39 column
->name
= xstrdup(name
);
40 column
->mutable = mutable;
41 column
->persistent
= persistent
;
42 ovsdb_type_clone(&column
->type
, type
);
48 ovsdb_column_clone(const struct ovsdb_column
*old
)
50 /* Doesn't copy the column's 'index': the caller must do that. */
51 return ovsdb_column_create(old
->name
,
52 old
->mutable, old
->persistent
,
57 ovsdb_column_destroy(struct ovsdb_column
*column
)
59 ovsdb_type_destroy(&column
->type
);
65 ovsdb_column_from_json(const struct json
*json
, const char *name
,
66 struct ovsdb_column
**columnp
)
68 const struct json
*mutable_json
, *ephemeral
, *type_json
;
69 struct ovsdb_error
*error
;
70 struct ovsdb_type type
;
71 struct ovsdb_parser parser
;
75 ovsdb_parser_init(&parser
, json
, "schema for column %s", name
);
76 mutable_json
= ovsdb_parser_member(&parser
, "mutable",
77 OP_TRUE
| OP_FALSE
| OP_OPTIONAL
);
78 ephemeral
= ovsdb_parser_member(&parser
, "ephemeral",
79 OP_TRUE
| OP_FALSE
| OP_OPTIONAL
);
80 type_json
= ovsdb_parser_member(&parser
, "type", OP_STRING
| OP_OBJECT
);
81 error
= ovsdb_parser_finish(&parser
);
86 error
= ovsdb_type_from_json(&type
, type_json
);
91 bool mutable = !mutable_json
|| json_boolean(mutable_json
);
93 && (ovsdb_base_type_is_weak_ref(&type
.key
) ||
94 ovsdb_base_type_is_weak_ref(&type
.value
))) {
95 /* We cannot allow a weak reference to be immutable: if referenced rows
96 * are deleted, then the weak reference needs to change. */
100 bool persistent
= ephemeral
? !json_boolean(ephemeral
) : true;
101 *columnp
= ovsdb_column_create(name
, mutable, persistent
, &type
);
103 ovsdb_type_destroy(&type
);
109 ovsdb_column_to_json(const struct ovsdb_column
*column
)
111 struct json
*json
= json_object_create();
112 if (!column
->mutable) {
113 json_object_put(json
, "mutable", json_boolean_create(false));
115 if (!column
->persistent
) {
116 json_object_put(json
, "ephemeral", json_boolean_create(true));
118 json_object_put(json
, "type", ovsdb_type_to_json(&column
->type
));
123 ovsdb_column_set_init(struct ovsdb_column_set
*set
)
126 set
->n_columns
= set
->allocated_columns
= 0;
130 ovsdb_column_set_destroy(struct ovsdb_column_set
*set
)
136 ovsdb_column_set_clone(struct ovsdb_column_set
*new,
137 const struct ovsdb_column_set
*old
)
139 new->columns
= xmemdup(old
->columns
,
140 old
->n_columns
* sizeof *old
->columns
);
141 new->n_columns
= new->allocated_columns
= old
->n_columns
;
145 ovsdb_column_set_from_json(const struct json
*json
,
146 const struct ovsdb_table_schema
*schema
,
147 struct ovsdb_column_set
*set
)
149 ovsdb_column_set_init(set
);
151 struct shash_node
*node
;
153 SHASH_FOR_EACH (node
, &schema
->columns
) {
154 const struct ovsdb_column
*column
= node
->data
;
155 ovsdb_column_set_add(set
, column
);
160 struct ovsdb_error
*error
= NULL
;
163 if (json
->type
!= JSON_ARRAY
) {
167 /* XXX this is O(n**2) */
168 for (i
= 0; i
< json
->array
.n
; i
++) {
169 const struct ovsdb_column
*column
;
172 if (json
->array
.elems
[i
]->type
!= JSON_STRING
) {
176 s
= json
->array
.elems
[i
]->string
;
177 column
= shash_find_data(&schema
->columns
, s
);
179 error
= ovsdb_syntax_error(json
, NULL
, "%s is not a valid "
182 } else if (ovsdb_column_set_contains(set
, column
->index
)) {
185 ovsdb_column_set_add(set
, column
);
190 ovsdb_column_set_destroy(set
);
191 ovsdb_column_set_init(set
);
193 error
= ovsdb_syntax_error(json
, NULL
, "array of distinct column "
201 ovsdb_column_set_to_json(const struct ovsdb_column_set
*set
)
206 json
= json_array_create_empty();
207 for (i
= 0; i
< set
->n_columns
; i
++) {
208 json_array_add(json
, json_string_create(set
->columns
[i
]->name
));
213 /* Returns an English string listing the contents of 'set', e.g. "columns
214 * \"a\", \"b\", and \"c\"". The caller must free the string. */
216 ovsdb_column_set_to_string(const struct ovsdb_column_set
*set
)
218 if (!set
->n_columns
) {
219 return xstrdup("no columns");
225 ds_put_format(&s
, "column%s ", set
->n_columns
> 1 ? "s" : "");
226 for (i
= 0; i
< set
->n_columns
; i
++) {
227 const char *delimiter
= english_list_delimiter(i
, set
->n_columns
);
228 ds_put_format(&s
, "%s\"%s\"", delimiter
, set
->columns
[i
]->name
);
230 return ds_steal_cstr(&s
);
235 ovsdb_column_set_add(struct ovsdb_column_set
*set
,
236 const struct ovsdb_column
*column
)
238 if (set
->n_columns
>= set
->allocated_columns
) {
239 set
->columns
= x2nrealloc(set
->columns
, &set
->allocated_columns
,
240 sizeof *set
->columns
);
242 set
->columns
[set
->n_columns
++] = column
;
246 ovsdb_column_set_add_all(struct ovsdb_column_set
*set
,
247 const struct ovsdb_table
*table
)
249 struct shash_node
*node
;
251 SHASH_FOR_EACH (node
, &table
->schema
->columns
) {
252 const struct ovsdb_column
*column
= node
->data
;
253 ovsdb_column_set_add(set
, column
);
258 ovsdb_column_set_contains(const struct ovsdb_column_set
*set
,
259 unsigned int column_index
)
263 for (i
= 0; i
< set
->n_columns
; i
++) {
264 if (set
->columns
[i
]->index
== column_index
) {
271 /* This comparison is sensitive to ordering of columns within a set, but that's
272 * good: the only existing caller wants to make sure that hash values are
273 * comparable, which is only true if column ordering is the same. */
275 ovsdb_column_set_equals(const struct ovsdb_column_set
*a
,
276 const struct ovsdb_column_set
*b
)
280 if (a
->n_columns
!= b
->n_columns
) {
283 for (i
= 0; i
< a
->n_columns
; i
++) {
284 if (a
->columns
[i
] != b
->columns
[i
]) {