node_cassandra | |
| lib/cassandra.js |
copyright 2011 Yuki Morishitamor.yuki@gmail.com
|
var sys = require('sys'),
thrift = require('thrift'),
Cassandra = require('../gen-nodejs/Cassandra'),
ttype = require('../gen-nodejs/cassandra_types');
|
Cassandra Client
|
var Client = function(host) {
var pair = host.split(/:/);
this.host = pair[0];
this.port = pair[1];
this.defaultCL = {
read: ttype.ConsistencyLevel.QUORUM,
write: ttype.ConsistencyLevel.QUORUM
};
this.state = 0;
}
sys.inherits(Client, process.EventEmitter);
|
Connect to Cassandra cluster
- param: keyspace
keyspace name to use
- param: credential
if given, try login into cassandra
api: public
|
Client.prototype.connect = function(keyspace, credential) {
this.keyspace = keyspace;
this.connected = false;
var args = Array.prototype.slice.call(arguments);
this.connection = thrift.createConnection(this.host, this.port);
this.connection.on('error', function(err) {
this.emit('error',err);
});
this.thrift_client = thrift.createClient(Cassandra, this.connection);
var self = this;
this.connection.on('connect', function(err) {
self.thrift_client.describe_keyspace(self.keyspace, function(err, ksdef) {
if (err) {
self.emit('error', err);
return;
}
self.definition_ = ksdef;
self.column_families_ = {};
var i = ksdef.cf_defs.length;
var cf;
while (i--) {
cf = ksdef.cf_defs[i];
self.column_families_[cf.name] = cf;
}
self.thrift_client.set_keyspace(self.keyspace, function(err) {
if (err) {
selt.emit('error', err);
return;
}
if (credential) {
self.thrift_client.login(
new ttype.AuthenticationRequest(credential), function(err) {
if (err) {
self.emit('error', err);
return;
}
self.emit('connected', self.column_families_);
});
} else {
self.emit('connected', self.column_families_);
}
});
});
});
}
|
Set or get default consistency level
|
Client.prototype.consistencyLevel = function() {
if (arguments.length == 0) {
return this.defaultCL;
} else {
var newCL = arguments[0];
this.defaultCL.read = newCL.read || ttype.ConsistencyLevel.QUORUM;
this.defaultCL.write = newCL.write || ttype.ConsistencyLevel.QUORUM;
}
}
|
Get column family to perform query or mutation
- param: name
ColumnFamily name to get
- return: An
instance of ColumnFamily
|
Client.prototype.getColumnFamily = function(name) {
return new ColumnFamily(this, name);
};
|
Close connection
|
Client.prototype.close = function() {
this.connection.end();
};
|
- param: client
Client
- param: name
name of this Column Family
constructo: r
|
var ColumnFamily = function(client, name) {
this.name = name;
this.queue = [];
this.ready = false;
this.client_ = client;
var self = this;
this.client_.on('connected', function(cfdef) {
var cf = cfdef[self.name];
if (!cf) {
self.client_.emit('error', new Error('Column Family ' + self.name + ' does not exist.'));
}
for (var prop in cf) {
if (cf.hasOwnProperty(prop)) {
self[prop] = cf[prop];
}
}
self.isSuper = self.column_type === 'Super';
self.ready = true;
self.dispatch();
});
};
|
Get data from cassandra
- param: keys
row keys to fetch
- param: columns
optional. which columns to retrieve
- param: options
optional. valid params are start, finish, reversed, count
- param: callback
callback function which called after data retrieval.
|
ColumnFamily.prototype.get = function() {
var args = Array.prototype.slice.call(arguments);
if (!this.ready) {
this.queue.push([arguments.callee, args]);
return;
}
var callback;
if (typeof args[args.length - 1] === 'function') {
callback = args.pop();
}
var keys = args.shift();
if (!(keys instanceof Array)) {
keys = [keys];
}
var method_args = this.isSuper ? this.parseArgumentsForSuperCF_(args) : this.parseArgumentsForStandardCF_(args);
var column_parent = method_args[0];
var predicate = method_args[1];
var cl = method_args[2] || this.client_.defaultCL.read;
var self = this;
this.client_.thrift_client.multiget_slice(
keys, column_parent, predicate, cl,
function(err, res) {
if (err) {
callback(err, obj);
}
var obj = {};
var key, col, sub_col;
for (key in res) {
if (res.hasOwnProperty(key)) {
obj[key] = {};
var i = res[key].length;
while (i--) {
col = res[key][i].super_column;
if (col) {
obj[key][col.name] = {};
var j = col.columns.length;
while (j--) {
sub_col = col.columns[j];
obj[key][col.name][sub_col.name] = sub_col.value;
}
} else {
col = res[key][i].column;
obj[key][col.name] = col.value;
}
}
}
}
if (keys.length == 1) {
obj = obj[keys[0]];
}
callback(err, obj);
});
};
|
Get column count from cassandra
- param: keys
row keys to fetch
- param: columns
optional. which columns to retrieve
- param: options
optional. valid params are start, finish, reversed, count
- param: callback
callback function which called after data retrieval.
|
ColumnFamily.prototype.count = function() {
var args = Array.prototype.slice.call(arguments);
if (!this.ready) {
this.queue.push([arguments.callee, args]);
return;
}
var callback;
if (typeof args[args.length - 1] === 'function') {
callback = args.pop();
}
var keys = args.shift();
if (!(keys instanceof Array)) {
keys = [keys];
}
var method_args = this.isSuper ? this.parseArgumentsForSuperCF_(args) : this.parseArgumentsForStandardCF_(args);
var column_parent = method_args[0];
var predicate = method_args[1];
var cl = method_args[2] || this.client_.defaultCL.read;
this.client_.thrift_client.multiget_count(
keys, column_parent, predicate, cl,
function(err, res) {
if (err) {
callback(err, obj);
}
var obj = {};
var key, count;
for (key in res) {
if (res.hasOwnProperty(key)) {
obj[key] = res[key];
}
}
if (keys.length == 1) {
obj = obj[keys[0]];
}
callback(err, obj);
});
};
|
slice data
|
ColumnFamily.prototype.slice = function() {
this.client_.emit('error', new Error('slice(get_range_slices, get_indexed_slices) not supported.'));
};
|
set (insert or update) data
|
ColumnFamily.prototype.set = function() {
var args = Array.prototype.slice.call(arguments);
if (!this.ready) {
this.queue.push([arguments.callee, args]);
return;
}
var callback;
if (typeof args[args.length - 1] === 'function') {
callback = args.pop();
}
var key = args.shift();
var values = args.shift() || {};
var ts = new Date().getTime();
var prop, value;
var mutations = [], columns;
if (this.isSuper) {
for (prop in values) {
if (values.hasOwnProperty(prop)) {
columns = [];
value = values[prop];
for (var col in value) {
columns.push(new ttype.Column({
name: col,
value: '' + value[col],
timestamp: ts,
ttl: null
}));
}
mutations.push(new ttype.Mutation({
column_or_supercolumn: new ttype.ColumnOrSuperColumn({
super_column: new ttype.SuperColumn({
name: prop,
columns: columns
})
})
}));
}
}
} else {
for (prop in values) {
mutations.push(new ttype.Mutation({
column_or_supercolumn: new ttype.ColumnOrSuperColumn({
column: new ttype.Column({
name: prop,
value: '' + values[prop],
timestamp: ts,
ttl: null
})
})
}));
}
}
var mutation_map = {};
mutation_map[key] = {};
mutation_map[key][this.name] = mutations;
this.client_.thrift_client.batch_mutate(
mutation_map, ttype.ConsistencyLevel.ONE, callback);
};
|
remove data
|
ColumnFamily.prototype.remove = function() {
var args = Array.prototype.slice.call(arguments);
if (!this.ready) {
this.queue.push([arguments.callee, args]);
return;
}
var callback;
if (typeof args[args.length - 1] === 'function') {
callback = args.pop();
}
var key = args.shift();
var method_args = this.isSuper ? this.parseArgumentsForSuperCF_(args) : this.parseArgumentsForStandardCF_(args);
var column_parent = method_args[0];
var predicate = method_args[1];
var cl = method_args[2] || this.client_.defaultCL.write;
var ts = new Date().getTime();
var mutations = [];
mutations.push(new ttype.Mutation({
deletion: new ttype.Deletion({
timestamp: ts,
super_column: column_parent.super_column,
predicate: predicate.column_names ? predicate : null
})
}));
var mutation_map = {};
mutation_map[key] = {};
mutation_map[key][this.name] = mutations;
this.client_.thrift_client.batch_mutate(mutation_map, cl, callback);
};
|
truncate this column family
|
ColumnFamily.prototype.truncate = function() {
var args = Array.prototype.slice.call(arguments);
if (!this.ready) {
this.queue.push([arguments.callee, args]);
return;
}
var callback = args.shift();
this.client_.thrift_client.truncate(this.name, callback);
}
|
module exports
|
exports.Client = Client;
exports.ConsistencyLevel = ttype.ConsistencyLevel;
|