October 14, 2010

Starting Membase with NodeJS

Happily, I've recently found an intersection of tasks that I can roll into a single, quick, unified project.  Here's a small subset of my to-do list...
 
- build some automated Membase/Moxi cluster testing, with a large number of nodes
- show how folks can use TAP streams in Membase for great good
- learn more about that other new hot thing, nodejs
- blog more
 
Clearly, the stars are aligned for me to build a Membase cluster exerciser, in nodejs, and blog about it along the way.  I certainly hope to learn a lot about nodejs by doing this, and I hope to impart some practical knowledge to you about Membase.
 
Membase allows users to connect using either of the two memcached
protocols: ascii or binary.
 
TAP streams, however, are memcached binary protocol only.  Step one, then, is to ensure that nodejs can support raw binary TCP communication, which it certainly can through its binary buffer encodings.  However, nodejs seems to be missing the classic ntohl and htonl functions out of the box that are needed for any binary protocol manipulations.
 
As a gentle start, then, here's a first contribution to the nodejs world, which is a nodejs implementation of the ntohl/htonl functions...
 
-----------------------------------------------------------------------
/* Copyright 2010 Membase, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
exports.htons = function(b, i, v) {
  b[i]   = (0xff & (v >> 8));
  b[i+1] = (0xff & (v));
}
exports.ntohs = function(b, i) {
  return ((0xff & b[i + 0]) << 8) |
         ((0xff & b[i + 1]));
}
exports.ntohsStr = function(s, i) {
  return ((0xff & s.charCodeAt(i + 0)) << 8) |
         ((0xff & s.charCodeAt(i + 1))); }
exports.htonl = function(b, i, v) {
  b[i+0] = (0xff & (v >> 24));
  b[i+1] = (0xff & (v >> 16));
  b[i+2] = (0xff & (v >> 8));
  b[i+3] = (0xff & (v));
}
exports.ntohl = function(b, i) {
  return ((0xff & b[i + 0]) << 24) |
         ((0xff & b[i + 1]) << 16) |
         ((0xff & b[i + 2]) << 8) |
         ((0xff & b[i + 3]));
}
exports.ntohlStr = function(s, i) {
  return ((0xff & s.charCodeAt(i + 0)) << 24) |
         ((0xff & s.charCodeAt(i + 1)) << 16) |
         ((0xff & s.charCodeAt(i + 2)) << 8) |
         ((0xff & s.charCodeAt(i + 3))); }
-----------------------------------------------------------------------
This JavaScript stuff might actually go places.  Above, a "b" parameter may either be an Array of octets or a nodejs Buffer.  A "s" parameter is a JavaScript string. "i" is a zero-based index into an Array/Buffer/String.
 
More's coming soon, where I'll next show how to create a connection to Membase in nodejs and encode and decode binary protocol messages to Membase.

Comments