[Pkg-javascript-commits] [node-leveldown] 07/492: batch binary, improved batch interface

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Sun Jul 6 17:13:38 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to annotated tag rocksdb-0.10.1
in repository node-leveldown.

commit 254b6a2e97e4ffe903e9cbc8c5be3d7dbef4f994
Author: Rod Vagg <rod at vagg.org>
Date:   Sun Jul 15 14:35:28 2012 +1000

    batch binary, improved batch interface
---
 lib/levelup.js      | 50 ++++++++++++++++++++++++++++++++------------------
 src/batch.cc        | 13 +++++--------
 src/batch.h         | 19 ++++++-------------
 src/database.cc     | 50 +++++++++++++++++++-------------------------------
 test/binary-test.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 112 insertions(+), 70 deletions(-)

diff --git a/lib/levelup.js b/lib/levelup.js
index fd6ac0f..5cb32e1 100644
--- a/lib/levelup.js
+++ b/lib/levelup.js
@@ -39,7 +39,7 @@ var bridge              = require('../build/Release/levelup')
     }
 
   , toBuffer = function (data, encoding) {
-      return Buffer.isBuffer(data) ? data : new Buffer('' + data, encoding)
+      return data === undefined || data === null || Buffer.isBuffer(data) ? data : new Buffer('' + data, encoding)
     }
 
   , toEncoding = function (buffer, encoding) {
@@ -98,6 +98,7 @@ var bridge              = require('../build/Release/levelup')
                   return callback(err)
                 throw err
               }
+               // reference to key to prevent premature GC
               callback && callback(null, toEncoding(value, options.valueEncoding || options.encoding), key)
             })
           } else
@@ -118,7 +119,7 @@ var bridge              = require('../build/Release/levelup')
                   return callback(err)
                 throw err
               }
-              callback && callback(null, key, value)
+              callback && callback(null, key, value)  // reference to key&value to prevent premature GC
             })
           } else
             callback(new errors.ReadError('Database has not been opened'))
@@ -137,7 +138,7 @@ var bridge              = require('../build/Release/levelup')
                   return callback(err)
                 throw err
               }
-              callback && callback(null, key)
+              callback && callback(null, key) // reference to key to prevent premature GC
             })
           } else
             callback(new errors.ReadError('Database has not been opened'))
@@ -145,22 +146,35 @@ var bridge              = require('../build/Release/levelup')
 
       , batch: function (arr, options_, callback_) {
           var callback = getCallback(options_, callback_)
-            , options
-          if (this.isOpen()) {
-            options = getOptions(options_, this.encoding)
-            this.db.batch(arr, options, function (err) {
-              if (err) {
-                err = new errors.WriteError(err)
-                if (callback)
-                  return callback(err)
-                throw err
+            , options, keyEncoding, valueEncoding
+
+          if (!this.isOpen())
+            return callback(new errors.ReadError('Database has not been opened'))
+
+          options       = getOptions(options_, this.encoding)
+          keyEncoding   = options.keyEncoding   || options.encoding
+          valueEncoding = options.valueEncoding || options.encoding
+          arr           = arr.map(function (e) {
+            var o = {}
+            if (e.type) {
+              o.type = e.type
+              if (e.key) {
+                o.key = toBuffer(e.key, keyEncoding)
+                if (e.value)
+                  o.value = toBuffer(e.value, valueEncoding)
               }
-              // reference to 'arr' important to keep from being garbage collected
-              // we don't keep a Persistent<T> reference in the bridge
-              callback && callback(null, arr)
-            })
-          } else
-            callback(new errors.ReadError('Database has not been opened'))
+            }
+            return o
+          })
+          this.db.batch(arr, options, function (err) {
+            if (err) {
+              err = new errors.WriteError(err)
+              if (callback)
+                return callback(err)
+              throw err
+            }
+            callback && callback(null)
+          })
         }
     }
 
diff --git a/src/batch.cc b/src/batch.cc
index ef2309f..9a4ccd2 100644
--- a/src/batch.cc
+++ b/src/batch.cc
@@ -8,21 +8,18 @@
 using namespace std;
 
 BatchDelete::~BatchDelete () {
-  if (keyPtr != NULL)
-    delete keyPtr;
+  delete key;
 }
 
 void BatchDelete::Execute (WriteBatch* batch) {
-  batch->Delete(key);
+  batch->Delete(Slice(*key));
 }
 
 BatchWrite::~BatchWrite () {
-  if (keyPtr != NULL)
-    delete keyPtr;
-  if (valuePtr != NULL)
-    delete valuePtr;
+  delete key;
+  delete value;
 }
 
 void BatchWrite::Execute (WriteBatch* batch) {
-  batch->Put(key, value);
+  batch->Put(Slice(*key), Slice(*value));
 }
\ No newline at end of file
diff --git a/src/batch.h b/src/batch.h
index eb1cd81..3860670 100644
--- a/src/batch.h
+++ b/src/batch.h
@@ -15,36 +15,29 @@ public:
 class BatchDelete : public BatchOp {
 public:
   BatchDelete (
-      Slice key
-    , string* keyPtr
+      string* key
   ) : key(key)
-    , keyPtr(keyPtr)
   {};
   ~BatchDelete ();
   virtual void Execute (WriteBatch* batch);
 
 protected:
-  Slice key;
-  string* keyPtr;
+  string* key;
 };
 
 class BatchWrite : public BatchDelete {
 public:
   BatchWrite (
-      Slice key
-    , string* keyPtr
-    , Slice value
-    , string* valuePtr
-  ) : BatchDelete(key, keyPtr)
+      string* key
+    , string* value
+  ) : BatchDelete(key)
     , value(value)
-    , valuePtr(valuePtr)
   {};
   ~BatchWrite ();
   virtual void Execute (WriteBatch* batch);
 
 private:
-  Slice value;
-  string* valuePtr;
+  string* value;
 };
 
 #endif
\ No newline at end of file
diff --git a/src/database.cc b/src/database.cc
index 0f5452f..f9cc964 100644
--- a/src/database.cc
+++ b/src/database.cc
@@ -134,9 +134,9 @@ Handle<Value> Database::Put (const Arguments& args) {
 
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
 
-  Local<Object> keyBuffer = args[0]->ToObject();
+  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
   Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
-  Local<Object> valueBuffer = args[1]->ToObject();
+  Persistent<Object> valueBuffer = Persistent<Object>::New(args[1]->ToObject());
   Slice value(Buffer::Data(valueBuffer), Buffer::Length(valueBuffer));
   Local<Object> optionsObj = Local<Object>::Cast(args[2]);
   bool sync = optionsObj->Has(option_sync) && optionsObj->Get(option_sync)->BooleanValue();
@@ -148,8 +148,8 @@ Handle<Value> Database::Put (const Arguments& args) {
     , key
     , value
     , sync
-    , Persistent<Object>::New(keyBuffer)
-    , Persistent<Object>::New(valueBuffer)
+    , keyBuffer
+    , valueBuffer
   );
   AsyncQueueWorker(worker);
 
@@ -160,7 +160,7 @@ Handle<Value> Database::Get (const Arguments& args) {
   HandleScope scope;
 
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
-  Local<Object> keyBuffer = args[0]->ToObject();
+  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
   Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
   //Local<Object> optionsObj = Local<Object>::Cast(args[1]);
   Persistent<Function> callback = Persistent<Function>::New(Local<Function>::Cast(args[2]));
@@ -169,7 +169,7 @@ Handle<Value> Database::Get (const Arguments& args) {
       database
     , callback
     , key
-    , Persistent<Object>::New(keyBuffer)
+    , keyBuffer
   );
   AsyncQueueWorker(worker);
 
@@ -180,7 +180,7 @@ Handle<Value> Database::Delete (const Arguments& args) {
   HandleScope scope;
 
   Database* database = ObjectWrap::Unwrap<Database>(args.This());
-  Local<Object> keyBuffer = args[0]->ToObject();
+  Persistent<Object> keyBuffer = Persistent<Object>::New(args[0]->ToObject());
   Slice key(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
   Local<Object> optionsObj = Local<Object>::Cast(args[1]);
   bool sync = optionsObj->Has(option_sync) && optionsObj->Get(option_sync)->BooleanValue();
@@ -191,7 +191,7 @@ Handle<Value> Database::Delete (const Arguments& args) {
     , callback
     , key
     , sync
-    , Persistent<Object>::New(keyBuffer)
+    , keyBuffer
   );
   AsyncQueueWorker(worker);
 
@@ -213,31 +213,19 @@ Handle<Value> Database::Batch (const Arguments& args) {
     if (!obj->Has(str_type) || !obj->Has(str_key))
       continue;
 
-    Local<Object> keyObj = obj->Get(str_key)->ToObject();
-    string* keyStr = NULL;
-    Slice key;
-    if (Buffer::HasInstance(keyObj))
-      key = Slice(Buffer::Data(keyObj), Buffer::Length(keyObj));
-    else {
-      keyStr = new string(ToCString(String::Utf8Value(keyObj->ToString())));
-      key = *keyStr;
-    }
+    Local<Object> keyBuffer = obj->Get(str_key)->ToObject();
+    if (!keyBuffer->IsObject() || !Buffer::HasInstance(keyBuffer))
+      continue;
+    string* key = new string(Buffer::Data(keyBuffer), Buffer::Length(keyBuffer));
 
     if (obj->Get(str_type)->StrictEquals(str_del)) {
-      operations.push_back(new BatchDelete(key, keyStr));
-    } else if (obj->Get(str_type)->StrictEquals(str_put)) {
-      if (obj->Has(str_value)) {
-        Local<Object> valueObj = obj->Get(str_value)->ToObject();
-        string* valueStr = NULL;
-        Slice value;
-        if (Buffer::HasInstance(valueObj))
-          value = Slice(Buffer::Data(valueObj), Buffer::Length(valueObj));
-        else {
-          valueStr = new string(ToCString(String::Utf8Value(valueObj->ToString())));
-          value = *valueStr;
-        }
-        operations.push_back(new BatchWrite(key, keyStr, value, valueStr));
-      }
+      operations.push_back(new BatchDelete(key));
+    } else if (obj->Get(str_type)->StrictEquals(str_put) && obj->Has(str_value)) {
+      Local<Object> valueBuffer = obj->Get(str_value)->ToObject();
+      if (!valueBuffer->IsObject() || !Buffer::HasInstance(valueBuffer))
+        continue;
+      string* value = new string(Buffer::Data(valueBuffer), Buffer::Length(valueBuffer));     
+      operations.push_back(new BatchWrite(key, value));
     }
   }
 
diff --git a/test/binary-test.js b/test/binary-test.js
index d754879..1fd8464 100644
--- a/test/binary-test.js
+++ b/test/binary-test.js
@@ -8,6 +8,8 @@ var buster  = require('buster')
   , async   = require('async')
   , fs      = require('fs')
 
+require('./common.js')
+
 buster.testCase('Binary API', {
     'setUp': function (done) {
       this.cleanupDirs = []
@@ -92,4 +94,52 @@ buster.testCase('Binary API', {
         }.bind(this))
       }.bind(this))
     }
+
+
+  , 'test put() and del() and get() with binary key {encoding:binary}': function (done) {
+      this.openTestDatabase(function (db) {
+        db.put(this.testData, 'binarydata', {encoding:'binary'}, function (err) {
+          refute(err)
+          db.del(this.testData, {encoding:'binary'}, function (err) {
+            db.get(this.testData, {encoding:'binary'}, function (err, value) {
+              assert(err)
+              done()
+            }.bind(this))
+          }.bind(this))
+        }.bind(this))
+      }.bind(this))
+    }
+
+  , 'batch() with multiple puts': function (done) {
+      this.openTestDatabase(function (db) {
+        db.batch(
+            [
+                { type: 'put', key: 'foo', value: this.testData }
+              , { type: 'put', key: 'bar', value: this.testData }
+              , { type: 'put', key: 'baz', value: 'abazvalue' }
+            ]
+          , {keyEncoding:'utf8',valueEncoding:'binary'}
+          , function (err) {
+              refute(err)
+              async.forEach(
+                  ['foo', 'bar', 'baz']
+                , function (key, callback) {
+                    db.get(key, {encoding:'binary'}, function (err, value) {
+                      refute(err)
+                      if (key == 'baz') {
+                        assert.equals(value, 'a' + key + 'value')
+                        callback()
+                      } else {
+                        checkBinaryTestData(value, callback)
+                      }
+                    })
+                  }
+                , done
+              )
+            }.bind(this)
+        )
+      }.bind(this))
+    }
+
+
 })
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-leveldown.git



More information about the Pkg-javascript-commits mailing list