Code

a489a665c57ece9d19254611b8ae0832e10b168b
[sysdb.git] / src / core / memstore_exec.c
1 /*
2  * SysDB - src/core/memstore_exec.c
3  * Copyright (C) 2014-2015 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #include "core/object.h"
29 #include "core/plugin.h"
30 #include "core/memstore-private.h"
31 #include "frontend/connection.h"
32 #include "parser/ast.h"
33 #include "utils/error.h"
35 #include <errno.h>
37 #include <arpa/inet.h>
38 #include <stdlib.h>
39 #include <string.h>
41 /*
42  * private helper functions
43  */
45 typedef struct {
46         sdb_memstore_obj_t *current_host;
48         sdb_store_writer_t *w;
49         sdb_object_t *wd;
50 } iter_t;
52 static int
53 maybe_emit_host(iter_t *iter, sdb_memstore_obj_t *obj)
54 {
55         if ((obj->type == SDB_HOST) || (obj->type == SDB_ATTRIBUTE))
56                 return 0;
57         if (iter->current_host == obj->parent)
58                 return 0;
59         iter->current_host = obj->parent;
60         return sdb_memstore_emit(obj->parent, iter->w, iter->wd);
61 } /* maybe_emit_host */
63 static int
64 list_tojson(sdb_memstore_obj_t *obj,
65                 sdb_memstore_matcher_t __attribute__((unused)) *filter,
66                 void *user_data)
67 {
68         iter_t *iter = user_data;
69         maybe_emit_host(iter, obj);
70         return sdb_memstore_emit(obj, iter->w, iter->wd);
71 } /* list_tojson */
73 static int
74 lookup_tojson(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter,
75                 void *user_data)
76 {
77         iter_t *iter = user_data;
78         maybe_emit_host(iter, obj);
79         return sdb_memstore_emit_full(obj, filter, iter->w, iter->wd);
80 } /* lookup_tojson */
82 /*
83  * query implementations
84  */
86 static int
87 exec_fetch(sdb_memstore_t *store,
88                 sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf,
89                 int type, const char *hostname, int parent_type, const char *parent,
90                 const char *name, bool full, sdb_memstore_matcher_t *filter)
91 {
92         sdb_memstore_obj_t *host, *p = NULL, *obj;
93         int status = 0;
95         if (type == SDB_HOST)
96                 hostname = name;
98         host = sdb_memstore_get_host(store, hostname);
99         if ((! host)
100                         || (filter && (! sdb_memstore_matcher_matches(filter, host, NULL)))) {
101                 sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s: "
102                                 "host %s not found", SDB_STORE_TYPE_TO_NAME(type),
103                                 name, hostname);
104                 sdb_object_deref(SDB_OBJ(host));
105                 return -1;
106         }
107         obj = host;
108         if (type != SDB_HOST) {
109                 if (parent) {
110                         p = sdb_memstore_get_child(obj, parent_type, parent);
111                         if ((! p) || (filter
112                                                 && (! sdb_memstore_matcher_matches(filter, p, NULL)))) {
113                                 sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s.%s: "
114                                                 "%s not found", SDB_STORE_TYPE_TO_NAME(type),
115                                                 hostname, parent, name, parent);
116                                 status = -1;
117                         }
118                         obj = p;
119                 }
120                 if (! status) {
121                         obj = sdb_memstore_get_child(obj, type, name);
122                         if ((! obj) || (filter
123                                                 && (! sdb_memstore_matcher_matches(filter, obj, NULL)))) {
124                                 sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s: "
125                                                 "%s not found", SDB_STORE_TYPE_TO_NAME(type),
126                                                 hostname, name, name);
127                                 status = -1;
128                         }
129                 }
130         }
132         if (! status) {
133                 if (type != SDB_HOST)
134                         status = sdb_memstore_emit(host, w, wd);
135                 if ((! status) && parent)
136                         status = sdb_memstore_emit(p, w, wd);
137                 if (! status) {
138                         if (full)
139                                 status = sdb_memstore_emit_full(obj, filter, w, wd);
140                         else
141                                 status = sdb_memstore_emit(obj, w, wd);
142                 }
143                 if (status) {
144                         sdb_log(SDB_LOG_ERR, "memstore: Failed to serialize "
145                                         "%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type),
146                                         hostname, name);
147                         sdb_strbuf_sprintf(errbuf, "Out of memory");
148                         status = -1;
149                 }
150         }
152         if (host != obj)
153                 sdb_object_deref(SDB_OBJ(host));
154         if (p != obj)
155                 sdb_object_deref(SDB_OBJ(p));
156         sdb_object_deref(SDB_OBJ(obj));
158         if (status)
159                 return status;
160         return SDB_CONNECTION_DATA;
161 } /* exec_fetch */
163 static int
164 exec_list(sdb_memstore_t *store,
165                 sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf,
166                 int type, sdb_memstore_matcher_t *filter)
168         iter_t iter = { NULL, w, wd };
170         if (sdb_memstore_scan(store, type, /* m = */ NULL, filter, list_tojson, &iter)) {
171                 sdb_log(SDB_LOG_ERR, "memstore: Failed to serialize "
172                                 "store to JSON");
173                 sdb_strbuf_sprintf(errbuf, "Out of memory");
174                 return -1;
175         }
177         return SDB_CONNECTION_DATA;
178 } /* exec_list */
180 static int
181 exec_lookup(sdb_memstore_t *store,
182                 sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf,
183                 int type, sdb_memstore_matcher_t *m, sdb_memstore_matcher_t *filter)
185         iter_t iter = { NULL, w, wd };
187         if (sdb_memstore_scan(store, type, m, filter, lookup_tojson, &iter)) {
188                 sdb_log(SDB_LOG_ERR, "memstore: Failed to lookup %ss",
189                                 SDB_STORE_TYPE_TO_NAME(type));
190                 sdb_strbuf_sprintf(errbuf, "Failed to lookup %ss",
191                                 SDB_STORE_TYPE_TO_NAME(type));
192                 return -1;
193         }
195         return SDB_CONNECTION_DATA;
196 } /* exec_lookup */
198 /*
199  * public API
200  */
202 int
203 sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *q,
204                 sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf)
206         sdb_ast_node_t *ast;
208         if (! q)
209                 return -1;
210         if (! q->ast) {
211                 sdb_log(SDB_LOG_ERR, "memstore: Invalid empty query");
212                 return -1;
213         }
215         ast = q->ast;
216         switch (ast->type) {
217         case SDB_AST_TYPE_FETCH:
218                 return exec_fetch(store, w, wd, errbuf,
219                                 SDB_AST_FETCH(ast)->obj_type, SDB_AST_FETCH(ast)->hostname,
220                                 SDB_AST_FETCH(ast)->parent_type, SDB_AST_FETCH(ast)->parent,
221                                 SDB_AST_FETCH(ast)->name, SDB_AST_FETCH(ast)->full, q->filter);
223         case SDB_AST_TYPE_LIST:
224                 return exec_list(store, w, wd, errbuf, SDB_AST_LIST(ast)->obj_type,
225                                 q->filter);
227         case SDB_AST_TYPE_LOOKUP:
228                 return exec_lookup(store, w, wd, errbuf, SDB_AST_LOOKUP(ast)->obj_type,
229                                 q->matcher, q->filter);
231         default:
232                 sdb_log(SDB_LOG_ERR, "memstore: Invalid query of type %s",
233                                 SDB_AST_TYPE_TO_STRING(ast));
234                 return -1;
235         }
237         return 0;
238 } /* sdb_memstore_query_execute */
240 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */