Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-01-25 04:50:10 +0300
committerRyan Dahl <ry@tinyclouds.org>2011-01-25 05:59:06 +0300
commit068b733583a4f0781a8418ddf42f7912e3dd53a6 (patch)
tree7f9dd4ca422b06447db9f901cc11d9f7bca90423 /src
parent91cc2d8c4bff5c5fbacd757f38b9a8c690dce131 (diff)
Land Cantrill's DTrace patch
only works on solaris
Diffstat (limited to 'src')
-rw-r--r--src/node.cc3
-rw-r--r--src/node.d64
-rw-r--r--src/node_dtrace.cc113
-rw-r--r--src/node_dtrace.h28
-rw-r--r--src/node_provider.d44
5 files changed, 252 insertions, 0 deletions
diff --git a/src/node.cc b/src/node.cc
index 512c1d97f12..582b0d23c41 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -3,6 +3,7 @@
#include <node.h>
#include <v8-debug.h>
+#include <node_dtrace.h>
#include <locale.h>
#include <stdio.h>
@@ -2028,6 +2029,8 @@ static void Load(int argc, char *argv[]) {
Local<Object> global = v8::Context::GetCurrent()->Global();
Local<Value> args[1] = { Local<Value>::New(process) };
+ InitDTrace(global);
+
f->Call(global, 1, args);
if (try_catch.HasCaught()) {
diff --git a/src/node.d b/src/node.d
new file mode 100644
index 00000000000..80010e9b4f7
--- /dev/null
+++ b/src/node.d
@@ -0,0 +1,64 @@
+/*
+ * This is the DTrace library file for the node provider, which includes
+ * the necessary translators to get from the args[] to something useful.
+ * Be warned: the mechanics here are seriously ugly -- and one must always
+ * keep in mind that clean abstractions often require filthy systems.
+ */
+#pragma D depends_on library procfs.d
+
+typedef struct {
+ int32_t fd;
+ int32_t port;
+ uint32_t remote;
+} node_dtrace_connection_t;
+
+typedef struct {
+ int32_t fd;
+ int32_t port;
+ uint64_t remote;
+} node_dtrace_connection64_t;
+
+typedef struct {
+ int fd;
+ string remoteAddress;
+ int remotePort;
+} node_connection_t;
+
+translator node_connection_t <node_dtrace_connection_t *nc> {
+ fd = *(int32_t *)copyin((uintptr_t)&nc->fd, sizeof (int32_t));
+ remotePort =
+ *(int32_t *)copyin((uintptr_t)&nc->port, sizeof (int32_t));
+ remoteAddress = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
+ copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nc->remote,
+ sizeof (int32_t))) :
+ copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
+ &((node_dtrace_connection64_t *)nc)->remote, sizeof (int64_t)));
+};
+
+typedef struct {
+ uint32_t url;
+ uint32_t method;
+} node_dtrace_http_request_t;
+
+typedef struct {
+ uint64_t url;
+ uint64_t method;
+} node_dtrace_http_request64_t;
+
+typedef struct {
+ string url;
+ string method;
+} node_http_request_t;
+
+translator node_http_request_t <node_dtrace_http_request_t *nd> {
+ url = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
+ copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->url,
+ sizeof (int32_t))) :
+ copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
+ &((node_dtrace_http_request64_t *)nd)->url, sizeof (int64_t)));
+ method = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
+ copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->method,
+ sizeof (int32_t))) :
+ copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
+ &((node_dtrace_http_request64_t *)nd)->method, sizeof (int64_t)));
+};
diff --git a/src/node_dtrace.cc b/src/node_dtrace.cc
new file mode 100644
index 00000000000..0f7726a6209
--- /dev/null
+++ b/src/node_dtrace.cc
@@ -0,0 +1,113 @@
+#include <node_dtrace.h>
+
+#ifdef HAVE_DTRACE
+#include "node_provider.h"
+#else
+#define NODE_HTTP_SERVER_REQUEST(arg0, arg1)
+#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0)
+#define NODE_HTTP_SERVER_RESPONSE(arg0)
+#define NODE_HTTP_SERVER_RESPONSE_ENABLED() (0)
+#define NODE_NET_SERVER_CONNECTION(arg0)
+#define NODE_NET_SERVER_CONNECTION_ENABLED() (0)
+#define NODE_NET_STREAM_END(arg0)
+#define NODE_NET_STREAM_END_ENABLED() (0)
+#endif
+
+namespace node {
+
+using namespace v8;
+
+#define SLURP_STRING(obj, member, valp) \
+ String::Utf8Value _##member(obj->Get(String::New(#member))->ToString()); \
+ if ((*(const char **)valp = *_##member) == NULL) \
+ *(const char **)valp = "<unknown>";
+
+#define SLURP_INT(obj, member, valp) \
+ *valp = obj->Get(String::New(#member))->ToInteger()->Value();
+
+#define SLURP_CONNECTION(arg, conn) \
+ node_dtrace_connection_t conn; \
+ Local<Object> _##conn = Local<Object>::Cast(arg); \
+ SLURP_INT(_##conn, fd, &conn.fd); \
+ SLURP_STRING(_##conn, remoteAddress, &conn.remote); \
+ SLURP_INT(_##conn, remotePort, &conn.port);
+
+Handle<Value> DTRACE_NET_SERVER_CONNECTION(const Arguments& args) {
+ if (!NODE_NET_SERVER_CONNECTION_ENABLED())
+ return Undefined();
+
+ HandleScope scope;
+
+ SLURP_CONNECTION(args[0], conn);
+ NODE_NET_SERVER_CONNECTION(&conn);
+
+ return Undefined();
+}
+
+Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) {
+ if (!NODE_NET_STREAM_END_ENABLED())
+ return Undefined();
+
+ HandleScope scope;
+
+ SLURP_CONNECTION(args[0], conn);
+ NODE_NET_STREAM_END(&conn);
+
+ return Undefined();
+}
+
+Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
+ node_dtrace_http_request_t req;
+
+ if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
+ return Undefined();
+
+ HandleScope scope;
+
+ Local<Object> arg0 = Local<Object>::Cast(args[0]);
+ Local<Object> arg1 = Local<Object>::Cast(args[1]);
+
+ SLURP_STRING(arg0, url, &req.url);
+ SLURP_STRING(arg0, method, &req.method);
+
+ SLURP_CONNECTION(args[1], conn);
+
+ NODE_HTTP_SERVER_REQUEST(&req, &conn);
+ return Undefined();
+}
+
+Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) {
+ if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
+ return Undefined();
+
+ HandleScope scope;
+
+ SLURP_CONNECTION(args[0], conn);
+ NODE_HTTP_SERVER_RESPONSE(&conn);
+
+ return Undefined();
+}
+
+#define NODE_PROBE(name) #name, name
+
+void InitDTrace(Handle<Object> target) {
+ static struct {
+ const char *name;
+ Handle<Value> (*func)(const Arguments&);
+ Persistent<FunctionTemplate> templ;
+ } tab[] = {
+ { NODE_PROBE(DTRACE_NET_SERVER_CONNECTION) },
+ { NODE_PROBE(DTRACE_NET_STREAM_END) },
+ { NODE_PROBE(DTRACE_HTTP_SERVER_REQUEST) },
+ { NODE_PROBE(DTRACE_HTTP_SERVER_RESPONSE) },
+ { NULL }
+ };
+
+ for (int i = 0; tab[i].name != NULL; i++) {
+ tab[i].templ = Persistent<FunctionTemplate>::New(
+ FunctionTemplate::New(tab[i].func));
+ target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
+ }
+}
+
+}
diff --git a/src/node_dtrace.h b/src/node_dtrace.h
new file mode 100644
index 00000000000..267c7292169
--- /dev/null
+++ b/src/node_dtrace.h
@@ -0,0 +1,28 @@
+#ifndef NODE_DTRACE_H_
+#define NODE_DTRACE_H_
+
+#include <node.h>
+#include <v8.h>
+
+extern "C" {
+
+typedef struct {
+ int32_t fd;
+ int32_t port;
+ char *remote;
+} node_dtrace_connection_t;
+
+typedef struct {
+ char *url;
+ char *method;
+} node_dtrace_http_request_t;
+
+}
+
+namespace node {
+
+void InitDTrace(v8::Handle<v8::Object> target);
+
+}
+
+#endif
diff --git a/src/node_provider.d b/src/node_provider.d
new file mode 100644
index 00000000000..3d11f39416b
--- /dev/null
+++ b/src/node_provider.d
@@ -0,0 +1,44 @@
+/*
+ * DTrace provider for node.js.
+ */
+
+/*
+ * In order to have the information we need here to create the provider,
+ * we must declare bogus definitions for our depended-upon structures. And
+ * yes, the fact that we need to do this represents a shortcoming in DTrace,
+ * one that would be resolved by that elusive El Dorado: dynamic translators.
+ */
+
+typedef struct {
+ int dummy;
+} node_dtrace_connection_t;
+
+typedef struct {
+ int dummy;
+} node_connection_t;
+
+typedef struct {
+ int dummy;
+} node_dtrace_http_request_t;
+
+typedef struct {
+ int dummy;
+} node_http_request_t;
+
+provider node {
+ probe net__server__connection(node_dtrace_connection_t *c) :
+ (node_connection_t *c);
+ probe net__stream__end(node_dtrace_connection_t *c) :
+ (node_connection_t *c);
+ probe http__server__request(node_dtrace_http_request_t *h,
+ node_dtrace_connection_t *c) :
+ (node_http_request_t *h, node_connection_t *c);
+ probe http__server__response(node_dtrace_connection_t *c) :
+ (node_connection_t *c);
+};
+
+#pragma D attributes Evolving/Evolving/ISA provider node provider
+#pragma D attributes Private/Private/Unknown provider node module
+#pragma D attributes Private/Private/Unknown provider node function
+#pragma D attributes Private/Private/ISA provider node name
+#pragma D attributes Evolving/Evolving/ISA provider node args