Skip to content

Commit

Permalink
Implemented full request protocol for 1 query per request, got answer…
Browse files Browse the repository at this point in the history
… from server
  • Loading branch information
kurokikaze committed Jan 11, 2010
1 parent 7d267ee commit 4529332
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 38 deletions.
40 changes: 29 additions & 11 deletions bits.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@
(function () {

var chr, proto;

exports.Encoder = function (header) {
this.header = header || "";

exports.Encoder = function (ServerCommand, ClientCommand) {
// if (ServerCommand & ClientCommand) {
this.header = encode_int16(ServerCommand) + encode_int16(ClientCommand);
// } else {
// this.header = "";
// }
this.data = "";
};

chr = String.fromCharCode;
proto = exports.Encoder.prototype;

// Factor out the encode so it can be shared by add_header and push_int32
function encode_int32(number) {
var a, b, c, d, unsigned;
Expand All @@ -31,9 +35,23 @@
return chr(a) + chr(b) + chr(c) + chr(d);
}

function encode_int16(number) {
var a, b, unsigned;
unsigned = (number < 0) ? (number + 0x10000) : number;
a = Math.floor(unsigned / 0xff);
unsigned &= 0xff;
b = Math.floor(unsigned);
return chr(a) + chr(b);
}

// Add a postgres header to the binary string and return it.
proto.toString = function () {
return this.header + encode_int32(this.data.length + 4) + this.data;
return this.header + encode_int32(this.data.length + 4) + encode_int32(1) + this.data;
};

// Return data without headers (e.g. for negotiating with server about protocol version)
proto.toRawString = function () {
return this.data;
};

// Encode number as 32 bit 2s compliment
Expand Down Expand Up @@ -70,7 +88,7 @@
this.data += fields.join("\0") + "\0\0";
return this;
};

proto.push_hash = function (hash) {
for (var key in hash) {
if (hash.hasOwnProperty(key)) {
Expand All @@ -87,9 +105,9 @@
// TODO: Convert to use a moving pointer instead of creating a new substring
// each iteration. This will help performance a bit on parsing.
(function () {

var proto;

exports.Decoder = function (data) {
this.data = data;
};
Expand Down Expand Up @@ -122,7 +140,7 @@
this.data = this.data.substr(len);
return string;
};

// Grab a null terminated string
proto.shift_cstring = function () {
var pos, string;
Expand All @@ -131,7 +149,7 @@
this.data = this.data.substr(pos + 1);
return string;
};

// Grab a null terminated array of null terminated strings
proto.shift_multi_cstring = function () {
var pos, string;
Expand All @@ -140,7 +158,7 @@
this.data = this.data.substr(pos + 1);
return string;
};


}());

Expand Down
109 changes: 82 additions & 27 deletions limestone.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// http://pastebin.com/f262be9bc

var binary = require('./binary');
var bits = require('./bits');
var tcp = require('tcp');
var sys = require('sys');

Expand Down Expand Up @@ -66,7 +66,7 @@ var Sphinx = {

// Current version client commands
Sphinx.clientCommand = {
"SEARCH": 0x116,
"SEARCH": 278,
"EXCERPT": 0x100,
"UPDATE": 0x102,
"KEYWORDS": 0x100,
Expand All @@ -92,41 +92,90 @@ var Sphinx = {
// server_conn.send(parseInt('00000000',2));
// server_conn.send(parseInt('00000001',2));
// server_conn.send(0x00000001);
server_conn.send(binary.pack('N', 1));
server_conn.send((new bits.Encoder()).push_int32(1).toRawString(), 'binary');

// Waiting for answer
server_conn.addListener('receive', function(data) {
var data_unpacked = binary.unpack('N*', data);
// var data_unpacked = binary.unpack('N*', data);
var receive_listeners = server_conn.listeners('receive');
var i;
for (i = 0; i < receive_listeners.length; i++) {
server_conn.removeListener('receive', receive_listeners[i]);
}
var protocol_version = (new bits.Decoder(data)).shift_int32();
var data_unpacked = {'': 1};

var composeQuery = function(query) {
var req_main = binary.pack("NNNNN", 0, 20, Sphinx.searchMode.ALL, Sphinx.rankingMode.BM25, Sphinx.sortMode.RELEVANCE); // mode and limits
var req_sortby = binary.pack("N", 0); // "sort by" is not supported yet
var req_query_length = binary.pack('N', query.length); // Watch out for Unicode string length
var req_query = query; // We need to send it in separate object for it to be converted to ASCII
var req_weights = binary.pack( "N", 0); // weights is not supported yet
var req_index = binary.pack("N", 1) + '*'; // Watch out for string length
var req_marker = binary.pack('N', 1); // id64 range
// Header


var request = (new bits.Encoder(0, 278)).push_int32(0).push_int32(20).push_int32(Sphinx.searchMode.ALL).push_int32(Sphinx.rankingMode.BM25).push_int32(Sphinx.sortMode.RELEVANCE);

// var req_main = binary.pack("NNNNN", 0, 20, Sphinx.searchMode.ALL, Sphinx.rankingMode.BM25, Sphinx.sortMode.RELEVANCE); // mode and limits

request.push_int32(0);
// var req_sortby = binary.pack("N", 0); // "sort by" is not supported yet

request.push_int32(query.length);
// var req_query_length = binary.pack('N', query.length); // Watch out for Unicode string length

request.push_raw_string(query);
// var req_query = query; // We need to send it in separate object for it to be converted to ASCII

request.push_int32(0);
// var req_weights = binary.pack( "N", 0); // weights is not supported yet

request.push_int32(1).push_raw_string('*');
//var req_index = binary.pack("N", 1) + '*'; // Watch out for string length
request.push_int32(1);
//var req_marker = binary.pack('N', 1); // id64 range
request.push_int32(0).push_int32(0).push_int32(0).push_int32(0); // No limits for range

var req_filters = binary.pack("N", 0); // filters is not supported yet
var req_grouping = binary.pack("NN", Sphinx.groupMode.DAY, 0); // Basic grouping is supported
request.push_int32(0);
// var req_filters = binary.pack("N", 0); // filters is not supported yet
request.push_int32(Sphinx.groupMode.DAY);
request.push_int32(0); // Groupby length
// var req_grouping = binary.pack("NN", Sphinx.groupMode.DAY, 0); // Basic grouping is supported

var req_anchor = binary.pack("N", 0); // anchor is not supported yet
var req_indexWeights = binary.pack("N", 0); // Per-index weights is not supported yet
var req_maxQueryTime = binary.pack("N", 0); // Max query time is set to 0
var req_fieldWeights = binary.pack("N", 0); // Per-field weights is not supported yet
request.push_int32(1000); // Maxmatches, default to 1000

var req_comment = binary.pack("N", 0); // Comments is not supported yet
var req_overrides = binary.pack("N", 0); // Atribute overrides is not supported yet
request.push_int32("@group desc".length); // Groupsort
request.push_raw_string("@group desc");

var req_select = binary.pack("N", 1) + '*'; // Watch out for string length
request.push_int32(0); // Cutoff
request.push_int32(0); // Retrycount
request.push_int32(0); // Retrydelay

var req = req_main + req_sortby + req_query_length + req_query + req_weights + req_index + req_marker + req_filters + req_grouping + req_anchor + req_indexWeights + req_maxQueryTime + req_fieldWeights + req_comment + req_overrides + req_select;
request.push_int32(0); // Group distinct

request.push_int32(0);
// var req_anchor = binary.pack("N", 0); // anchor is not supported yet
request.push_int32(0);
// var req_indexWeights = binary.pack("N", 0); // Per-index weights is not supported yet
request.push_int32(0);
// var req_maxQueryTime = binary.pack("N", 0); // Max query time is set to 0
request.push_int32(0);
// var req_fieldWeights = binary.pack("N", 0); // Per-field weights is not supported yet

request.push_int32(0);
// var req_comment = binary.pack("N", 0); // Comments is not supported yet
request.push_int32(0);
// var req_overrides = binary.pack("N", 0); // Atribute overrides is not supported yet

request.push_int32(1).push_raw_string('*');
// var req_select = binary.pack("N", 1) + '*'; // Watch out for string length

// request.push_int32(0);
// var req = req_main + req_sortby + req_query_length + req_query + req_weights + req_index + req_marker + req_filters + req_grouping + req_anchor + req_indexWeights + req_maxQueryTime + req_fieldWeights + req_comment + req_overrides + req_select;

// Add header to request
var request = binary.pack('nnNN', Sphinx.command.SEARCH, Sphinx.clientCommand.SEARCH, req.length, 1) + req;
// var request = binary.pack('nnNN', Sphinx.command.SEARCH, Sphinx.clientCommand.SEARCH, req.length, 1) + req;

server_conn.send(request, 'binary');
server_conn.send(binary.pack('N', 0x00), 'binary'); // end of query

// var request_header = (new bits.Encoder()).push_int16(Sphinx.command.SEARCH).push_int16(Sphinx.clientCommand.SEARCH).push_int32(request.toString().length).push_int32(1);
// server_conn.send(request_header.toString(), 'binary');
server_conn.send(request.toString(), 'binary');
// server_conn.send(binary.pack('N', 0x00), 'binary'); // end of query

/* server_conn.send(binary.pack('nnNN', Sphinx.command.SEARCH, Sphinx.clientCommand.SEARCH, 20 + query.length, 1), 'binary');
server_conn.send(req_main, 'binary');
Expand All @@ -152,14 +201,19 @@ var Sphinx = {
*/


sys.puts('Request sent [' + (24 + query.length) + ']');
sys.puts('Request sent: [' + request.toString().length + ']');
var x;
for (x = 0; x < request.toString().length; x++) {
sys.puts(x + ':' + request.toString().charCodeAt(x).toString(16));
}

server_conn.addListener('receive', function(data) {
// Got response!
sys.puts('Answer received:' + data + '[' + data.length + ']');
});
};

sys.puts('Server data received: ' + JSON.stringify(data_unpacked));
sys.puts('Server data received: ' + protocol_version);
if (data_unpacked[""] >= 1) {

// Remove listener after handshaking
Expand All @@ -170,8 +224,9 @@ var Sphinx = {
server_conn.removeListener('receive');
// Here is our answer. It contains 1+
sys.puts('Connection established, sending query');
sys.puts('text'.length);

composeQuery('Simple');
composeQuery('text');

//server_conn.close();
}
Expand Down

0 comments on commit 4529332

Please sign in to comment.