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 <lua.h>
19#include <lauxlib.h>
20#include <lualib.h>
21
22#include <aerospike/as_val.h>
23
24#include <aerospike/mod_lua_val.h>
25#include <aerospike/mod_lua_stream.h>
26#include <aerospike/mod_lua_reg.h>
27
28#include "internal.h"
29
30
31/*******************************************************************************
32 * MACROS
33 ******************************************************************************/
34
35#define OBJECT_NAME "stream"
36#define CLASS_NAME "Stream"
37
38/*******************************************************************************
39 * FUNCTIONS
40 ******************************************************************************/
41
42as_stream * mod_lua_tostream(lua_State * l, int index) {
43 mod_lua_box * box = mod_lua_tobox(l, index, CLASS_NAME);
44 return (as_stream *) mod_lua_box_value(box);
45}
46
47as_stream * mod_lua_pushstream(lua_State * l, as_stream * stream) {
48 mod_lua_box * box = mod_lua_pushbox(l, MOD_LUA_SCOPE_HOST, stream, CLASS_NAME);
49 return (as_stream *) mod_lua_box_value(box);
50}
51
52// static as_stream * mod_lua_checkstream(lua_State * l, int index) {
53// mod_lua_box * box = mod_lua_checkbox(l, index, CLASS_NAME);
54// return (as_stream *) mod_lua_box_value(box);
55// }
56
57static int mod_lua_stream_gc(lua_State * l) {
58 mod_lua_freebox(l, 1, CLASS_NAME);
59 return 0;
60}
61
62static int mod_lua_stream_tostring(lua_State * l) {
63 as_stream * stream = mod_lua_tostream(l, 1);
64 char str[128] = { '\0' };
65 snprintf(str, 128, "Stream<%p>", stream);
66 lua_pushstring(l, str);
67 return 1;
68}
69
70static int mod_lua_stream_read(lua_State * l) {
71 as_stream * stream = mod_lua_tostream(l, 1);
72 if ( stream ) {
73 as_val * val = as_stream_read(stream);
74 mod_lua_pushval(l, val );
75
76// Client aggregation queries read data from server nodes and populate this stream. After that,
77// the client has no use for this value. Therefore, destroy value after reading from this stream.
78// Enable on client build only.
79#ifdef AS_MOD_LUA_CLIENT
80 as_val_destroy(val);
81#endif
82
83 return 1;
84 }
85 else {
86 lua_pushnil(l);
87 return 1;
88 }
89}
90
91static int mod_lua_stream_readable(lua_State * l) {
92 as_stream * stream = mod_lua_tostream(l, 1);
93 if ( stream ) {
94 lua_pushboolean(l, as_stream_readable(stream));
95 return 1;
96 }
97 else {
98 lua_pushboolean(l, false);
99 return 1;
100 }
101}
102
103static int mod_lua_stream_write(lua_State * l) {
104 as_stream * stream = mod_lua_tostream(l, 1);
105 if ( stream ) {
106 as_val * val = mod_lua_toval(l, 2);
107 if ( val == &as_nil ) {
108 // as_nil terminates the stream in Lua,
109 // while NULL terminates the stream in C,
110 // so we map the former to the latter here.
111 val = NULL;
112 }
113 int rc = as_stream_write(stream, val);
114 lua_pushinteger(l, rc);
115 return 1;
116 }
117 else {
118 lua_pushinteger(l, AS_STREAM_ERR);
119 return 1;
120 }
121}
122
123static int mod_lua_stream_writable(lua_State * l) {
124 as_stream * stream = mod_lua_tostream(l, 1);
125 if ( stream ) {
126 lua_pushboolean(l, as_stream_readable(stream));
127 return 1;
128 }
129 else {
130 lua_pushboolean(l, false);
131 return 1;
132 }
133}
134
135/*******************************************************************************
136 * OBJECT TABLE
137 ******************************************************************************/
138
139static const luaL_reg object_table[] = {
140 {"read", mod_lua_stream_read},
141 {"write", mod_lua_stream_write},
142 {"readable", mod_lua_stream_readable},
143 {"writable", mod_lua_stream_writable},
144 {"tostring", mod_lua_stream_tostring},
145 {0, 0}
146};
147
148static const luaL_reg object_metatable[] = {
149 {0, 0}
150};
151
152/*******************************************************************************
153 * CLASS TABLE
154 ******************************************************************************/
155
156/*
157static const luaL_reg class_table[] = {
158 {0, 0}
159};
160*/
161
162static const luaL_reg class_metatable[] = {
163 {"__tostring", mod_lua_stream_tostring},
164 {"__gc", mod_lua_stream_gc},
165 {0, 0}
166};
167
168/*******************************************************************************
169 * REGISTER
170 ******************************************************************************/
171
172int mod_lua_stream_register(lua_State * l) {
173 mod_lua_reg_object(l, OBJECT_NAME, object_table, object_metatable);
174 mod_lua_reg_class(l, CLASS_NAME, NULL, class_metatable);
175 return 1;
176}
177