1 /*
2  Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights
3  reserved.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License, version 2.0,
7  as published by the Free Software Foundation.
8 
9  This program is also distributed with certain software (including
10  but not limited to OpenSSL) that is licensed under separate terms,
11  as designated in a particular file or component or in included license
12  documentation.  The authors of MySQL hereby grant you an additional
13  permission to link the program and your derivative works with the
14  separately licensed software that they have included with MySQL.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License, version 2.0, for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24  02110-1301  USA
25 */
26 
27 #include <NdbApi.hpp>
28 
29 #include "adapter_global.h"
30 #include "js_wrapper_macros.h"
31 #include "Record.h"
32 #include "NativeMethodCall.h"
33 #include "NativeCFunctionCall.h"
34 #include "NdbWrapperErrors.h"
35 
36 using namespace v8;
37 
38 Handle<Value> getAutoIncValue(const Arguments &);
39 Handle<Value> closeNdb(const Arguments &);
40 Handle<Value> getStatistics(const Arguments &);
41 Handle<Value> getConnectionStatistics(const Arguments &);
42 
43 class NdbEnvelopeClass : public Envelope {
44 public:
NdbEnvelopeClass()45   NdbEnvelopeClass() : Envelope("Ndb") {
46     DEFINE_JS_FUNCTION(Envelope::stencil, "getNdbError", getNdbError<Ndb>);
47     DEFINE_JS_FUNCTION(Envelope::stencil, "close", closeNdb);
48     DEFINE_JS_FUNCTION(Envelope::stencil, "getStatistics", getStatistics);
49     DEFINE_JS_FUNCTION(Envelope::stencil, "getConnectionStatistics", getConnectionStatistics);
50   }
51 
wrap(Ndb * ndb)52   Local<Object> wrap(Ndb *ndb) {
53     HandleScope scope;
54     Local<Object> wrapper = Envelope::stencil->NewInstance();
55     wrapPointerInObject(ndb, *this, wrapper);
56     return scope.Close(wrapper);
57   }
58 };
59 
60 NdbEnvelopeClass NdbEnvelope;
61 
Ndb_Wrapper(Ndb * ndb)62 Handle<Value> Ndb_Wrapper(Ndb *ndb) {
63   return NdbEnvelope.wrap(ndb);
64 }
65 
66 /* Ndb constructor.
67    create_ndb(Ndb_cluster_connection, databaseName, callback)
68    The constructor is wrapped in a call that also calls ndb->init().
69 */
async_create_ndb(Ndb_cluster_connection * conn,const char * db)70 Ndb * async_create_ndb(Ndb_cluster_connection *conn, const char *db) {
71   Ndb *ndb = new Ndb(conn, db);
72   DEBUG_PRINT("Created Ndb %p", ndb);
73   if(ndb) ndb->init();
74   return ndb;
75 }
76 
create_ndb(const Arguments & args)77 Handle<Value> create_ndb(const Arguments &args) {
78   REQUIRE_ARGS_LENGTH(3);
79 
80   typedef NativeCFunctionCall_2_<Ndb *, Ndb_cluster_connection *, const char *> MCALL;
81   MCALL * mcallptr = new MCALL(& async_create_ndb, args);
82   mcallptr->wrapReturnValueAs(& NdbEnvelope);
83   mcallptr->runAsync();
84   return Undefined();
85 }
86 
87 
88 /* getAutoIncrementValue(ndb, table, batch_size, callback);
89    We can't map Ndb::getAutoIncrementValue() directly due to in/out param.
90    The JS Wrapper function will simply return 0 on error.
91 */
getAutoInc(Ndb * ndb,const NdbDictionary::Table * table,uint32_t batch)92 Uint64 getAutoInc(Ndb *ndb, const NdbDictionary::Table * table, uint32_t batch) {
93   Uint64 autoinc;
94   DEBUG_PRINT("getAutoIncrementValue %p", ndb);
95   int r = ndb->getAutoIncrementValue(table, autoinc, batch);
96   if(r == -1) autoinc = 0;
97   return autoinc;
98 }
99 
getAutoIncValue(const Arguments & args)100 Handle<Value> getAutoIncValue(const Arguments &args) {
101   DEBUG_MARKER(UDEB_DEBUG);
102   REQUIRE_ARGS_LENGTH(4);
103   typedef NativeCFunctionCall_3_<Uint64, Ndb *, const NdbDictionary::Table *,
104                                  uint32_t> MCALL;
105   MCALL * mcallptr = new MCALL(& getAutoInc, args);
106   mcallptr->runAsync();
107   return Undefined();
108 }
109 
110 
getStatistics(const Arguments & args)111 Handle<Value> getStatistics(const Arguments &args) {
112   HandleScope scope;
113   Ndb *ndb = unwrapPointer<Ndb *>(args.Holder());
114   Local<Object> stats = Object::New();
115   for(int i = 0 ; i < Ndb::NumClientStatistics ; i ++) {
116     stats->Set(String::NewSymbol(ndb->getClientStatName(i)),
117                Number::New(ndb->getClientStat(i)),
118                ReadOnly);
119   }
120   return scope.Close(stats);
121 }
122 
123 
getConnectionStatistics(const Arguments & args)124 Handle<Value> getConnectionStatistics(const Arguments &args) {
125   HandleScope scope;
126   Uint64 ndb_stats[Ndb::NumClientStatistics];
127 
128   Ndb *ndb = unwrapPointer<Ndb *>(args.Holder());
129   Ndb_cluster_connection & c = ndb->get_ndb_cluster_connection();
130 
131   c.collect_client_stats(ndb_stats, Ndb::NumClientStatistics);
132 
133   Local<Object> stats = Object::New();
134   for(int i = 0 ; i < Ndb::NumClientStatistics ; i ++) {
135     stats->Set(String::NewSymbol(ndb->getClientStatName(i)),
136                Number::New(ndb_stats[i]),
137                ReadOnly);
138   }
139   return scope.Close(stats);
140 }
141 
closeNdb(const Arguments & args)142 Handle<Value> closeNdb(const Arguments &args) {
143   DEBUG_MARKER(UDEB_DETAIL);
144   typedef NativeDestructorCall<Ndb> MCALL;
145   MCALL * mcallptr = new MCALL(args);
146   mcallptr->runAsync();
147   return Undefined();
148 }
149 
150 
NdbWrapper_initOnLoad(Handle<Object> target)151 void NdbWrapper_initOnLoad(Handle<Object> target) {
152   DEFINE_JS_FUNCTION(target, "getAutoIncrementValue", getAutoIncValue);
153   DEFINE_JS_FUNCTION(target, "create_ndb", create_ndb);
154 }
155