module Nmdb
require "nmdb_ll"
class NetworkException < StandardError
end
class GenericDB
attr_accessor :automarshal
attr_accessor :default
def initialize(default = nil)
@db = Nmdb_ll::DB.new
@automarshal = true
@default = default
end
def add_tipc_server(port = -1)
return @db.add_tipc_server(port)
end
def add_tcp_server(host, port = 26010)
return @db.add_tcp_server(host, port)
end
def add_udp_server(host, port = 26010)
return @db.add_udp_server(host, port)
end
def add_sctp_server(host, port = 26010)
return @db.add_sctp_server(host, port)
end
def normal_set(key, val)
if @automarshal then
key = Marshal.dump(key)
val = Marshal.dump(val)
end
return @db.set(key, val)
end
def set_sync(key, val)
if @automarshal then
key = Marshal.dump(key)
val = Marshal.dump(val)
end
return @db.set_sync(key, val)
end
def cache_set(key, val)
if @automarshal then
key = Marshal.dump(key)
val = Marshal.dump(val)
end
return @db.cache_set(key, val)
end
def generic_get(gfunc, key)
if @automarshal then
key = Marshal.dump(key)
end
r = gfunc.call(key)
if r.class == String then
if @automarshal then
r = Marshal.load(r)
end
return r
elsif r == -1 then
# key not in the database
return @default
elsif r <= 2 then
raise NetworkException
else
# we should never get here
raise Exception
end
end
def normal_get(key)
return generic_get(@db.method(:get), key)
end
def cache_get(key)
return generic_get(@db.method(:cache_get), key)
end
def normal_delete(key)
if @automarshal then
key = Marshal.dump(key)
end
return @db.del(key)
end
def cache_delete(key)
if @automarshal then
key = Marshal.dump(key)
end
return @db.cache_del(key)
end
def delete_sync(key)
if @automarshal then
key = Marshal.dump(key)
end
return @db.del_sync(key)
end
def generic_cas(gfunc, key, old, new)
if @automarshal then
key = Marshal.dump(key)
old = Marshal.dump(old)
new = Marshal.dump(new)
end
r = gfunc.call(key, old, new)
if r == 0 then
# key not in the database
return nil
elsif r < 0 then
raise NetworkException
else
return r
end
end
def normal_cas(key, old, new)
return generic_cas(@db.method(:cas), key, old, new)
end
def cache_cas(key, old, new)
return generic_cas(@db.method(:cache_cas), key, old, new)
end
def generic_incr(gfunc, key, increment)
if @automarshal then
key = Marshal.dump(key)
end
r, v = gfunc.call(key, increment)
if r == 0 then
# key not in the database
return nil
elsif r == 1 or r < 0 then
raise NetworkException
else
return v
end
end
def normal_incr(key, increment)
return generic_incr(@db.method(:incr), key, increment)
end
def cache_incr(key, increment)
return generic_incr(@db.method(:cache_incr), key, increment)
end
# The following functions asume we have set(), get(), delete() and
# cas(), which are supposed to be implemented by our subclasses
def include?(key)
# we assume we have get() implemented
return get(key) == @default
end
def []=(key, val)
return set(key, val)
end
def [](key)
return get(key)
end
end
class DB < GenericDB
alias set normal_set
alias get normal_get
alias delete normal_delete
alias cas normal_cas
alias incr normal_incr
end
class Cache < GenericDB
alias set cache_set
alias get cache_get
alias delete cache_delete
alias cas cache_cas
alias incr cache_cas
end
class Sync < GenericDB
alias set set_sync
alias get normal_get
alias delete delete_sync
alias cas normal_cas
alias incr normal_cas
end
end