Skip to content

Instantly share code, notes, and snippets.

@erickdavidson
Created October 6, 2011 00:06
Show Gist options
  • Save erickdavidson/1266124 to your computer and use it in GitHub Desktop.
Save erickdavidson/1266124 to your computer and use it in GitHub Desktop.
diff --git a/lib/memcached.js b/lib/memcached.js
index c3e4f26..64a7a01 100644
--- a/lib/memcached.js
+++ b/lib/memcached.js
@@ -78,7 +78,8 @@ Client.config = {
, BUFFER = 1E2
, CONTINUE = 1E1
, FLAG_JSON = 1<<1
- , FLAG_BINARY = 2<<1;
+ , FLAG_BINARY = 2<<1
+ , FLAG_COMPRESSED = 3;
var memcached = nMemcached.prototype = new EventEmitter
, private = {}
@@ -192,10 +193,14 @@ Client.config = {
if (error) return query.callback && query.callback(error);
if (S.readyState !== 'open') return query.callback && query.callback('Connection readyState is set to ' + S.readySate);
+ var lineBreakValue = new Buffer((new Buffer(query.command, 'binary')).length + 2);
+ lineBreakValue.write(query.command, 0, 'binary');
+ lineBreakValue.write(LINEBREAK, query.command.length, 'binary');
+
// used for request timing
query.start = Date.now();
S.metaData.push(query);
- S.write(query.command + LINEBREAK);
+ S.write(new Buffer(lineBreakValue.toString('binary'), 'binary'));
});
// if we have redundancy enabled and the query is used for redundancy, than we are going loop over
@@ -300,6 +305,9 @@ Client.config = {
case FLAG_JSON:
dataSet = JSON.parse(dataSet);
break;
+ case FLAG_COMPRESSED:
+ dataSet = zlib.inflate(new Buffer(dataSet, 'binary'));
+ break;
case FLAG_BINARY:
tmp = new Buffer(dataSet.length);
tmp.write(dataSet, 0, 'binary');
@@ -410,7 +418,7 @@ Client.config = {
// or even right in the middle of a line-break, so we need to make sure, the last piece in the buffer is a LINEBREAK
// because that is all what is sure about the Memcached Protocol, all responds end with them.
private.buffer = function BufferBuffer(S, BufferStream){
- S.responseBuffer += BufferStream;
+ S.responseBuffer += BufferStream.toString('binary');
// only call transform the data once we are sure, 100% sure, that we valid response ending
if (S.responseBuffer.substr(S.responseBuffer.length - 2) === LINEBREAK){
@@ -588,26 +596,45 @@ Client.config = {
// function to ease maintenance. This is possible because most set commands will use the same
// syntax for the Memcached server. Some commands do not require a lifetime and a flag, but the
// memcached server is smart enough to ignore those.
- private.setters = function setters(type, validate, key, value, lifetime, callback, cas){
+ private.setters = function setters(type, validate, key, value, lifetime, compress, callback, cas){
var flag = 0
, memcached = this
, valuetype = typeof value
, length;
if (Buffer.isBuffer(value)){
- flag = FLAG_BINARY;
+ if (compress) {
+ flag = FLAG_COMPRESSED;
+ value = new Buffer(zlib.deflate(value), 'binary');
+ } else {
+ flag = FLAG_BINARY;
+ }
+ length = value.length;
value = value.toString('binary');
} else if (valuetype !== 'string' && valuetype !== 'number'){
flag = FLAG_JSON;
value = JSON.stringify(value);
+ length = Buffer.byteLength(value);
} else {
value = value.toString();
+ length = Buffer.byteLength(value);
}
length = Buffer.byteLength(value);
if (length > memcached.maxValue) return private.errorResponse('The length of the value is greater than ' + memcached.maxValue, callback);
- memcached.command(function settersCommand(noreply){ return {
+ var lineBreakValue = new Buffer((new Buffer(value, 'binary')).length + 2);
+ lineBreakValue.write(LINEBREAK, 0, 'binary');
+ lineBreakValue.write(value, 2, 'binary');
+
+ memcached.command(function settersCommand(noreply){
+
+ var commandBuffer = new Buffer([type, key, flag, lifetime, length].join(' ') + (cas ? ' ' + cas : '') + (noreply ? NOREPLY : ''), 'binary');
+ var commandWithValue = new Buffer(commandBuffer.length + lineBreakValue.length);
+ commandBuffer.copy(commandWithValue, 0, 0);
+ lineBreakValue.copy(commandWithValue, commandBuffer.length, 0);
+
+ return {
key: key
, callback: callback
, lifetime: lifetime
@@ -616,15 +643,11 @@ Client.config = {
, validate: validate
, type: type
, redundancyEnabled: true
- , command: [type, key, flag, lifetime, length].join(' ') +
- (cas ? ' ' + cas : '') +
- (noreply ? NOREPLY : '') +
- LINEBREAK + value
- }});
+ , command: commandWithValue.toString('binary') }});
};
// Curry the function and so we can tell the type our private set function
- memcached.set = Utils.curry(false, private.setters, 'set', [['key', String], ['lifetime', Number], ['value', String], ['callback', Function]]);
+ memcached.set = Utils.curry(false, private.setters, 'set', [['key', String], ['lifetime', Number], ['value', String], ['compress', Boolean], ['callback', Function]]);
memcached.replace = Utils.curry(false, private.setters, 'replace', [['key', String], ['lifetime', Number], ['value', String], ['callback', Function]]);
memcached.add = Utils.curry(false, private.setters, 'add', [['key', String], ['lifetime', Number], ['value', String], ['callback', Function]]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment