1 | /* |
2 | * Copyright 2008-2018 Aerospike, Inc. |
3 | * |
4 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
5 | * license agreements. |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
8 | * use this file except in compliance with the License. You may obtain a copy of |
9 | * the License at http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
14 | * License for the specific language governing permissions and limitations under |
15 | * the License. |
16 | */ |
17 | |
18 | #include <aerospike/as_val.h> |
19 | #include <aerospike/as_aerospike.h> |
20 | |
21 | #include <aerospike/mod_lua_aerospike.h> |
22 | #include <aerospike/mod_lua_record.h> |
23 | #include <aerospike/mod_lua_val.h> |
24 | #include <aerospike/mod_lua_reg.h> |
25 | |
26 | #include "internal.h" |
27 | |
28 | |
29 | /******************************************************************************* |
30 | * MACROS |
31 | ******************************************************************************/ |
32 | |
33 | #define CLASS_NAME "Aerospike" |
34 | |
35 | /******************************************************************************* |
36 | * FUNCTIONS |
37 | ******************************************************************************/ |
38 | |
39 | /** |
40 | * Read the item at index and convert to a aerospike |
41 | */ |
42 | as_aerospike * mod_lua_toaerospike(lua_State * l, int index) { |
43 | mod_lua_box * box = mod_lua_tobox(l, index, CLASS_NAME); |
44 | return (as_aerospike *) mod_lua_box_value(box); |
45 | } |
46 | |
47 | /** |
48 | * Push aerospike on to the lua stack |
49 | */ |
50 | as_aerospike * mod_lua_pushaerospike(lua_State * l, as_aerospike * a) { |
51 | mod_lua_box * box = mod_lua_pushbox(l, MOD_LUA_SCOPE_HOST, a, CLASS_NAME); |
52 | return (as_aerospike *) mod_lua_box_value(box); |
53 | } |
54 | |
55 | /** |
56 | * Get aerospike from the stack at index |
57 | */ |
58 | static as_aerospike * mod_lua_checkaerospike(lua_State * l, int index) { |
59 | mod_lua_box * box = mod_lua_checkbox(l, index, CLASS_NAME); |
60 | return (as_aerospike *) mod_lua_box_value(box); |
61 | } |
62 | |
63 | /** |
64 | * Garbage collection |
65 | */ |
66 | static int mod_lua_aerospike_gc(lua_State * l) { |
67 | LOG("mod_lua_aerospike_gc: begin" ); |
68 | mod_lua_freebox(l, 1, CLASS_NAME); |
69 | LOG("mod_lua_aerospike_gc: end" ); |
70 | return 0; |
71 | } |
72 | |
73 | |
74 | /** |
75 | * aerospike.create(record) => result<bool> |
76 | */ |
77 | static int mod_lua_aerospike_rec_create(lua_State * l) { |
78 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
79 | as_rec * r = mod_lua_torecord(l, 2); |
80 | int rc = as_aerospike_rec_create(a, r); |
81 | lua_pushinteger(l, rc); |
82 | return 1; |
83 | } |
84 | |
85 | /** |
86 | * aerospike.update(record) => result<bool> |
87 | */ |
88 | static int mod_lua_aerospike_rec_update(lua_State * l) { |
89 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
90 | as_rec * r = mod_lua_torecord(l, 2); |
91 | int rc = as_aerospike_rec_update(a, r); |
92 | lua_pushinteger(l, rc); |
93 | return 1; |
94 | } |
95 | |
96 | /** |
97 | * aerospike.exists(record) => result<bool> |
98 | */ |
99 | static int mod_lua_aerospike_rec_exists(lua_State * l) { |
100 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
101 | as_rec * r = mod_lua_torecord(l, 2); |
102 | int rc = as_aerospike_rec_exists(a, r); |
103 | lua_pushboolean(l, rc == 1); |
104 | return 1; |
105 | } |
106 | |
107 | /** |
108 | * aerospike.remove(namespace, set, key) => result<bool> |
109 | */ |
110 | static int mod_lua_aerospike_rec_remove(lua_State * l) { |
111 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
112 | as_rec * r = mod_lua_torecord(l, 2); |
113 | int rc = as_aerospike_rec_remove(a, r); |
114 | lua_pushinteger(l, rc); |
115 | return 1; |
116 | } |
117 | |
118 | /** |
119 | * aerospike.log(level, message) |
120 | */ |
121 | static int mod_lua_aerospike_log(lua_State * l) { |
122 | lua_Debug ar; |
123 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
124 | int lvl = luaL_optint(l, 2, 0); |
125 | const char * msg = luaL_optstring(l, 3, NULL); |
126 | |
127 | // With LuaJIT, stack level 1 is where we find the Lua function that made |
128 | // the logging call. With the regular Lua lib it's at level 2. |
129 | #ifdef USE_LUAJIT |
130 | lua_getstack(l, 1, &ar); |
131 | #else |
132 | lua_getstack(l, 2, &ar); |
133 | #endif |
134 | |
135 | lua_getinfo(l, "nSl" , &ar); |
136 | |
137 | as_aerospike_log(a, ++ar.source, ar.currentline, lvl, msg); |
138 | return 0; |
139 | } // end mod_lua_aerospike_log() |
140 | |
141 | /** |
142 | * Compute the time and store it in Lua. We will have to decide what type |
143 | * we want to use for that -- since Lua numbers are only 56 bits precision, |
144 | * and cf_clock is a 64 bit value. |
145 | * It is possible that we'll have to store this as BYTES (similar to how we |
146 | * deal with digests) -- or something. |
147 | */ |
148 | static int mod_lua_aerospike_get_current_time(lua_State * l) { |
149 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
150 | cf_clock cur_time = as_aerospike_get_current_time( a ); |
151 | lua_pushinteger(l, cur_time ); // May have to push some other type @TOBY |
152 | return 1; |
153 | } |
154 | |
155 | /** |
156 | * Hook to set execution context information |
157 | */ |
158 | static int mod_lua_aerospike_set_context(lua_State * l) { |
159 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
160 | |
161 | as_rec * r = mod_lua_torecord(l, 2); |
162 | |
163 | // Get the 2nd arg off the stack -- and process as context |
164 | uint32_t context = (uint32_t)luaL_optinteger(l, 3, 0); |
165 | |
166 | int ret = as_aerospike_set_context(a, r, context); |
167 | |
168 | lua_pushinteger(l, ret); |
169 | return 1; |
170 | } |
171 | |
172 | /** |
173 | * hook to fetch config information from server. |
174 | */ |
175 | static int mod_lua_aerospike_get_config(lua_State * l) { |
176 | as_aerospike * a = mod_lua_checkaerospike(l, 1); |
177 | as_rec * r = mod_lua_torecord(l, 2); |
178 | const char * name = luaL_optstring(l, 3, NULL); |
179 | |
180 | int ret = as_aerospike_get_config(a, r, name); |
181 | lua_pushinteger(l, ret); |
182 | return 1; |
183 | } // end mod_lua_aerospike_get_config() |
184 | |
185 | /****************************************************************************** |
186 | * CLASS TABLE |
187 | *****************************************************************************/ |
188 | |
189 | static const luaL_reg class_table[] = { |
190 | {"create" , mod_lua_aerospike_rec_create}, |
191 | {"update" , mod_lua_aerospike_rec_update}, |
192 | {"exists" , mod_lua_aerospike_rec_exists}, |
193 | {"remove" , mod_lua_aerospike_rec_remove}, |
194 | {"log" , mod_lua_aerospike_log}, |
195 | {"get_current_time" , mod_lua_aerospike_get_current_time}, |
196 | {"set_context" , mod_lua_aerospike_set_context}, |
197 | {"get_config" , mod_lua_aerospike_get_config}, |
198 | {0, 0} |
199 | }; |
200 | |
201 | static const luaL_reg class_metatable[] = { |
202 | {"__gc" , mod_lua_aerospike_gc}, |
203 | {0, 0} |
204 | }; |
205 | |
206 | /****************************************************************************** |
207 | * REGISTER |
208 | *****************************************************************************/ |
209 | |
210 | int mod_lua_aerospike_register(lua_State * l) { |
211 | mod_lua_reg_class(l, CLASS_NAME, class_table, class_metatable); |
212 | return 1; |
213 | } |
214 | |