File: dtrace_probe.cc

package info (click to toggle)
node-dtrace-provider 0.8.8-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 336 kB
  • sloc: cpp: 391; sh: 51; makefile: 2
file content (110 lines) | stat: -rw-r--r-- 2,941 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "dtrace_provider.h"
#include <nan.h>

namespace node {

  using namespace v8;

  DTraceProbe::DTraceProbe() : Nan::ObjectWrap() {
    argc = 0;
    probedef = NULL;
  }

  DTraceProbe::~DTraceProbe() {
    for (size_t i = 0; i < argc; i++)
      delete(this->arguments[i]);
    usdt_probe_release(probedef);
  }

  Nan::Persistent<FunctionTemplate> DTraceProbe::constructor_template;

  void DTraceProbe::Initialize(v8::Local<Object> target) {
    Nan::HandleScope scope;

    Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(DTraceProbe::New);
    t->InstanceTemplate()->SetInternalFieldCount(2);
    t->SetClassName(Nan::New<String>("DTraceProbe").ToLocalChecked());
    constructor_template.Reset(t);

    Nan::SetPrototypeMethod(t, "fire", DTraceProbe::Fire);

    target->Set(Nan::New<String>("DTraceProbe").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked());
  }

  NAN_METHOD(DTraceProbe::New) {
    Nan::HandleScope scope;
    DTraceProbe *probe = new DTraceProbe();
    probe->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }

  NAN_METHOD(DTraceProbe::Fire) {
    Nan::HandleScope scope;

    if (!info[0]->IsFunction()) {
      Nan::ThrowTypeError("Must give probe value callback as first argument");
      return;
    }

    DTraceProbe *pd = Nan::ObjectWrap::Unwrap<DTraceProbe>(info.Holder());
    info.GetReturnValue().Set(pd->_fire(info, 0));
  }

  v8::Local<Value> DTraceProbe::_fire(Nan::NAN_METHOD_ARGS_TYPE argsinfo, size_t fnidx) {
    Nan::HandleScope scope;

    if (usdt_is_enabled(this->probedef->probe) == 0) {
      return Nan::Undefined();
    }

    // invoke fire callback
    Nan::TryCatch try_catch;

    size_t cblen = argsinfo.Length() - fnidx - 1;
    Local<Value> *cbargs = new Local<Value>[cblen];

    for (size_t i = 0; i < cblen; i++) {
        cbargs[i] = argsinfo[i + fnidx + 1];
    }

    Local<Function> cb = Local<Function>::Cast(argsinfo[fnidx]);
    Nan::MaybeLocal<Value> maybe = Nan::Call(cb, this->handle(), cblen, cbargs);
    if (maybe.IsEmpty()) {
      Nan::ThrowTypeError("Failed to invoke fire callback");
      return Nan::Undefined();
    }
    Local<Value> probe_args = maybe.ToLocalChecked();

    delete [] cbargs;

    // exception in args callback?
    if (try_catch.HasCaught()) {
      Nan::FatalException(try_catch);
      return Nan::Undefined();
    }

    // check return
    if (!probe_args->IsArray()) {
      return Nan::Undefined();
    }

    Local<Array> a = Local<Array>::Cast(probe_args);
    void *argv[USDT_ARG_MAX];

    // convert each argument value
    for (size_t i = 0; i < argc; i++) {
      argv[i] = this->arguments[i]->ArgumentValue(a->Get(i));
    }

    // finally fire the probe
    usdt_fire_probe(this->probedef->probe, argc, argv);

    // free argument values
    for (size_t i = 0; i < argc; i++) {
      this->arguments[i]->FreeArgument(argv[i]);
    }

    return Nan::True();
  }

} // namespace node