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 */
42as_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 */
50as_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 */
58static 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 */
66static 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 */
77static 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 */
88static 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 */
99static 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 */
110static 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 */
121static 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 */
148static 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 */
158static 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 */
175static 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
189static 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
201static const luaL_reg class_metatable[] = {
202 {"__gc", mod_lua_aerospike_gc},
203 {0, 0}
204};
205
206/******************************************************************************
207 * REGISTER
208 *****************************************************************************/
209
210int mod_lua_aerospike_register(lua_State * l) {
211 mod_lua_reg_class(l, CLASS_NAME, class_table, class_metatable);
212 return 1;
213}
214