Permalink
Browse files

Update for compatibility w/ Node v0.6.0

  • Loading branch information...
1 parent 688f27c commit 980a313f6e7dc12b8896087459b36b61180dd5f0 Dave Dopson committed Nov 17, 2011
View
@@ -0,0 +1,3 @@
+build
+node_modules
+npm-debug.log
File renamed without changes.
File renamed without changes.
File renamed without changes.
View
@@ -1,7 +1,7 @@
var assert = require ('assert');
var sys = require ('sys');
-var promise = require("zookeeper/promise");
-var ZK = require ("zookeeper").ZooKeeper;
+var promise = require("./promise");
+var ZK = require ("./zookeeper").ZooKeeper;
exports.ZK = ZK;
ZK.prototype.context = {};
View
@@ -0,0 +1,143 @@
+try {
+ // as of node 0.6.x, node-waf seems to build to a different directory. grr.
+ var NativeZk = require(__dirname + '/../build/Release/zookeeper_native').ZooKeeper;
+} catch(e) {
+ var NativeZk = require(__dirname + '/../build/default/zookeeper_native').ZooKeeper;
+}
+var EventEmitter = require('events').EventEmitter;
+var util = require('util');
+var _ = require('underscore');
+
+// with Node 0.5.x and greater, EventEmitter is pure-js, so we have to make a simple wrapper...
+// Partly inspired by https://github.com/bnoordhuis/node-event-emitter
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor
+////////////////////////////////////////////////////////////////////////////////
+
+module.exports = ZooKeeper;
+function ZooKeeper() {
+ var self = this;
+ self._native = new NativeZk();
+ self._native.emit = function(ev, a1, a2, a3) {
+ if(this.logger) this.logger("Emitting '" + ev + "' with args: " + a1 + ", " + a2 + ", " + a3);
+ if(typeof a1 === 'ZooKeeper') {
+ // callback returns the object. need to mangle this to return the wrapper instead
+ a1 = this;
+ }
+ self.emit(ev, a1, a2, a3);
+ }
+}
+
+util.inherits(ZooKeeper, EventEmitter);
+
+exports = module.exports = ZooKeeper;
+module.exports.ZooKeeper = ZooKeeper; // for compatibility
+
+////////////////////////////////////////////////////////////////////////////////
+// Constants
+////////////////////////////////////////////////////////////////////////////////
+
+// Other Stuff
+exports.ZOK = NativeZk.ZOK;
+exports.ZOO_EPHEMERAL = NativeZk.ZOO_EPHEMERAL;
+exports.ZOO_SEQUENCE = NativeZk.ZOO_SEQUENCE;
+
+// Permissions
+exports.ZOO_PERM_ADMIN = NativeZk.ZOO_PERM_ADMIN;
+exports.ZOO_PERM_ALL = NativeZk.ZOO_PERM_ALL;
+exports.ZOO_PERM_CREATE = NativeZk.ZOO_PERM_CREATE;
+exports.ZOO_PERM_DELETE = NativeZk.ZOO_PERM_DELETE;
+exports.ZOO_PERM_READ = NativeZk.ZOO_PERM_READ;
+exports.ZOO_PERM_WRITE = NativeZk.ZOO_PERM_WRITE;
+
+// Log Levels
+exports.ZOO_LOG_LEVEL_ERROR = NativeZk.ZOO_LOG_LEVEL_ERROR;
+exports.ZOO_LOG_LEVEL_WARN = NativeZk.ZOO_LOG_LEVEL_WARN;
+exports.ZOO_LOG_LEVEL_INFO = NativeZk.ZOO_LOG_LEVEL_INFO;
+exports.ZOO_LOG_LEVEL_DEBUG = NativeZk.ZOO_LOG_LEVEL_DEBUG;
+exports.ZOO_LOG_LEVEL_ERROR = NativeZk.ZOO_LOG_LEVEL_ERROR;
+
+////////////////////////////////////////////////////////////////////////////////
+// Methods
+////////////////////////////////////////////////////////////////////////////////
+
+ZooKeeper.prototype.setLogger = function(logger) {
+ if(logger === true) {
+ this.logger = function logger(str) {
+ console.log("ZOOKEEPER_LOG: " + str);
+ }
+ } else if(logger === false) {
+ this.logger = undefined;
+ } else if(_.isFunction(logger)) {
+ this.logger = logger;
+ } else {
+ throw new Error("InvalidArgument: logger must be a function or true/false to utilize default logger");
+ }
+}
+
+ZooKeeper.prototype.init = function init() {
+ if(this.logger) this.logger("Calling init with " + util.inspect(arguments));
+ return this._native.init.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.close = function close() {
+ if(this.logger) this.logger("Calling close with " + util.inspect(arguments));
+ return this._native.close.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_create = function a_create() {
+ if(this.logger) this.logger("Calling a_create with " + util.inspect(arguments));
+ return this._native.a_create.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_exists = function a_exists() {
+ if(this.logger) this.logger("Calling a_exists with " + util.inspect(arguments));
+ return this._native.a_exists.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.aw_exists = function aw_exists() {
+ if(this.logger) this.logger("Calling aw_exists with " + util.inspect(arguments));
+ return this._native.aw_exists.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_get = function a_get() {
+ if(this.logger) this.logger("Calling a_get with " + util.inspect(arguments));
+ return this._native.a_get.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.aw_get = function aw_get() {
+ if(this.logger) this.logger("Calling aw_get with " + util.inspect(arguments));
+ return this._native.aw_get.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_get_children = function a_get_children() {
+ if(this.logger) this.logger("Calling a_get_children with " + util.inspect(arguments));
+ return this._native.a_get_children.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.aw_get_children = function aw_get_children() {
+ if(this.logger) this.logger("Calling aw_get_children with " + util.inspect(arguments));
+ return this._native.aw_get_children.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_get_children2 = function a_get_children2() {
+ if(this.logger) this.logger("Calling a_get_children with " + util.inspect(arguments));
+ return this._native.a_get_children2.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.aw_get_children2 = function aw_get_children2() {
+ if(this.logger) this.logger("Calling aw_get_children with " + util.inspect(arguments));
+ return this._native.aw_get_children2.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_set = function a_set() {
+ if(this.logger) this.logger("Calling a_set with " + util.inspect(arguments));
+ return this._native.a_set.apply(this._native, arguments);
+}
+
+ZooKeeper.prototype.a_delete_ = function a_delete_() {
+ if(this.logger) this.logger("Calling a_delete_ with " + util.inspect(arguments));
+ return this._native.a_delete_.apply(this._native, arguments);
+}
+
View
@@ -15,7 +15,7 @@
,"dependencies": {
"webworker": ">=0.8.2"
}
- ,"main": "build/default/zookeeper"
+ ,"main": "lib/zookeeper"
,"directories.lib": "build/default/"
,"scripts" : {
"build" : "node-waf configure build"
View
@@ -4,7 +4,6 @@
#include <stdarg.h>
#include <node.h>
#include <node_buffer.h>
-#include <node_events.h>
#include <node_object_wrap.h>
#include <v8-debug.h>
using namespace v8;
@@ -48,15 +47,14 @@ do { \
__callback##_TEM); \
} while (0)
-class ZooKeeper: public EventEmitter {
+class ZooKeeper: public ObjectWrap {
public:
static Persistent<FunctionTemplate> constructor_template;
static void Initialize(v8::Handle<v8::Object> target) {
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New);
constructor_template = Persistent<FunctionTemplate>::New(t);
- constructor_template->Inherit(EventEmitter::constructor_template);
constructor_template->SetClassName(String::NewSymbol("ZooKeeper"));
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
@@ -207,7 +205,9 @@ class ZooKeeper: public EventEmitter {
}
void yield () {
- last_activity = ev_now (EV_A);
+ // DDOPSON-2011-11-17 the line following this comment is breaking the build do to a redefinition of 'EV_A' in Node v0.5/6.x
+ // I am commenting it out because the timeout logic in this module has no effect. read "zk_timer_cb" to convince yourself of this...
+ // last_activity = ev_now (EV_A);
int rc = zookeeper_interest (zhandle, &fd, &interest, &tv);
if (rc != ZOK) {
LOG_ERROR(("yield:zookeeper_interest returned error: %d - %s\n", rc, zerror(rc)));
@@ -345,16 +345,26 @@ class ZooKeeper: public EventEmitter {
void DoEmit (Handle<String> event_name, const char* path = NULL) {
HandleScope scope;
- Local<Value> argv[2];
- argv[0] = Local<Value>::New(handle_);
+ Local<Value> argv[3];
@Woodya
Woodya Dec 16, 2011 Collaborator

could you explain this a bit?
Dit event emitting change b/c you're changing the event, or b/c of a node.js api change in 0.6?

@ddopson
ddopson Dec 16, 2011 Collaborator

Node v0.6.x (actually, v0.5.x) removed the native EventEmitter class. This broke, well, pretty much all native modules. The only documentation on writing native modules was a link to node-postgres as an example, and at the time I checked (v0.6.2 or so), THAT module was still broken.

The common solution to the issue was to move event emitting into Javascript, adding a wrapper layer around the native module. There were a couple of other things that made this important / useful:

  • the node-waf building changed the default build dir from "build/default" to "build/Release". Thus, the package.json had no way to reference the native module safely for the "main" property. In JS land, we can do a try/catch to attempt the new location and fallback to the old location, abstracting the problem away from module users. This too has precedence in other native modules.
+ argv[0] = Local<Value>::New(event_name);
+ argv[1] = Local<Value>::New(handle_);
if (path != 0) {
- argv[1] = String::New(path);
+ argv[2] = String::New(path);
LOG_DEBUG (("calling Emit(%s, path='%s')", *String::Utf8Value(event_name), path));
} else {
- argv[1] = Local<Value>::New(Undefined());
+ argv[2] = Local<Value>::New(Undefined());
LOG_DEBUG (("calling Emit(%s, path=null)", *String::Utf8Value(event_name)));
}
- Emit(event_name, 2, argv);
+ Local<Value> emit_v = handle_->Get(String::NewSymbol("emit"));
+ assert(emit_v->IsFunction());
+ Local<Function> emit_fn = emit_v.As<Function>();
+
+
+ TryCatch tc;
+ emit_fn->Call(handle_, 3, argv);
+ if(tc.HasCaught()) {
+ FatalException(tc);
+ }
}
#define CALLBACK_PROLOG(args) \
@@ -695,7 +705,7 @@ class ZooKeeper: public EventEmitter {
#define ZERO_MEM(member) bzero(&(member), sizeof(member))
- ZooKeeper () : EventEmitter(), zhandle(0), clientIdFile(0), fd(-1), data_as_buffer(true) {
+ ZooKeeper () : zhandle(0), clientIdFile(0), fd(-1), data_as_buffer(true) {
ZERO_MEM (myid);
ZERO_MEM (zk_io);
ZERO_MEM (zk_timer);
@@ -716,4 +726,6 @@ class ZooKeeper: public EventEmitter {
Persistent<FunctionTemplate> ZooKeeper::constructor_template;
}
-NODE_MODULE(zookeeper, zk::ZooKeeper::Initialize);
+extern "C" void init(Handle<Object> target) {
+ zk::ZooKeeper::Initialize(target);
+}
View
@@ -0,0 +1,5 @@
+I did what I could to fix this tests, but most of them seem not to work.
+
+zk_test_buffer.js -- that one works. everything else, not so much.
+
+I"m not going to debug much further at this time, but I did fix the require statements so that all the tests load and execute. Most of them just hang. Unclear if that's because my ZK server is different or .... whatever. The "promise" stuff is in especially bad shape.
@@ -1,5 +1,4 @@
-require.paths.unshift('./build/default', '../build/default');
-var ZK = require('zookeeper').ZooKeeper,
+var ZK = require("../lib/zookeeper").ZooKeeper,
Buffer = require('buffer').Buffer,
exec = require('child_process').exec;
@@ -25,7 +24,7 @@ zk.on(ZK.on_connected, function (zkk) {
++tests;
zk.data_as_buffer = true;
zkk.a_create('/zk_test_a_get_children.js1', b, ZK.ZOO_SEQUENCE, function(rc, error, path) {
- // console.log(require('sys').inspect(zkk));
+ // console.log(util.inspect(zkk));
if (rc != 0) {
console.log("ERROR zk node1 create result: %d, error: '%s', path=%s", rc, error, path);
zkk.a_delete_(path, 0, function(rcd, errord) { done(rc); });
@@ -1,23 +1,23 @@
-require.paths.unshift('./build/default', '../build/default');
-var ZK = require('zookeeper').ZooKeeper,
+var ZK = require('../lib/zookeeper'),
Buffer = require('buffer').Buffer,
- exec = require('child_process').exec;
+ exec = require('child_process').exec,
+ util = require('util');
var zk = new ZK();
var connect = (process.argv[2] || 'localhost:2181');
var err = false;
zk.init({connect:connect, timeout:5000, debug_level:ZK.ZOO_LOG_LEVEL_WARN, host_order_deterministic:false, data_as_buffer:false});
-zk.on(ZK.on_connected, function (zkk) {
+zk.on('on_connected', function (zkk) {
console.log('zk session established, id=%s', zkk.client_id);
var b = new Buffer('\u00bd + \u00bc = \u00be');
var b2 = new Buffer('\u00bd + \u00bc = \u00be :: \u00bd + \u00bc = \u00be');
function phase2() {
zk.data_as_buffer = true;
zkk.a_create('/node.js1', b, ZK.ZOO_SEQUENCE | ZK.ZOO_EPHEMERAL, function(rc, error, path) {
- // console.log(require('sys').inspect(zkk));
- if (rc != 0) {
+ // console.log(util.inspect(zkk));
+ if (rc != 0 && rc != -110) {
console.log("zk node create result: %d, error: '%s', path=%s", rc, error, path);
} else {
// now get it
@@ -26,7 +26,7 @@ zk.on(ZK.on_connected, function (zkk) {
zkk.a_get(path, false, function(rc3, error3, stat3, value3) { // response
if( Buffer.isBuffer(value3) === false ) {
console.log('ERROR (p2) value3 is not a Buffer, is: ' + (typeof(value3)));
- console.log(require('sys').inspect(value3));
+ console.log(util.inspect(value3));
err = true;
}
if( err == false ) {
@@ -41,17 +41,20 @@ zk.on(ZK.on_connected, function (zkk) {
}
zkk.a_create('/node.js1', b, ZK.ZOO_SEQUENCE | ZK.ZOO_EPHEMERAL, function(rc, error, path) {
- console.log(require('sys').inspect(zkk));
- if (rc != 0) {
+ console.log(util.inspect(zkk));
+ if (rc != 0 && rc != -110) { // -110 means "already created"
console.log("zk node create result: %d, error: '%s', path=%s", rc, error, path);
} else {
+ console.log("now getting the thing");
// now get it
zkk.a_get(path, false, function(rc, error, stat, value) { // response
+ console.log("get returned, now setting the thing");
zkk.a_set(path, b2, 0, function(rc2, error2, stat2) { // response
+ console.log("set returned, now getting the thing");
zkk.a_get(path, false, function(rc3, error3, stat3, value3) { // response
if( Buffer.isBuffer(value3) ) {
console.log('ERROR (p1) value3 should be a Buffer, is: ' + (typeof(value3)));
- console.log(require('sys').inspect(value3));
+ console.log(util.inspect(value3));
err = true;
}
setTimeout(phase2, 1);
@@ -1,8 +1,6 @@
-require.paths.unshift('./build/default', '../build/default');
var assert = require ('assert');
-var sys = require ('sys');
-
-var ZK = require ("zookeeper").ZooKeeper;
+var util = require('util');
+var ZK = require ("../lib/zookeeper").ZooKeeper;
if (process.argv.length < 2)
throw new Error ("must supply number of sessions (optionally)");
@@ -1,6 +1,4 @@
-require.paths.unshift('./build/default', '../build/default');
-var ZK = require ("zookeeper").ZooKeeper;
-var sys = require("sys");
+var ZK = require ("../lib/zookeeper").ZooKeeper;
if (process.argv.length < 3)
throw new Error ("must supply number of nodes to create and number of sessions (optionally)");
@@ -1,6 +1,3 @@
-require.paths.unshift('./build/default', '../build/default');
-require.paths.unshift('./node-promise', '../node-promise');
-require.paths.unshift('./lib', '../lib');
/*
Shootout is played by the following rules:
@@ -34,8 +31,8 @@ game #2:
Also note how the looping is implemented. Recursion in node.js does not cause stack growth. It's not a tail recursion either...
*/
-var promise = require("zookeeper/promise");
-var ZK = require("zookeeper/zk_promise").ZK;
+var promise = require("../lib/promise");
+var ZK = require("../lib/zk_promise").ZK;
var NGames = parseInt (process.argv[2] || 1);
var connect = (process.argv[3] || 'localhost:2181');
@@ -1,17 +1,16 @@
-require.paths.unshift('./build/default', '../build/default');
-var ZK = require ("zookeeper").ZooKeeper,
+var ZK = require ("../lib/zookeeper").ZooKeeper,
exec = require('child_process').exec;
var zk = new ZK();
var connect = (process.argv[2] || 'localhost:2181');
zk.init({connect:connect, timeout:200000, debug_level:ZK.ZOO_LOG_LEVEL_WARN, host_order_deterministic:false});
-zk.on(ZK.on_connected, function (zkk) {
+zk.on('connected', function (zkk) {
console.log("zk session established, id=%s", zkk.client_id);
var str = '\u00bd + \u00bc = \u00be';
var data = new String(str);
zkk.a_create("/node.js1", data, ZK.ZOO_SEQUENCE | ZK.ZOO_EPHEMERAL, function(rc, error, path) {
- // console.log(require('sys').inspect(zkk));
+ // console.log(util.inspect(zkk));
if (rc != 0) {
console.log("zk node create result: %d, error: '%s', path=%s", rc, error, path);
} else {
Oops, something went wrong.

0 comments on commit 980a313

Please sign in to comment.