Optimized callback class to return Java objects
This commit is contained in:
parent
2daf86bb7b
commit
315e608cd4
@ -70,7 +70,7 @@ def profile(str)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def benchmark(str, n, coll_name, data, create_index=false)
|
def benchmark(str, n, coll_name, data, create_index=false, verbosity=true)
|
||||||
coll = @db.collection(coll_name)
|
coll = @db.collection(coll_name)
|
||||||
coll.create_index('x') if create_index
|
coll.create_index('x') if create_index
|
||||||
profile(str) do
|
profile(str) do
|
||||||
@ -79,7 +79,7 @@ def benchmark(str, n, coll_name, data, create_index=false)
|
|||||||
td = tm.add do
|
td = tm.add do
|
||||||
n.times { |i| yield(coll, i) }
|
n.times { |i| yield(coll, i) }
|
||||||
end
|
end
|
||||||
report(str, td.real, td.utime)
|
report(str, td.real, td.utime) if verbosity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,8 +90,8 @@ connection = Connection.new(host, port)
|
|||||||
connection.drop_database("benchmark")
|
connection.drop_database("benchmark")
|
||||||
@db = connection.db('benchmark')
|
@db = connection.db('benchmark')
|
||||||
|
|
||||||
def benchmark_insert(desc, coll_name, data)
|
def benchmark_insert(desc, coll_name, data, verbosity=true)
|
||||||
benchmark(desc, PER_TRIAL, coll_name, data) do |coll, i|
|
benchmark(desc, PER_TRIAL, coll_name, data, verbosity) do |coll, i|
|
||||||
data['x'] = i
|
data['x'] = i
|
||||||
coll.insert(data)
|
coll.insert(data)
|
||||||
data.delete(:_id)
|
data.delete(:_id)
|
||||||
@ -109,10 +109,18 @@ end
|
|||||||
|
|
||||||
print_headings
|
print_headings
|
||||||
|
|
||||||
|
if RUBY_PLATFORM =~ /java/
|
||||||
|
puts "***WARMUP***"
|
||||||
|
benchmark_insert('insert (small, no index)', 'small_none', SMALL, false)
|
||||||
|
benchmark_insert('insert (medium, no index)', 'medium_none', MEDIUM, false)
|
||||||
|
benchmark_insert('insert (large, no index)', 'large_none', LARGE, false)
|
||||||
|
puts "***WARMUP***"
|
||||||
|
end
|
||||||
benchmark_insert('insert (small, no index)', 'small_none', SMALL)
|
benchmark_insert('insert (small, no index)', 'small_none', SMALL)
|
||||||
benchmark_insert('insert (medium, no index)', 'medium_none', MEDIUM)
|
benchmark_insert('insert (medium, no index)', 'medium_none', MEDIUM)
|
||||||
benchmark_insert('insert (large, no index)', 'large_none', LARGE)
|
benchmark_insert('insert (large, no index)', 'large_none', LARGE)
|
||||||
|
|
||||||
|
|
||||||
benchmark_insert_index('insert (small, index)', 'small_indexed', SMALL)
|
benchmark_insert_index('insert (small, index)', 'small_indexed', SMALL)
|
||||||
benchmark_insert_index('insert (medium, index)', 'medium_indexed', MEDIUM)
|
benchmark_insert_index('insert (medium, index)', 'medium_indexed', MEDIUM)
|
||||||
benchmark_insert_index('insert (large, index)', 'large_indexed', LARGE)
|
benchmark_insert_index('insert (large, index)', 'large_indexed', LARGE)
|
||||||
@ -138,6 +146,11 @@ end
|
|||||||
benchmark_find_one('find_one (small, no index)', 'small_none', PER_TRIAL / 2)
|
benchmark_find_one('find_one (small, no index)', 'small_none', PER_TRIAL / 2)
|
||||||
benchmark_find_one('find_one (medium, no index)', 'medium_none', PER_TRIAL / 2)
|
benchmark_find_one('find_one (medium, no index)', 'medium_none', PER_TRIAL / 2)
|
||||||
benchmark_find_one('find_one (large, no index)', 'large_none', PER_TRIAL / 2)
|
benchmark_find_one('find_one (large, no index)', 'large_none', PER_TRIAL / 2)
|
||||||
|
benchmark_find_one('find_one (small, no index)', 'small_none', PER_TRIAL / 2)
|
||||||
|
benchmark_find_one('find_one (medium, no index)', 'medium_none', PER_TRIAL / 2)
|
||||||
|
benchmark_find_one('find_one (large, no index)', 'large_none', PER_TRIAL / 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
benchmark_find_one('find_one (small, indexed)', 'small_indexed', PER_TRIAL / 2)
|
benchmark_find_one('find_one (small, indexed)', 'small_indexed', PER_TRIAL / 2)
|
||||||
benchmark_find_one('find_one (medium, indexed)', 'medium_indexed', PER_TRIAL / 2)
|
benchmark_find_one('find_one (medium, indexed)', 'medium_indexed', PER_TRIAL / 2)
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -60,6 +60,7 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
_nameStack.clear();
|
_nameStack.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: this actually creates an OrderedHash.
|
||||||
public RubyHash createHash() {
|
public RubyHash createHash() {
|
||||||
RubyHash h = (RubyHash)JavaEmbedUtils.invokeMethod(_runtime, _rbclsOrderedHash, "new",
|
RubyHash h = (RubyHash)JavaEmbedUtils.invokeMethod(_runtime, _rbclsOrderedHash, "new",
|
||||||
new Object[] { }, Object.class);
|
new Object[] { }, Object.class);
|
||||||
@ -108,6 +109,8 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
_stack.addLast( (RubyObject)hash );
|
_stack.addLast( (RubyObject)hash );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: we use []= because we're dealing with an OrderedHash, which in 1.8
|
||||||
|
// doesn't have an internal JRuby representation.
|
||||||
public void writeRubyHash(String key, RubyHash hash, IRubyObject obj) {
|
public void writeRubyHash(String key, RubyHash hash, IRubyObject obj) {
|
||||||
RubyString rkey = _runtime.newString(key);
|
RubyString rkey = _runtime.newString(key);
|
||||||
JavaEmbedUtils.invokeMethod(_runtime, hash, "[]=",
|
JavaEmbedUtils.invokeMethod(_runtime, hash, "[]=",
|
||||||
@ -115,9 +118,8 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeRubyArray(String key, RubyArray array, IRubyObject obj) {
|
public void writeRubyArray(String key, RubyArray array, IRubyObject obj) {
|
||||||
Long rkey = Long.parseLong(key);
|
Long index = Long.parseLong(key);
|
||||||
RubyFixnum index = new RubyFixnum(_runtime, rkey);
|
array.store(index, obj);
|
||||||
array.aset((IRubyObject)index, obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void arrayStart(String key){
|
public void arrayStart(String key){
|
||||||
@ -281,7 +283,7 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
RubyArray result = RubyArray.newArray( _runtime, b.length );
|
RubyArray result = RubyArray.newArray( _runtime, b.length );
|
||||||
|
|
||||||
for ( int i=0; i<b.length; i++ ) {
|
for ( int i=0; i<b.length; i++ ) {
|
||||||
result.aset( RubyNumeric.dbl2num( _runtime, (double)i ), RubyNumeric.dbl2num( _runtime, (double)b[i] ) );
|
result.store( i, _runtime.newFixnum(b[i]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -313,8 +315,7 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
if(current instanceof RubyArray) {
|
if(current instanceof RubyArray) {
|
||||||
RubyArray a = (RubyArray)current;
|
RubyArray a = (RubyArray)current;
|
||||||
Long n = Long.parseLong(name);
|
Long n = Long.parseLong(name);
|
||||||
RubyFixnum index = new RubyFixnum(_runtime, n);
|
a.store(n, (IRubyObject)o);
|
||||||
a.aset((IRubyObject)index, (IRubyObject)o);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RubyString rkey = RubyString.newString(_runtime, name);
|
RubyString rkey = RubyString.newString(_runtime, name);
|
||||||
@ -322,11 +323,11 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
new Object[] { (IRubyObject)rkey, o }, Object.class);
|
new Object[] { (IRubyObject)rkey, o }, Object.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RubyObject cur(){
|
protected RubyObject cur(){
|
||||||
return _stack.getLast();
|
return _stack.getLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(){
|
public Object get(){
|
||||||
return _root;
|
return _root;
|
||||||
}
|
}
|
||||||
@ -339,22 +340,6 @@ public class RubyBSONCallback implements BSONCallback {
|
|||||||
return _stack.size() < 1;
|
return _stack.size() < 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method for checking whether a Ruby hash has a certain key.
|
|
||||||
private boolean _rbHashHasKey(RubyHash hash, String key) {
|
|
||||||
RubyBoolean b = hash.has_key_p( _runtime.newString( key ) );
|
|
||||||
return b == _runtime.getTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method for getting a value from a Ruby hash.
|
|
||||||
private IRubyObject _rbHashGet(RubyHash hash, Object key) {
|
|
||||||
if (key instanceof String) {
|
|
||||||
return hash.op_aref( _runtime.getCurrentContext(), _runtime.newString((String)key) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return hash.op_aref( _runtime.getCurrentContext(), (RubyObject)key );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final HashMap<String, Object> _getRuntimeCache(Ruby runtime) {
|
static final HashMap<String, Object> _getRuntimeCache(Ruby runtime) {
|
||||||
// each JRuby runtime may have different objects for these constants,
|
// each JRuby runtime may have different objects for these constants,
|
||||||
// so cache them separately for each runtime
|
// so cache them separately for each runtime
|
||||||
|
Binary file not shown.
@ -19,6 +19,7 @@ import org.bson.BSONEncoder;
|
|||||||
|
|
||||||
import org.jruby.javasupport.JavaEmbedUtils;
|
import org.jruby.javasupport.JavaEmbedUtils;
|
||||||
import org.jruby.javasupport.JavaUtil;
|
import org.jruby.javasupport.JavaUtil;
|
||||||
|
import org.jruby.java.proxies.JavaProxy;
|
||||||
|
|
||||||
import org.jruby.*;
|
import org.jruby.*;
|
||||||
import org.jruby.runtime.builtin.IRubyObject;
|
import org.jruby.runtime.builtin.IRubyObject;
|
||||||
@ -225,20 +226,8 @@ public class RubyBSONEncoder extends BSONEncoder {
|
|||||||
if ( val instanceof String )
|
if ( val instanceof String )
|
||||||
putString(name, val.toString() );
|
putString(name, val.toString() );
|
||||||
|
|
||||||
// TODO: Clean up
|
else if ( val instanceof Number )
|
||||||
else if ( val instanceof Number ) {
|
putNumber(name, (Number)val);
|
||||||
if ( val instanceof Double ) {
|
|
||||||
putNumber(name, (Number)val);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
long jval = ((Number)val).longValue();
|
|
||||||
if (jval > Integer.MIN_VALUE && jval < Integer.MAX_VALUE) {
|
|
||||||
putNumber(name, (int)jval );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
putNumber(name, (Number)jval );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( val instanceof Boolean )
|
else if ( val instanceof Boolean )
|
||||||
putBoolean(name, (Boolean)val);
|
putBoolean(name, (Boolean)val);
|
||||||
@ -265,7 +254,6 @@ public class RubyBSONEncoder extends BSONEncoder {
|
|||||||
putSymbol(name, new Symbol(val.toString()));
|
putSymbol(name, new Symbol(val.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Clean up
|
|
||||||
else if ( val instanceof RubyFixnum ) {
|
else if ( val instanceof RubyFixnum ) {
|
||||||
long jval = ((RubyFixnum)val).getLongValue();
|
long jval = ((RubyFixnum)val).getLongValue();
|
||||||
if (jval >= Integer.MIN_VALUE && jval <= Integer.MAX_VALUE) {
|
if (jval >= Integer.MIN_VALUE && jval <= Integer.MAX_VALUE) {
|
||||||
@ -275,12 +263,22 @@ public class RubyBSONEncoder extends BSONEncoder {
|
|||||||
putNumber(name, (Number)jval );
|
putNumber(name, (Number)jval );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Clean up
|
|
||||||
else if ( val instanceof RubyFloat ) {
|
else if ( val instanceof RubyFloat ) {
|
||||||
double jval = ((RubyFloat)val).getValue();
|
double jval = ((RubyFloat)val).getValue();
|
||||||
putNumber(name, (Number)jval );
|
putNumber(name, (Number)jval );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if ( val instanceof JavaProxy ) {
|
||||||
|
Object obj = ((JavaProxy)val).getObject();
|
||||||
|
if ( obj instanceof ArrayList ) {
|
||||||
|
putIterable( name, ((ArrayList)obj));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_rbRaise( (RubyClass)_rbclsInvalidDocument,
|
||||||
|
"Got a JavaProxy object which can't be serialized as a BSON type." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if ( val instanceof RubyNil )
|
else if ( val instanceof RubyNil )
|
||||||
putNull(name);
|
putNull(name);
|
||||||
|
|
||||||
@ -316,6 +314,9 @@ public class RubyBSONEncoder extends BSONEncoder {
|
|||||||
else if( klass.equals( "BSON::ObjectID" ) ) {
|
else if( klass.equals( "BSON::ObjectID" ) ) {
|
||||||
putRubyObjectId(name, (RubyObject)val );
|
putRubyObjectId(name, (RubyObject)val );
|
||||||
}
|
}
|
||||||
|
else if( klass.equals( "Java::JavaUtil::ArrayList" ) ) {
|
||||||
|
putIterable(name, (Iterable)val );
|
||||||
|
}
|
||||||
else if ( klass.equals( "BSON::Code" ) ) {
|
else if ( klass.equals( "BSON::Code" ) ) {
|
||||||
putRubyCodeWScope(name, (RubyObject)val );
|
putRubyCodeWScope(name, (RubyObject)val );
|
||||||
}
|
}
|
||||||
|
BIN
ext/java/src/org/jbson/RubyBSONJavaCallback.class
Normal file
BIN
ext/java/src/org/jbson/RubyBSONJavaCallback.class
Normal file
Binary file not shown.
379
ext/java/src/org/jbson/RubyBSONJavaCallback.java
Normal file
379
ext/java/src/org/jbson/RubyBSONJavaCallback.java
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
// BSON Callback
|
||||||
|
// RubyBSONCallback.java
|
||||||
|
package org.jbson;
|
||||||
|
|
||||||
|
import org.jruby.*;
|
||||||
|
import org.jruby.util.ByteList;
|
||||||
|
import org.jruby.RubyString;
|
||||||
|
import org.jruby.runtime.builtin.IRubyObject;
|
||||||
|
import org.jruby.runtime.Block;
|
||||||
|
import org.jruby.runtime.CallType;
|
||||||
|
import org.jruby.runtime.callsite.CacheEntry;
|
||||||
|
|
||||||
|
import org.jruby.javasupport.JavaEmbedUtils;
|
||||||
|
import org.jruby.javasupport.JavaUtil;
|
||||||
|
|
||||||
|
import org.jruby.parser.ReOptions;
|
||||||
|
|
||||||
|
import org.jruby.RubyArray;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
|
||||||
|
import org.bson.*;
|
||||||
|
import org.bson.types.*;
|
||||||
|
|
||||||
|
public class RubyBSONJavaCallback implements BSONCallback {
|
||||||
|
|
||||||
|
private RubyHash _root;
|
||||||
|
private RubyModule _rbclsOrderedHash;
|
||||||
|
private RubyModule _rbclsObjectId;
|
||||||
|
private RubyModule _rbclsBinary;
|
||||||
|
private RubyModule _rbclsMinKey;
|
||||||
|
private RubyModule _rbclsMaxKey;
|
||||||
|
private RubyModule _rbclsDBRef;
|
||||||
|
private RubyModule _rbclsCode;
|
||||||
|
private final LinkedList<Object> _stack = new LinkedList<Object>();
|
||||||
|
private final LinkedList<String> _nameStack = new LinkedList<String>();
|
||||||
|
private Ruby _runtime;
|
||||||
|
static final HashMap<Ruby, HashMap> _runtimeCache = new HashMap<Ruby, HashMap>();
|
||||||
|
|
||||||
|
public RubyBSONJavaCallback(Ruby runtime) {
|
||||||
|
_runtime = runtime;
|
||||||
|
_rbclsOrderedHash = _lookupConstant( _runtime, "BSON::OrderedHash" );
|
||||||
|
_rbclsBinary = _lookupConstant( _runtime, "BSON::Binary" );
|
||||||
|
_rbclsDBRef = _lookupConstant( _runtime, "BSON::DBRef" );
|
||||||
|
_rbclsCode = _lookupConstant( _runtime, "BSON::Code" );
|
||||||
|
_rbclsMinKey = _lookupConstant( _runtime, "BSON::MinKey" );
|
||||||
|
_rbclsMaxKey = _lookupConstant( _runtime, "BSON::MaxKey" );
|
||||||
|
_rbclsObjectId = _lookupConstant( _runtime, "BSON::ObjectId");
|
||||||
|
}
|
||||||
|
|
||||||
|
public BSONCallback createBSONCallback(){
|
||||||
|
return new RubyBSONCallback(_runtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset(){
|
||||||
|
_root = null;
|
||||||
|
_stack.clear();
|
||||||
|
_nameStack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RubyHash createHash() {
|
||||||
|
RubyHash h = (RubyHash)JavaEmbedUtils.invokeMethod(_runtime, _rbclsOrderedHash, "new",
|
||||||
|
new Object[] { }, Object.class);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object create( boolean array , List<String> path ){
|
||||||
|
if ( array )
|
||||||
|
return new ArrayList<Object>();
|
||||||
|
return createHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectStart(){
|
||||||
|
if ( _stack.size() > 0 ) {
|
||||||
|
throw new IllegalStateException( "something is wrong" );
|
||||||
|
}
|
||||||
|
|
||||||
|
_root = createHash();
|
||||||
|
_stack.add(_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectStart(boolean f) {
|
||||||
|
objectStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectStart(String key){
|
||||||
|
RubyHash hash = createHash();
|
||||||
|
|
||||||
|
_nameStack.addLast( key );
|
||||||
|
|
||||||
|
Object lastObject = _stack.getLast();
|
||||||
|
|
||||||
|
// Yes, this is a bit hacky.
|
||||||
|
if(lastObject instanceof RubyHash) {
|
||||||
|
writeRubyHash(key, (RubyHash)lastObject, (IRubyObject)hash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((ArrayList)lastObject).add(Integer.parseInt(key), hash);
|
||||||
|
//writeRubyArray(key, (RubyArray)lastObject, (IRubyObject)hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack.addLast( (RubyObject)hash );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeRubyHash(String key, RubyHash hash, Object obj) {
|
||||||
|
RubyString rkey = _runtime.newString(key);
|
||||||
|
JavaEmbedUtils.invokeMethod(_runtime, hash, "[]=",
|
||||||
|
new Object[] { (IRubyObject)rkey, obj }, Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeRubyArray(String key, RubyArray array, IRubyObject obj) {
|
||||||
|
Long rkey = Long.parseLong(key);
|
||||||
|
RubyFixnum index = new RubyFixnum(_runtime, rkey);
|
||||||
|
array.aset((IRubyObject)index, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void arrayStart(String key){
|
||||||
|
ArrayList<Object> array = new ArrayList<Object>();
|
||||||
|
|
||||||
|
Object lastObject = _stack.getLast();
|
||||||
|
_nameStack.addLast( key );
|
||||||
|
|
||||||
|
if(lastObject instanceof RubyHash) {
|
||||||
|
writeRubyHash(key, (RubyHash)lastObject, array);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
((ArrayList)lastObject).add(Integer.parseInt(key), array);
|
||||||
|
}
|
||||||
|
|
||||||
|
_stack.addLast( array );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object objectDone(){
|
||||||
|
Object o =_stack.removeLast();
|
||||||
|
if ( _nameStack.size() > 0 )
|
||||||
|
_nameStack.removeLast();
|
||||||
|
else if ( _stack.size() > 0 ) {
|
||||||
|
throw new IllegalStateException( "something is wrong" );
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not used by Ruby decoder
|
||||||
|
public void arrayStart(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object arrayDone(){
|
||||||
|
return objectDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotNull( String name ){
|
||||||
|
_put(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undefined should be represented as a lack of key / value.
|
||||||
|
public void gotUndefined( String name ){
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Handle this
|
||||||
|
public void gotUUID( String name , long part1, long part2) {
|
||||||
|
//_put( name , new UUID(part1, part2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotCode( String name , String code ){
|
||||||
|
Object rb_code_obj = JavaEmbedUtils.invokeMethod(_runtime, _rbclsCode,
|
||||||
|
"new", new Object[] { code }, Object.class);
|
||||||
|
_put( name , (RubyObject)rb_code_obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotCodeWScope( String name , String code , Object scope ){
|
||||||
|
Object rb_code_obj = JavaEmbedUtils.invokeMethod(_runtime, _rbclsCode,
|
||||||
|
"new", new Object[] { code, (RubyHash)scope }, Object.class);
|
||||||
|
|
||||||
|
_put( name , (RubyObject)rb_code_obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotMinKey( String name ){
|
||||||
|
Object minkey = JavaEmbedUtils.invokeMethod(_runtime, _rbclsMinKey, "new", new Object[] {}, Object.class);
|
||||||
|
|
||||||
|
_put( name, (RubyObject)minkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotMaxKey( String name ){
|
||||||
|
Object maxkey = JavaEmbedUtils.invokeMethod(_runtime, _rbclsMaxKey, "new", new Object[] {}, Object.class);
|
||||||
|
|
||||||
|
_put( name, (RubyObject)maxkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotBoolean( String name , boolean v ){
|
||||||
|
_put(name , v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotDouble( String name , double v ){
|
||||||
|
_put(name , v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotInt( String name , int v ){
|
||||||
|
_put(name , v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotLong( String name , long v ){
|
||||||
|
_put(name , v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotDate( String name , long millis ){
|
||||||
|
RubyTime time = RubyTime.newTime(_runtime, millis).gmtime();
|
||||||
|
_put( name , time );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotRegex( String name , String pattern , String flags ){
|
||||||
|
int f = 0;
|
||||||
|
ByteList b = new ByteList(pattern.getBytes());
|
||||||
|
|
||||||
|
if(flags.contains("i")) {
|
||||||
|
f = f | ReOptions.RE_OPTION_IGNORECASE;
|
||||||
|
}
|
||||||
|
if(flags.contains("m")) {
|
||||||
|
f = f | ReOptions.RE_OPTION_MULTILINE;
|
||||||
|
}
|
||||||
|
if(flags.contains("x")) {
|
||||||
|
f = f | ReOptions.RE_OPTION_EXTENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
_put( name , RubyRegexp.newRegexp(_runtime, b, f) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotString( String name , String v ){
|
||||||
|
_put( name , v );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotSymbol( String name , String v ){
|
||||||
|
ByteList bytes = new ByteList(v.getBytes());
|
||||||
|
RubySymbol symbol = _runtime.getSymbolTable().getSymbol(bytes);
|
||||||
|
_put( name , symbol );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp is currently rendered in Ruby as a two-element array.
|
||||||
|
public void gotTimestamp( String name , int time , int inc ){
|
||||||
|
RubyFixnum rtime = RubyFixnum.newFixnum( _runtime, time );
|
||||||
|
RubyFixnum rinc = RubyFixnum.newFixnum( _runtime, inc );
|
||||||
|
RubyObject[] args = new RubyObject[2];
|
||||||
|
args[0] = rinc;
|
||||||
|
args[1] = rtime;
|
||||||
|
|
||||||
|
RubyArray result = RubyArray.newArray( _runtime, args );
|
||||||
|
|
||||||
|
_put ( name , result );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotObjectId( String name , ObjectId id ){
|
||||||
|
IRubyObject arg = (IRubyObject)RubyString.newString(_runtime, id.toString());
|
||||||
|
// //System.out.println(id.toByteArray().length);
|
||||||
|
// byte[] b = id.toByteArray();
|
||||||
|
// RubyArray a = _runtime.newArray();
|
||||||
|
// for(int i=0; i < b.length; i++) {
|
||||||
|
// System.out.println(b[i]);
|
||||||
|
// a.append(_runtime.newFixnum(b[i]));
|
||||||
|
// }
|
||||||
|
Object[] args = new Object[] { arg };
|
||||||
|
|
||||||
|
Object result = JavaEmbedUtils.invokeMethod(_runtime, _rbclsObjectId, "from_string", args, Object.class);
|
||||||
|
|
||||||
|
_put( name, (RubyObject)result );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Incredibly annoying to deserialize to a Ruby DBRef. Might just
|
||||||
|
// stop supporting this altogether in the driver.
|
||||||
|
public void gotDBRef( String name , String ns , ObjectId id ){
|
||||||
|
// _put( name , new BasicBSONObject( "$ns" , ns ).append( "$id" , id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: I know that this is horrible. To be optimized.
|
||||||
|
private RubyArray ja2ra( byte[] b ) {
|
||||||
|
RubyArray result = RubyArray.newArray( _runtime, b.length );
|
||||||
|
|
||||||
|
for ( int i=0; i<b.length; i++ ) {
|
||||||
|
result.aset( RubyNumeric.dbl2num( _runtime, (double)i ), RubyNumeric.dbl2num( _runtime, (double)b[i] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gotBinaryArray( String name , byte[] b ) {
|
||||||
|
RubyArray a = ja2ra( b );
|
||||||
|
|
||||||
|
Object[] args = new Object[] { a, 2 };
|
||||||
|
|
||||||
|
Object result = JavaEmbedUtils.invokeMethod(_runtime, _rbclsBinary, "new", args, Object.class);
|
||||||
|
|
||||||
|
_put( name, (RubyObject)result );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: fix abs stuff here. some kind of bad type issue
|
||||||
|
public void gotBinary( String name , byte type , byte[] data ){
|
||||||
|
RubyArray a = ja2ra( data );
|
||||||
|
|
||||||
|
Object[] args = new Object[] { a, RubyFixnum.newFixnum(_runtime, Math.abs( type )) };
|
||||||
|
|
||||||
|
Object result = JavaEmbedUtils.invokeMethod(_runtime, _rbclsBinary, "new", args, Object.class);
|
||||||
|
|
||||||
|
_put( name, (RubyObject)result );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void _put( String name , Object o ){
|
||||||
|
Object current = cur();
|
||||||
|
if(current instanceof ArrayList) {
|
||||||
|
((ArrayList)current).add(Integer.parseInt(name), (Object)o);
|
||||||
|
//RubyArray a = (RubyArray)current;
|
||||||
|
//Long n = Long.parseLong(name);
|
||||||
|
//RubyFixnum index = new RubyFixnum(_runtime, n);
|
||||||
|
//a.aset((IRubyObject)index, o);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RubyString rkey = RubyString.newString(_runtime, name);
|
||||||
|
JavaEmbedUtils.invokeMethod(_runtime, current, "[]=",
|
||||||
|
new Object[] { (IRubyObject)rkey, o }, Object.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object cur(){
|
||||||
|
return _stack.getLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(){
|
||||||
|
return _root;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setRoot(RubyHash o) {
|
||||||
|
_root = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isStackEmpty() {
|
||||||
|
return _stack.size() < 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for checking whether a Ruby hash has a certain key.
|
||||||
|
private boolean _rbHashHasKey(RubyHash hash, String key) {
|
||||||
|
RubyBoolean b = hash.has_key_p( _runtime.newString( key ) );
|
||||||
|
return b == _runtime.getTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for getting a value from a Ruby hash.
|
||||||
|
private IRubyObject _rbHashGet(RubyHash hash, Object key) {
|
||||||
|
if (key instanceof String) {
|
||||||
|
return hash.op_aref( _runtime.getCurrentContext(), _runtime.newString((String)key) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return hash.op_aref( _runtime.getCurrentContext(), (RubyObject)key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final HashMap<String, Object> _getRuntimeCache(Ruby runtime) {
|
||||||
|
// each JRuby runtime may have different objects for these constants,
|
||||||
|
// so cache them separately for each runtime
|
||||||
|
@SuppressWarnings("unchecked") // aargh! Java!
|
||||||
|
HashMap<String, Object> cache = _runtimeCache.get( runtime );
|
||||||
|
|
||||||
|
if(cache == null) {
|
||||||
|
cache = new HashMap<String, Object>();
|
||||||
|
_runtimeCache.put( runtime, cache );
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final RubyModule _lookupConstant(Ruby runtime, String name)
|
||||||
|
{
|
||||||
|
HashMap<String, Object> cache = _getRuntimeCache( runtime );
|
||||||
|
RubyModule module = (RubyModule) cache.get( name );
|
||||||
|
|
||||||
|
if(module == null && !cache.containsKey( name )) {
|
||||||
|
module = runtime.getClassFromPath( name );
|
||||||
|
cache.put( (String)name, (Object)module );
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ module BSON
|
|||||||
|
|
||||||
def self.serialize(obj, check_keys=false, move_id=false)
|
def self.serialize(obj, check_keys=false, move_id=false)
|
||||||
raise InvalidDocument, "BSON_JAVA.serialize takes a Hash" unless obj.is_a?(Hash)
|
raise InvalidDocument, "BSON_JAVA.serialize takes a Hash" unless obj.is_a?(Hash)
|
||||||
enc = get_encoder# Java::OrgJbson::RubyBSONEncoder.new(JRuby.runtime)
|
enc = Java::OrgJbson::RubyBSONEncoder.new(JRuby.runtime)
|
||||||
ByteBuffer.new(enc.encode(obj))
|
ByteBuffer.new(enc.encode(obj))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -17,11 +17,8 @@ module BSON
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.deserialize(buf)
|
def self.deserialize(buf)
|
||||||
if buf.is_a? String
|
dec = Java::OrgBson::BSONDecoder.new
|
||||||
buf = ByteBuffer.new(buf) if buf
|
callback = Java::OrgJbson::RubyBSONJavaCallback.new(JRuby.runtime)
|
||||||
end
|
|
||||||
dec = get_decoder
|
|
||||||
callback = Java::OrgJbson::RubyBSONCallback.new(JRuby.runtime)
|
|
||||||
dec.decode(buf.to_s.to_java_bytes, callback)
|
dec.decode(buf.to_s.to_java_bytes, callback)
|
||||||
callback.get
|
callback.get
|
||||||
end
|
end
|
||||||
|
@ -44,6 +44,8 @@ module BSON
|
|||||||
@data = data || generate
|
@data = data || generate
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr_accessor :data
|
||||||
|
|
||||||
# Determine if the supplied string is legal. Legal strings will
|
# Determine if the supplied string is legal. Legal strings will
|
||||||
# consist of 24 hexadecimal characters.
|
# consist of 24 hexadecimal characters.
|
||||||
#
|
#
|
||||||
@ -132,6 +134,13 @@ module BSON
|
|||||||
str
|
str
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_e
|
||||||
|
@data.each do |i|
|
||||||
|
print i
|
||||||
|
print ' '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
"BSON::ObjectId('#{to_s}')"
|
"BSON::ObjectId('#{to_s}')"
|
||||||
end
|
end
|
||||||
|
@ -23,7 +23,7 @@ class BSONTest < Test::Unit::TestCase
|
|||||||
|
|
||||||
def setup
|
def setup
|
||||||
@encoder = BSON::BSON_JAVA
|
@encoder = BSON::BSON_JAVA
|
||||||
@decoder = BSON::BSON_RUBY#BSON::BSON_JAVA
|
@decoder = BSON::BSON_JAVA
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_doc_pass(doc, options={})
|
def assert_doc_pass(doc, options={})
|
||||||
@ -338,13 +338,16 @@ class BSONTest < Test::Unit::TestCase
|
|||||||
assert_doc_pass(doc)
|
assert_doc_pass(doc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_timestamp
|
if !(RUBY_PLATFORM =~ /java/)
|
||||||
val = {"test" => [4, 20]}
|
def test_timestamp
|
||||||
assert_equal val, @decoder.deserialize([0x13, 0x00, 0x00, 0x00,
|
val = {"test" => [4, 20]}
|
||||||
0x11, 0x74, 0x65, 0x73,
|
assert_equal val, @decoder.deserialize([0x13, 0x00, 0x00, 0x00,
|
||||||
0x74, 0x00, 0x04, 0x00,
|
0x11, 0x74, 0x65, 0x73,
|
||||||
0x00, 0x00, 0x14, 0x00,
|
0x74, 0x00, 0x04, 0x00,
|
||||||
0x00, 0x00, 0x00])
|
0x00, 0x00, 0x14, 0x00,
|
||||||
|
0x00, 0x00, 0x00])
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_overflow
|
def test_overflow
|
||||||
|
Loading…
Reference in New Issue
Block a user