~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/js_eval/js_eval.cc

  • Committer: Henrik Ingo
  • Date: 2011-09-01 07:09:26 UTC
  • mto: This revision was merged to the branch mainline in revision 2439.
  • Revision ID: henrik.ingo@avoinelama.fi-20110901070926-4z5zbzxw6npl3jgz
Use v8::Locker to allow multiple threads to use v8 engine.

Note that making all threads that need to use JavaScript lock
on a single mutex is going to be problematic. Newer versions
of libv8 provide a class Isolate, through which each thread can
have their own, isolated, instance of a v8 engine and use it
without locking. However, current version in Ubuntu 11.04 is
v8 2.5.9.9 and doesn't yet provide this class. Future work
on this code should add a run-time check about the v8 version
and use Isolate if available and Locker otherwise.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include <drizzled/function/str/strfunc.h>
25
25
 
26
26
#include <v8.h>
 
27
#define JS_ENGINE "v8"
27
28
 
28
29
using namespace std;
29
30
using namespace drizzled;
30
31
 
31
32
 
 
33
// TODO: Can I just declare functions like this? Do I need to use a namespace? Naming convention?
 
34
v8::Handle<v8::Value> V8Version(const v8::Arguments& args);
 
35
v8::Handle<v8::Value> JsEngine(const v8::Arguments& args);
32
36
const char* ToCString(const v8::String::Utf8Value& value);
33
37
void ReportException(v8::TryCatch* try_catch);
34
 
v8::Handle<v8::Value> V8Version(const v8::Arguments& args);
35
38
 
36
39
 
37
40
// TODO: So this is a function that returns strings? 
121
124
/**
122
125
 * Implements js_eval(), evaluate JavaScript code
123
126
 * 
124
 
 * @note: I only compiled this with -O0 but should work with default O2 also.
 
127
 * @note I only compiled this with -O0 but should work with default O2 also.
125
128
 *
126
 
 * @todo: Accepts more than one parameter, but doesn't use them.
127
 
 * @todo: How does it work if I want to return integers and doubles?
128
 
 * @todo: v8 exceptions are printed to the log. Should be converted to 
 
129
 * @todo Accepts more than one parameter, but doesn't use them.
 
130
 * @todo How does it work if I want to return integers and doubles?
 
131
 * @todo v8 exceptions are printed to the log. Should be converted to 
129
132
 * drizzle warning/error and returned with result.
130
 
 * @todo: Probably the v8 stuff will be moved to it's own function in the future.
131
 
 * @todo: Documentation for drizzle manual in .rst format
 
133
 * @todo Probably the v8 stuff will be moved to it's own function in the future.
 
134
 * @todo Documentation for drizzle manual in .rst format
 
135
 * @todo When available, use v8::Isolate instead of v8::Locker for multithreading
132
136
 * 
133
137
 * @param res Pointer to the drizzled::String object that will contain the result
134
138
 * @return a drizzled::String containing the value returned by executed JavaScript code (value of last executed statement) 
143
147
  String *source_str=NULL;
144
148
  source_str = args[0]->val_str(source_str); 
145
149
  
 
150
  // TODO Some of this (FunctionTemplate and other bindings) should probably be 
 
151
  // moved to initialize, but then it must be allocated on the heap.
 
152
  
 
153
  // Need to use Locker in multi-threaded app. v8 is unlocked by the destructor 
 
154
  // when locker goes out of scope.
 
155
  // TODO: Newer versions of v8 provide an Isolate class where you can get a 
 
156
  // separate instance of v8 (ie one per thread). v8 2.5.9.9 in Ubuntu 11.04 does 
 
157
  // not yet offer it.
 
158
  v8::Locker locker;
146
159
  // Pass code and arguments into v8...
147
 
  // TODO Some of this should probably be moved to initialize, but then 
148
 
  // it must be allocated on the heap.
149
160
  v8::HandleScope handle_scope;
150
 
  // Create a template for the global object.
151
 
  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
152
 
  // Bind the 'version' function (TODO: just an example but this is how we bind arguments too...)
153
 
  global->Set(v8::String::New("version"), v8::FunctionTemplate::New(V8Version));
154
 
 
 
161
  // Create a template for the global object and populate a drizzle object.
 
162
  v8::Handle<v8::ObjectTemplate> global  = v8::ObjectTemplate::New();
 
163
  // Drizzle will contain API's to drizzle variables, functions and tables
 
164
  v8::Handle<v8::ObjectTemplate> drizzle = v8::ObjectTemplate::New();
 
165
  v8::Handle<v8::ObjectTemplate> js      = v8::ObjectTemplate::New();
 
166
  // Bind the 'version' function 
 
167
  global->Set(v8::String::New("drizzle"), drizzle);
 
168
  drizzle->Set(v8::String::New("js"), js);
 
169
  js->Set(v8::String::New("version"), v8::FunctionTemplate::New(V8Version));
 
170
  js->Set(v8::String::New("engine"), v8::FunctionTemplate::New(JsEngine));
 
171
  // TODO: Now bind the arguments into argv[]
 
172
  
155
173
  // Create a v8 string containing the JavaScript source code.
156
 
  // Convert from drizzled::String to char[] string to v8::String.
 
174
  // Convert from drizzled::String to char* string to v8::String.
157
175
  v8::Handle<v8::String> source = v8::String::New(source_str->c_str());
158
176
 
159
177
  
163
181
    //... = args[n];
164
182
  }
165
183
  v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
 
184
  //v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
166
185
  if (context.IsEmpty()) {
167
186
    // TODO: how do I set warning/error in the drizzle result?
168
187
    printf("Error in js_eval() while creating JavaScript context in v8.\n");
187
206
      // TODO: how do I set warning/error in the drizzle result?
188
207
      // Print errors that happened during execution.
189
208
      ReportException(&try_catch);
 
209
      // Dispose of Persistent objects before returning. (Is it needed?)
 
210
      context->Exit();
 
211
      context.Dispose();
190
212
      return NULL;
191
213
    } else {
192
214
      assert(!try_catch.HasCaught());
193
215
      if (result->IsUndefined()) {
194
216
        printf("js_eval() got Undefined result back from v8.\n");
 
217
        // Dispose of Persistent objects before returning. (Is it needed?)
 
218
        context->Exit();
 
219
        context.Dispose();
195
220
        return NULL;
196
221
      }
197
222
    }
227
252
{
228
253
  js_eval_function = new plugin::Create_function<JsEvalFunction>("js_eval");
229
254
  context.add(js_eval_function);
 
255
  // Initialize V8
 
256
  v8::V8::Initialize();
230
257
  return 0;
231
258
}
232
259
 
237
264
  return v8::String::New(v8::V8::GetVersion());
238
265
}
239
266
 
 
267
v8::Handle<v8::Value> JsEngine(const v8::Arguments&) {
 
268
  return v8::String::New(JS_ENGINE);
 
269
}
240
270
 
241
271
 
242
272
DRIZZLE_DECLARE_PLUGIN