lmdb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +8 -0
- data/ext/lmdb_ext/cursor_delete_flags.h +1 -0
- data/ext/lmdb_ext/cursor_put_flags.h +2 -0
- data/ext/lmdb_ext/dbi_flags.h +7 -0
- data/ext/lmdb_ext/env_flags.h +8 -0
- data/ext/lmdb_ext/flag_parser.h +14 -0
- data/ext/lmdb_ext/lmdb_ext.c +237 -160
- data/ext/lmdb_ext/lmdb_ext.h +22 -15
- data/ext/lmdb_ext/put_flags.h +5 -0
- data/lib/lmdb/database.rb +26 -0
- data/lib/lmdb/version.rb +3 -0
- data/lib/lmdb.rb +2 -28
- data/lmdb.gemspec +4 -1
- data/spec/lmdb_spec.rb +63 -44
- metadata +11 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e65d2930d0d2e7812f17f527cec9e28227ff86d3
         | 
| 4 | 
            +
              data.tar.gz: 9b1be0c534d29babf1ecfb665bc0a93f1cadc158
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 79f1fa24f25e0c3dc0971df47ed6eea2d5f2e388a244f6354586c1a15c0cd9934ff302391a7a51b46f50534ddeb5c1b126e842ffb6e59773967e5e5ef49e35dd
         | 
| 7 | 
            +
              data.tar.gz: 29a36534234f8da14bce75b157add7d4f259e94addf60e32a2faaf2edf4f84d168580e85090803d4eb16bf095a05c5546c6ea172835ba0d2098305d78d02c4cd
         | 
    
        data/CHANGES
    CHANGED
    
    
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            FLAG(NODUPDATA, nodupdata)
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            static int METHOD(VALUE key, VALUE value, int* flags) {
         | 
| 2 | 
            +
                    ID id = rb_to_id(key);
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                    if (0) {}
         | 
| 5 | 
            +
            #define FLAG(const, name) else if (id == rb_intern(#name)) { if (RTEST(value)) { *flags |= MDB_##const; } }
         | 
| 6 | 
            +
            #include FILE
         | 
| 7 | 
            +
            #undef FLAG
         | 
| 8 | 
            +
                    else {
         | 
| 9 | 
            +
                            VALUE s = rb_inspect(key);
         | 
| 10 | 
            +
                            rb_raise(cError, "Invalid option %s", StringValueCStr(s));
         | 
| 11 | 
            +
                    }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    return 0;
         | 
| 14 | 
            +
            }
         | 
    
        data/ext/lmdb_ext/lmdb_ext.c
    CHANGED
    
    | @@ -24,8 +24,10 @@ static void transaction_deref(Transaction* transaction) { | |
| 24 24 | 
             
                                    Transaction* parent = (Transaction*)DATA_PTR(transaction->parent);
         | 
| 25 25 | 
             
                                    transaction_deref(parent);
         | 
| 26 26 | 
             
                            }
         | 
| 27 | 
            -
                            if (transaction->txn)
         | 
| 27 | 
            +
                            if (transaction->txn) {
         | 
| 28 | 
            +
                                    rb_warn("Garbage collecting active transaction!");
         | 
| 28 29 | 
             
                                    mdb_txn_abort(transaction->txn);
         | 
| 30 | 
            +
                            }
         | 
| 29 31 | 
             
                            free(transaction);
         | 
| 30 32 | 
             
                    }
         | 
| 31 33 | 
             
            }
         | 
| @@ -36,40 +38,26 @@ static void transaction_mark(Transaction* transaction) { | |
| 36 38 | 
             
            }
         | 
| 37 39 |  | 
| 38 40 | 
             
            static VALUE transaction_commit(VALUE self) {
         | 
| 39 | 
            -
                     | 
| 40 | 
            -
                    ENVIRONMENT(transaction->env, environment);
         | 
| 41 | 
            -
                    if (!transaction->txn)
         | 
| 42 | 
            -
                            rb_raise(cError, "Transaction is terminated");
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                    // Check nesting
         | 
| 45 | 
            -
                    VALUE p = environment->txn;
         | 
| 46 | 
            -
                    while (!NIL_P(p) && p != self) {
         | 
| 47 | 
            -
                            TRANSACTION(p, txn);
         | 
| 48 | 
            -
                            p = txn->parent;
         | 
| 49 | 
            -
                    }
         | 
| 50 | 
            -
                    if (p != self)
         | 
| 51 | 
            -
                            rb_raise(cError, "Transaction is not active");
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                    mdb_txn_commit(transaction->txn);
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                    p = environment->txn;
         | 
| 56 | 
            -
                    while (p != self) {
         | 
| 57 | 
            -
                            TRANSACTION(p, txn);
         | 
| 58 | 
            -
                            txn->txn = 0;
         | 
| 59 | 
            -
                            p = txn->parent;
         | 
| 60 | 
            -
                    }
         | 
| 61 | 
            -
                    transaction->txn = 0;
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                    environment->txn = transaction->parent;
         | 
| 41 | 
            +
                    transaction_finish(self, 1);
         | 
| 64 42 | 
             
                    return Qnil;
         | 
| 65 43 | 
             
            }
         | 
| 66 44 |  | 
| 67 45 | 
             
            static VALUE transaction_abort(VALUE self) {
         | 
| 46 | 
            +
                    transaction_finish(self, 0);
         | 
| 47 | 
            +
                    return Qnil;
         | 
| 48 | 
            +
            }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            static void transaction_finish(VALUE self, int commit) {
         | 
| 68 51 | 
             
                    TRANSACTION(self, transaction);
         | 
| 69 | 
            -
             | 
| 52 | 
            +
             | 
| 53 | 
            +
                    if (!transaction->txn)
         | 
| 54 | 
            +
                            rb_raise(cError, "Transaction is terminated");
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    if (transaction->thread != rb_thread_current())
         | 
| 57 | 
            +
                            rb_raise(cError, "Wrong thread");
         | 
| 70 58 |  | 
| 71 59 | 
             
                    // Check nesting
         | 
| 72 | 
            -
                    VALUE p =  | 
| 60 | 
            +
                    VALUE p = environment_active_txn(transaction->env);
         | 
| 73 61 | 
             
                    while (!NIL_P(p) && p != self) {
         | 
| 74 62 | 
             
                            TRANSACTION(p, txn);
         | 
| 75 63 | 
             
                            p = txn->parent;
         | 
| @@ -77,20 +65,23 @@ static VALUE transaction_abort(VALUE self) { | |
| 77 65 | 
             
                    if (p != self)
         | 
| 78 66 | 
             
                            rb_raise(cError, "Transaction is not active");
         | 
| 79 67 |  | 
| 80 | 
            -
                     | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 68 | 
            +
                    int ret = 0;
         | 
| 69 | 
            +
                    if (commit)
         | 
| 70 | 
            +
                            ret = mdb_txn_commit(transaction->txn);
         | 
| 71 | 
            +
                    else
         | 
| 72 | 
            +
                            mdb_txn_abort(transaction->txn);
         | 
| 83 73 |  | 
| 84 | 
            -
                    p =  | 
| 74 | 
            +
                    p = environment_active_txn(transaction->env);
         | 
| 85 75 | 
             
                    while (p != self) {
         | 
| 86 76 | 
             
                            TRANSACTION(p, txn);
         | 
| 87 77 | 
             
                            txn->txn = 0;
         | 
| 88 78 | 
             
                            p = txn->parent;
         | 
| 89 | 
            -
                    } | 
| 79 | 
            +
                    }
         | 
| 90 80 | 
             
                    transaction->txn = 0;
         | 
| 91 81 |  | 
| 92 | 
            -
                     | 
| 93 | 
            -
             | 
| 82 | 
            +
                    environment_set_active_txn(transaction->env, transaction->thread, transaction->parent);
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    check(ret);
         | 
| 94 85 | 
             
            }
         | 
| 95 86 |  | 
| 96 87 | 
             
            static VALUE call_with_transaction_helper(VALUE arg) {
         | 
| @@ -107,27 +98,35 @@ static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flag | |
| 107 98 | 
             
                    ENVIRONMENT(venv, environment);
         | 
| 108 99 |  | 
| 109 100 | 
             
                    MDB_txn* txn;
         | 
| 110 | 
            -
                    check(mdb_txn_begin(environment->env,  | 
| 101 | 
            +
                    check(mdb_txn_begin(environment->env, active_txn(venv), flags, &txn));
         | 
| 111 102 |  | 
| 112 103 | 
             
                    Transaction* transaction;
         | 
| 113 104 | 
             
                    VALUE vtxn = Data_Make_Struct(cTransaction, Transaction, transaction_mark, transaction_deref, transaction);
         | 
| 114 105 | 
             
                    transaction->refcount = 1;
         | 
| 115 | 
            -
                    transaction->parent =  | 
| 106 | 
            +
                    transaction->parent = environment_active_txn(venv);
         | 
| 116 107 | 
             
                    transaction->env = venv;
         | 
| 117 108 | 
             
                    transaction->txn = txn;
         | 
| 118 | 
            -
                     | 
| 109 | 
            +
                    transaction->thread = rb_thread_current();
         | 
| 110 | 
            +
                    environment_set_active_txn(venv, transaction->thread, vtxn);
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    if (!NIL_P(transaction->parent)) {
         | 
| 113 | 
            +
                            TRANSACTION(transaction->parent, parent);
         | 
| 114 | 
            +
                            ++parent->refcount;
         | 
| 115 | 
            +
                    }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    ++environment->refcount;
         | 
| 119 118 |  | 
| 120 119 | 
             
                    int exception;
         | 
| 121 | 
            -
                    VALUE  | 
| 120 | 
            +
                    VALUE ret = rb_protect(fn, NIL_P(arg) ? vtxn : arg, &exception);
         | 
| 122 121 |  | 
| 123 122 | 
             
                    if (exception) {
         | 
| 124 | 
            -
                            if (vtxn ==  | 
| 123 | 
            +
                            if (vtxn == environment_active_txn(venv))
         | 
| 125 124 | 
             
                                    transaction_abort(vtxn);
         | 
| 126 125 | 
             
                            rb_jump_tag(exception);
         | 
| 127 126 | 
             
                    }
         | 
| 128 | 
            -
                    if (vtxn ==  | 
| 127 | 
            +
                    if (vtxn == environment_active_txn(venv))
         | 
| 129 128 | 
             
                            transaction_commit(vtxn);
         | 
| 130 | 
            -
                    return  | 
| 129 | 
            +
                    return ret;
         | 
| 131 130 | 
             
            }
         | 
| 132 131 |  | 
| 133 132 | 
             
            static void environment_check(Environment* environment) {
         | 
| @@ -143,6 +142,12 @@ static void environment_deref(Environment *environment) { | |
| 143 142 | 
             
                    }
         | 
| 144 143 | 
             
            }
         | 
| 145 144 |  | 
| 145 | 
            +
             | 
| 146 | 
            +
            static void environment_mark(Environment* environment) {
         | 
| 147 | 
            +
                    rb_gc_mark(environment->thread_txn_hash);
         | 
| 148 | 
            +
                    rb_gc_mark(environment->txn_thread_hash);
         | 
| 149 | 
            +
            }
         | 
| 150 | 
            +
             | 
| 146 151 | 
             
            static VALUE environment_close(VALUE self) {
         | 
| 147 152 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 148 153 | 
             
                    mdb_env_close(environment->env);
         | 
| @@ -151,9 +156,9 @@ static VALUE environment_close(VALUE self) { | |
| 151 156 | 
             
            }
         | 
| 152 157 |  | 
| 153 158 | 
             
            static VALUE stat2hash(const MDB_stat* stat) {
         | 
| 154 | 
            -
                    VALUE  | 
| 159 | 
            +
                    VALUE ret = rb_hash_new();
         | 
| 155 160 |  | 
| 156 | 
            -
            #define STAT_SET(name) rb_hash_aset( | 
| 161 | 
            +
            #define STAT_SET(name) rb_hash_aset(ret, ID2SYM(rb_intern(#name)), INT2NUM(stat->ms_##name))
         | 
| 157 162 | 
             
                    STAT_SET(psize);
         | 
| 158 163 | 
             
                    STAT_SET(depth);
         | 
| 159 164 | 
             
                    STAT_SET(branch_pages);
         | 
| @@ -162,7 +167,7 @@ static VALUE stat2hash(const MDB_stat* stat) { | |
| 162 167 | 
             
                    STAT_SET(entries);
         | 
| 163 168 | 
             
            #undef STAT_SET
         | 
| 164 169 |  | 
| 165 | 
            -
                    return  | 
| 170 | 
            +
                    return ret;
         | 
| 166 171 | 
             
            }
         | 
| 167 172 |  | 
| 168 173 | 
             
            static VALUE environment_stat(VALUE self) {
         | 
| @@ -178,9 +183,9 @@ static VALUE environment_info(VALUE self) { | |
| 178 183 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 179 184 | 
             
                    check(mdb_env_info(environment->env, &info));
         | 
| 180 185 |  | 
| 181 | 
            -
                    VALUE  | 
| 186 | 
            +
                    VALUE ret = rb_hash_new();
         | 
| 182 187 |  | 
| 183 | 
            -
            #define INFO_SET(name) rb_hash_aset( | 
| 188 | 
            +
            #define INFO_SET(name) rb_hash_aset(ret, ID2SYM(rb_intern(#name)), INT2NUM((size_t)info.me_##name));
         | 
| 184 189 | 
             
                    INFO_SET(mapaddr);
         | 
| 185 190 | 
             
                    INFO_SET(mapsize);
         | 
| 186 191 | 
             
                    INFO_SET(last_pgno);
         | 
| @@ -189,7 +194,7 @@ static VALUE environment_info(VALUE self) { | |
| 189 194 | 
             
                    INFO_SET(numreaders);
         | 
| 190 195 | 
             
            #undef INFO_SET
         | 
| 191 196 |  | 
| 192 | 
            -
                    return  | 
| 197 | 
            +
                    return ret;
         | 
| 193 198 | 
             
            }
         | 
| 194 199 |  | 
| 195 200 | 
             
            static VALUE environment_copy(VALUE self, VALUE path) {
         | 
| @@ -208,51 +213,62 @@ static VALUE environment_sync(int argc, VALUE *argv, VALUE self) { | |
| 208 213 | 
             
                    return Qnil;
         | 
| 209 214 | 
             
            }
         | 
| 210 215 |  | 
| 211 | 
            -
            static  | 
| 212 | 
            -
                     | 
| 213 | 
            -
                    rb_scan_args(argc, argv, "11", &path, &options);
         | 
| 216 | 
            +
            static int environment_options(VALUE key, VALUE value, EnvironmentOptions* options) {
         | 
| 217 | 
            +
                    ID id = rb_to_id(key);
         | 
| 214 218 |  | 
| 215 | 
            -
                     | 
| 216 | 
            -
             | 
| 217 | 
            -
                     | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
                             | 
| 221 | 
            -
             | 
| 219 | 
            +
                    if (id == rb_intern("mode"))
         | 
| 220 | 
            +
                            options->mode = NUM2INT(value);
         | 
| 221 | 
            +
                    else if (id == rb_intern("maxreaders"))
         | 
| 222 | 
            +
                            options->maxreaders = NUM2INT(value);
         | 
| 223 | 
            +
                    else if (id == rb_intern("maxdbs"))
         | 
| 224 | 
            +
                            options->maxdbs = NUM2INT(value);
         | 
| 225 | 
            +
                    else if (id == rb_intern("mapsize"))
         | 
| 226 | 
            +
                            options->mapsize = NUM2SSIZET(value);
         | 
| 222 227 |  | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 228 | 
            +
            #define FLAG(const, name) else if (id == rb_intern(#name)) { if (RTEST(value)) { options->flags |= MDB_##const; } }
         | 
| 229 | 
            +
            #include "env_flags.h"
         | 
| 230 | 
            +
            #undef FLAG
         | 
| 226 231 |  | 
| 227 | 
            -
             | 
| 228 | 
            -
                             | 
| 229 | 
            -
             | 
| 232 | 
            +
                    else {
         | 
| 233 | 
            +
                            VALUE s = rb_inspect(key);
         | 
| 234 | 
            +
                            rb_raise(cError, "Invalid option %s", StringValueCStr(s));
         | 
| 235 | 
            +
                    }
         | 
| 230 236 |  | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
                                    maxdbs = NUM2INT(value);
         | 
| 237 | 
            +
                    return 0;
         | 
| 238 | 
            +
            }
         | 
| 234 239 |  | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 240 | 
            +
            static VALUE environment_new(int argc, VALUE *argv, VALUE klass) {
         | 
| 241 | 
            +
                    VALUE path, option_hash;
         | 
| 242 | 
            +
                    rb_scan_args(argc, argv, "1:", &path, &option_hash);
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                    EnvironmentOptions options = {
         | 
| 245 | 
            +
                            .flags = MDB_NOTLS,
         | 
| 246 | 
            +
                            .maxreaders = -1,
         | 
| 247 | 
            +
                            .maxdbs = 128,
         | 
| 248 | 
            +
                            .mapsize = 0,
         | 
| 249 | 
            +
                            .mode = 0755,
         | 
| 250 | 
            +
                    };
         | 
| 251 | 
            +
                    if (!NIL_P(option_hash))
         | 
| 252 | 
            +
                            rb_hash_foreach(option_hash, environment_options, (VALUE)&options);
         | 
| 239 253 |  | 
| 240 254 | 
             
                    MDB_env* env;
         | 
| 241 255 | 
             
                    check(mdb_env_create(&env));
         | 
| 242 256 |  | 
| 243 257 | 
             
                    Environment* environment;
         | 
| 244 | 
            -
                    VALUE venv = Data_Make_Struct(cEnvironment, Environment,  | 
| 258 | 
            +
                    VALUE venv = Data_Make_Struct(cEnvironment, Environment, environment_mark, environment_deref, environment);
         | 
| 245 259 | 
             
                    environment->env = env;
         | 
| 246 260 | 
             
                    environment->refcount = 1;
         | 
| 247 | 
            -
                    environment-> | 
| 261 | 
            +
                    environment->thread_txn_hash = rb_hash_new();
         | 
| 262 | 
            +
                    environment->txn_thread_hash = rb_hash_new();
         | 
| 248 263 |  | 
| 249 | 
            -
                    if (maxreaders > 0)
         | 
| 250 | 
            -
                            check(mdb_env_set_maxreaders( | 
| 251 | 
            -
                    if (mapsize > 0)
         | 
| 252 | 
            -
                            check(mdb_env_set_mapsize( | 
| 264 | 
            +
                    if (options.maxreaders > 0)
         | 
| 265 | 
            +
                            check(mdb_env_set_maxreaders(env, options.maxreaders));
         | 
| 266 | 
            +
                    if (options.mapsize > 0)
         | 
| 267 | 
            +
                            check(mdb_env_set_mapsize(env, options.mapsize));
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                    check(mdb_env_set_maxdbs(env, options.maxdbs <= 0 ? 1 : options.maxdbs));
         | 
| 270 | 
            +
                    check(mdb_env_open(env, StringValueCStr(path), options.flags, options.mode));
         | 
| 253 271 |  | 
| 254 | 
            -
                    check(mdb_env_set_maxdbs(environment->env, maxdbs <= 0 ? 1 : maxdbs));
         | 
| 255 | 
            -
                    check(mdb_env_open(environment->env, StringValueCStr(path), flags, mode));
         | 
| 256 272 | 
             
                    if (rb_block_given_p())
         | 
| 257 273 | 
             
                            return rb_ensure(rb_yield, venv, environment_close, venv);
         | 
| 258 274 |  | 
| @@ -263,7 +279,13 @@ static VALUE environment_flags(VALUE self) { | |
| 263 279 | 
             
                    unsigned int flags;
         | 
| 264 280 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 265 281 | 
             
                    check(mdb_env_get_flags(environment->env, &flags));
         | 
| 266 | 
            -
             | 
| 282 | 
            +
             | 
| 283 | 
            +
                    VALUE ret = rb_ary_new();
         | 
| 284 | 
            +
            #define FLAG(const, name) if (flags & MDB_##const) rb_ary_push(ret, ID2SYM(rb_intern(#name)));
         | 
| 285 | 
            +
            #include "env_flags.h"
         | 
| 286 | 
            +
            #undef FLAG
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                    return ret;
         | 
| 267 289 | 
             
            }
         | 
| 268 290 |  | 
| 269 291 | 
             
            static VALUE environment_path(VALUE self) {
         | 
| @@ -273,27 +295,68 @@ static VALUE environment_path(VALUE self) { | |
| 273 295 | 
             
                    return rb_str_new2(path);
         | 
| 274 296 | 
             
            }
         | 
| 275 297 |  | 
| 276 | 
            -
            static VALUE  | 
| 277 | 
            -
                    unsigned int flags = NUM2INT(vflags), oldflags;
         | 
| 298 | 
            +
            static VALUE environment_change_flags(int argc, VALUE* argv, VALUE self, int set) {
         | 
| 278 299 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 279 | 
            -
             | 
| 280 | 
            -
                     | 
| 281 | 
            -
                     | 
| 282 | 
            -
             | 
| 300 | 
            +
             | 
| 301 | 
            +
                    int i;
         | 
| 302 | 
            +
                    for (i = 0; i < argc; ++i) {
         | 
| 303 | 
            +
                            ID id = rb_to_id(argv[i]);
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                            if (0) {}
         | 
| 306 | 
            +
            #define FLAG(const, name) else if (id == rb_intern(#name)) check(mdb_env_set_flags(environment->env, MDB_##const, set));
         | 
| 307 | 
            +
            #include "env_flags.h"
         | 
| 308 | 
            +
            #undef FLAG
         | 
| 309 | 
            +
                            else
         | 
| 310 | 
            +
                                    rb_raise(cError, "Invalid option %s", StringValueCStr(argv[i]));
         | 
| 311 | 
            +
                    }
         | 
| 312 | 
            +
                    return Qnil;
         | 
| 313 | 
            +
            }
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            static VALUE environment_set_flags(int argc, VALUE* argv, VALUE self) {
         | 
| 316 | 
            +
                    environment_change_flags(argc, argv, self, 1);
         | 
| 317 | 
            +
                    return Qnil;
         | 
| 283 318 | 
             
            }
         | 
| 284 319 |  | 
| 285 | 
            -
            static  | 
| 320 | 
            +
            static VALUE environment_clear_flags(int argc, VALUE* argv, VALUE self) {
         | 
| 321 | 
            +
                    environment_change_flags(argc, argv, self, 0);
         | 
| 322 | 
            +
                    return Qnil;
         | 
| 323 | 
            +
            }
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            static VALUE environment_active_txn(VALUE self) {
         | 
| 286 326 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 287 | 
            -
                     | 
| 327 | 
            +
                    return rb_hash_aref(environment->thread_txn_hash, rb_thread_current());
         | 
| 328 | 
            +
            }
         | 
| 329 | 
            +
             | 
| 330 | 
            +
            static void environment_set_active_txn(VALUE self, VALUE thread, VALUE txn) {
         | 
| 331 | 
            +
                    ENVIRONMENT(self, environment);
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                    if (NIL_P(txn)) {
         | 
| 334 | 
            +
                            VALUE oldtxn = rb_hash_aref(environment->thread_txn_hash, thread);
         | 
| 335 | 
            +
                            if (!NIL_P(oldtxn)) {
         | 
| 336 | 
            +
                                    rb_hash_delete(environment->thread_txn_hash, thread);
         | 
| 337 | 
            +
                                    rb_hash_delete(environment->txn_thread_hash, oldtxn);
         | 
| 338 | 
            +
                            }
         | 
| 339 | 
            +
                    } else {
         | 
| 340 | 
            +
                            rb_hash_aset(environment->txn_thread_hash, txn, thread);
         | 
| 341 | 
            +
                            rb_hash_aset(environment->thread_txn_hash, thread, txn);
         | 
| 342 | 
            +
                    }
         | 
| 343 | 
            +
            }
         | 
| 344 | 
            +
             | 
| 345 | 
            +
             | 
| 346 | 
            +
            static MDB_txn* active_txn(VALUE self) {
         | 
| 347 | 
            +
                    VALUE vtxn = environment_active_txn(self);
         | 
| 348 | 
            +
                    if (NIL_P(vtxn))
         | 
| 288 349 | 
             
                            return 0;
         | 
| 289 | 
            -
                    TRANSACTION( | 
| 350 | 
            +
                    TRANSACTION(vtxn, transaction);
         | 
| 290 351 | 
             
                    if (!transaction->txn)
         | 
| 291 352 | 
             
                            rb_raise(cError, "Transaction is terminated");
         | 
| 353 | 
            +
                    if (transaction->thread != rb_thread_current())
         | 
| 354 | 
            +
                            rb_raise(cError, "Wrong thread");
         | 
| 292 355 | 
             
                    return transaction->txn;
         | 
| 293 356 | 
             
            }
         | 
| 294 357 |  | 
| 295 | 
            -
            static MDB_txn*  | 
| 296 | 
            -
                    MDB_txn* txn =  | 
| 358 | 
            +
            static MDB_txn* need_txn(VALUE self) {
         | 
| 359 | 
            +
                    MDB_txn* txn = active_txn(self);
         | 
| 297 360 | 
             
                    if (!txn)
         | 
| 298 361 | 
             
                            rb_raise(cError, "No active transaction");
         | 
| 299 362 | 
             
                    return txn;
         | 
| @@ -321,16 +384,26 @@ static void database_mark(Database* database) { | |
| 321 384 | 
             
                    rb_gc_mark(database->env);
         | 
| 322 385 | 
             
            }
         | 
| 323 386 |  | 
| 387 | 
            +
            #define METHOD database_flags
         | 
| 388 | 
            +
            #define FILE "dbi_flags.h"
         | 
| 389 | 
            +
            #include "flag_parser.h"
         | 
| 390 | 
            +
            #undef METHOD
         | 
| 391 | 
            +
            #undef FILE
         | 
| 392 | 
            +
             | 
| 324 393 | 
             
            static VALUE environment_database(int argc, VALUE *argv, VALUE self) {
         | 
| 325 394 | 
             
                    ENVIRONMENT(self, environment);
         | 
| 326 | 
            -
                    if ( | 
| 395 | 
            +
                    if (!active_txn(self))
         | 
| 327 396 | 
             
                            return call_with_transaction(self, self, "database", argc, argv, 0);
         | 
| 328 397 |  | 
| 329 | 
            -
                    VALUE  | 
| 330 | 
            -
                    rb_scan_args(argc, argv, " | 
| 398 | 
            +
                    VALUE name, option_hash;
         | 
| 399 | 
            +
                    rb_scan_args(argc, argv, "01:", &name, &option_hash);
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                    int flags = 0;
         | 
| 402 | 
            +
                    if (!NIL_P(option_hash))
         | 
| 403 | 
            +
                            rb_hash_foreach(option_hash, database_flags, (VALUE)&flags);
         | 
| 331 404 |  | 
| 332 405 | 
             
                    MDB_dbi dbi;
         | 
| 333 | 
            -
                    check(mdb_dbi_open( | 
| 406 | 
            +
                    check(mdb_dbi_open(need_txn(self), NIL_P(name) ? 0 : StringValueCStr(name), flags, &dbi));
         | 
| 334 407 |  | 
| 335 408 | 
             
                    Database* database;
         | 
| 336 409 | 
             
                    VALUE vdb = Data_Make_Struct(cDatabase, Database, database_mark, database_deref, database);
         | 
| @@ -344,33 +417,33 @@ static VALUE environment_database(int argc, VALUE *argv, VALUE self) { | |
| 344 417 |  | 
| 345 418 | 
             
            static VALUE database_stat(VALUE self) {
         | 
| 346 419 | 
             
                    DATABASE(self, database);
         | 
| 347 | 
            -
                    if (! | 
| 420 | 
            +
                    if (!active_txn(database->env))
         | 
| 348 421 | 
             
                            return call_with_transaction(database->env, self, "stat", 0, 0, MDB_RDONLY);
         | 
| 349 422 |  | 
| 350 423 | 
             
                    MDB_stat stat;
         | 
| 351 | 
            -
                    check(mdb_stat( | 
| 424 | 
            +
                    check(mdb_stat(need_txn(database->env), database->dbi, &stat));
         | 
| 352 425 | 
             
                    return stat2hash(&stat);
         | 
| 353 426 | 
             
            }
         | 
| 354 427 |  | 
| 355 428 | 
             
            static VALUE database_drop(VALUE self) {
         | 
| 356 429 | 
             
                    DATABASE(self, database);
         | 
| 357 | 
            -
                    if (! | 
| 430 | 
            +
                    if (!active_txn(database->env))
         | 
| 358 431 | 
             
                            return call_with_transaction(database->env, self, "drop", 0, 0, 0);
         | 
| 359 | 
            -
                    check(mdb_drop( | 
| 432 | 
            +
                    check(mdb_drop(need_txn(database->env), database->dbi, 1));
         | 
| 360 433 | 
             
                    return Qnil;
         | 
| 361 434 | 
             
            }
         | 
| 362 435 |  | 
| 363 436 | 
             
            static VALUE database_clear(VALUE self) {
         | 
| 364 437 | 
             
                    DATABASE(self, database);
         | 
| 365 | 
            -
                    if (! | 
| 438 | 
            +
                    if (!active_txn(database->env))
         | 
| 366 439 | 
             
                            return call_with_transaction(database->env, self, "clear", 0, 0, 0);
         | 
| 367 | 
            -
                    check(mdb_drop( | 
| 440 | 
            +
                    check(mdb_drop(need_txn(database->env), database->dbi, 0));
         | 
| 368 441 | 
             
                    return Qnil;
         | 
| 369 442 | 
             
            }
         | 
| 370 443 |  | 
| 371 444 | 
             
            static VALUE database_get(VALUE self, VALUE vkey) {
         | 
| 372 445 | 
             
                    DATABASE(self, database);
         | 
| 373 | 
            -
                    if (! | 
| 446 | 
            +
                    if (!active_txn(database->env))
         | 
| 374 447 | 
             
                            return call_with_transaction(database->env, self, "get", 1, &vkey, MDB_RDONLY);
         | 
| 375 448 |  | 
| 376 449 | 
             
                    vkey = StringValue(vkey);
         | 
| @@ -378,20 +451,30 @@ static VALUE database_get(VALUE self, VALUE vkey) { | |
| 378 451 | 
             
                    key.mv_size = RSTRING_LEN(vkey);
         | 
| 379 452 | 
             
                    key.mv_data = RSTRING_PTR(vkey);
         | 
| 380 453 |  | 
| 381 | 
            -
                    int ret = mdb_get( | 
| 454 | 
            +
                    int ret = mdb_get(need_txn(database->env), database->dbi, &key, &value);
         | 
| 382 455 | 
             
                    if (ret == MDB_NOTFOUND)
         | 
| 383 456 | 
             
                            return Qnil;
         | 
| 384 457 | 
             
                    check(ret);
         | 
| 385 458 | 
             
                    return rb_str_new(value.mv_data, value.mv_size);
         | 
| 386 459 | 
             
            }
         | 
| 387 460 |  | 
| 461 | 
            +
            #define METHOD database_put_flags
         | 
| 462 | 
            +
            #define FILE "put_flags.h"
         | 
| 463 | 
            +
            #include "flag_parser.h"
         | 
| 464 | 
            +
            #undef METHOD
         | 
| 465 | 
            +
            #undef FILE
         | 
| 466 | 
            +
             | 
| 388 467 | 
             
            static VALUE database_put(int argc, VALUE *argv, VALUE self) {
         | 
| 389 468 | 
             
                    DATABASE(self, database);
         | 
| 390 | 
            -
                    if (! | 
| 469 | 
            +
                    if (!active_txn(database->env))
         | 
| 391 470 | 
             
                            return call_with_transaction(database->env, self, "put", argc, argv, 0);
         | 
| 392 471 |  | 
| 393 | 
            -
                    VALUE vkey,  | 
| 394 | 
            -
                    rb_scan_args(argc, argv, " | 
| 472 | 
            +
                    VALUE vkey, vval, option_hash;
         | 
| 473 | 
            +
                    rb_scan_args(argc, argv, "2:", &vkey, &vval, &option_hash);
         | 
| 474 | 
            +
             | 
| 475 | 
            +
                    int flags = 0;
         | 
| 476 | 
            +
                    if (!NIL_P(option_hash))
         | 
| 477 | 
            +
                            rb_hash_foreach(option_hash, database_put_flags, (VALUE)&flags);
         | 
| 395 478 |  | 
| 396 479 | 
             
                    vkey = StringValue(vkey);
         | 
| 397 480 | 
             
                    vval = StringValue(vval);
         | 
| @@ -402,13 +485,13 @@ static VALUE database_put(int argc, VALUE *argv, VALUE self) { | |
| 402 485 | 
             
                    value.mv_size = RSTRING_LEN(vval);
         | 
| 403 486 | 
             
                    value.mv_data = RSTRING_PTR(vval);
         | 
| 404 487 |  | 
| 405 | 
            -
                    check(mdb_put( | 
| 488 | 
            +
                    check(mdb_put(need_txn(database->env), database->dbi, &key, &value, flags));
         | 
| 406 489 | 
             
                    return Qnil;
         | 
| 407 490 | 
             
            }
         | 
| 408 491 |  | 
| 409 492 | 
             
            static VALUE database_delete(int argc, VALUE *argv, VALUE self) {
         | 
| 410 493 | 
             
                    DATABASE(self, database);
         | 
| 411 | 
            -
                    if (! | 
| 494 | 
            +
                    if (!active_txn(database->env))
         | 
| 412 495 | 
             
                            return call_with_transaction(database->env, self, "delete", argc, argv, 0);
         | 
| 413 496 |  | 
| 414 497 | 
             
                    VALUE vkey, vval;
         | 
| @@ -421,13 +504,13 @@ static VALUE database_delete(int argc, VALUE *argv, VALUE self) { | |
| 421 504 | 
             
                    key.mv_data = RSTRING_PTR(vkey);
         | 
| 422 505 |  | 
| 423 506 | 
             
                    if (NIL_P(vval)) {
         | 
| 424 | 
            -
                            check(mdb_del( | 
| 507 | 
            +
                            check(mdb_del(need_txn(database->env), database->dbi, &key, 0));
         | 
| 425 508 | 
             
                    } else {
         | 
| 426 509 | 
             
                            VALUE vval = StringValue(vval);
         | 
| 427 510 | 
             
                            MDB_val value;
         | 
| 428 511 | 
             
                            value.mv_size = RSTRING_LEN(vval);
         | 
| 429 512 | 
             
                            value.mv_data = RSTRING_PTR(vval);
         | 
| 430 | 
            -
                            check(mdb_del( | 
| 513 | 
            +
                            check(mdb_del(need_txn(database->env), database->dbi, &key, &value));
         | 
| 431 514 | 
             
                    }
         | 
| 432 515 |  | 
| 433 516 | 
             
                    return Qnil;
         | 
| @@ -459,11 +542,11 @@ static VALUE cursor_close(VALUE self) { | |
| 459 542 |  | 
| 460 543 | 
             
            static VALUE database_cursor(VALUE self) {
         | 
| 461 544 | 
             
                    DATABASE(self, database);
         | 
| 462 | 
            -
                    if (! | 
| 545 | 
            +
                    if (!active_txn(database->env))
         | 
| 463 546 | 
             
                            return call_with_transaction(database->env, self, "cursor", 0, 0, 0);
         | 
| 464 547 |  | 
| 465 548 | 
             
                    MDB_cursor* cur;
         | 
| 466 | 
            -
                    check(mdb_cursor_open( | 
| 549 | 
            +
                    check(mdb_cursor_open(need_txn(database->env), database->dbi, &cur));
         | 
| 467 550 |  | 
| 468 551 | 
             
                    Cursor* cursor;
         | 
| 469 552 | 
             
                    VALUE vcur = Data_Make_Struct(cCursor, Cursor, cursor_mark, cursor_free, cursor);
         | 
| @@ -473,13 +556,13 @@ static VALUE database_cursor(VALUE self) { | |
| 473 556 |  | 
| 474 557 | 
             
                    if (rb_block_given_p()) {
         | 
| 475 558 | 
             
                            int exception;
         | 
| 476 | 
            -
                            VALUE  | 
| 559 | 
            +
                            VALUE ret = rb_protect(rb_yield, vcur, &exception);
         | 
| 477 560 | 
             
                            if (exception) {
         | 
| 478 561 | 
             
                                    cursor_close(vcur);
         | 
| 479 562 | 
             
                                    rb_jump_tag(exception);
         | 
| 480 563 | 
             
                            }
         | 
| 481 564 | 
             
                            cursor_close(vcur);
         | 
| 482 | 
            -
                            return  | 
| 565 | 
            +
                            return ret;
         | 
| 483 566 | 
             
                    }
         | 
| 484 567 |  | 
| 485 568 | 
             
                    return vcur;
         | 
| @@ -548,11 +631,21 @@ static VALUE cursor_get(VALUE self) { | |
| 548 631 | 
             
                    return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
         | 
| 549 632 | 
             
            }
         | 
| 550 633 |  | 
| 634 | 
            +
            #define METHOD cursor_put_flags
         | 
| 635 | 
            +
            #define FILE "cursor_put_flags.h"
         | 
| 636 | 
            +
            #include "flag_parser.h"
         | 
| 637 | 
            +
            #undef METHOD
         | 
| 638 | 
            +
            #undef FILE
         | 
| 639 | 
            +
             | 
| 551 640 | 
             
            static VALUE cursor_put(int argc, VALUE* argv, VALUE self) {
         | 
| 552 641 | 
             
                    CURSOR(self, cursor);
         | 
| 553 642 |  | 
| 554 | 
            -
                    VALUE vkey,  | 
| 555 | 
            -
                    rb_scan_args(argc, argv, " | 
| 643 | 
            +
                    VALUE vkey, vval, option_hash;
         | 
| 644 | 
            +
                    rb_scan_args(argc, argv, "2:", &vkey, &vval, &option_hash);
         | 
| 645 | 
            +
             | 
| 646 | 
            +
                    int flags = 0;
         | 
| 647 | 
            +
                    if (!NIL_P(option_hash))
         | 
| 648 | 
            +
                            rb_hash_foreach(option_hash, cursor_put_flags, (VALUE)&flags);
         | 
| 556 649 |  | 
| 557 650 | 
             
                    vkey = StringValue(vkey);
         | 
| 558 651 | 
             
                    vval = StringValue(vval);
         | 
| @@ -563,15 +656,27 @@ static VALUE cursor_put(int argc, VALUE* argv, VALUE self) { | |
| 563 656 | 
             
                    value.mv_size = RSTRING_LEN(vval);
         | 
| 564 657 | 
             
                    value.mv_data = RSTRING_PTR(vval);
         | 
| 565 658 |  | 
| 566 | 
            -
                    check(mdb_cursor_put(cursor->cur, &key, &value,  | 
| 659 | 
            +
                    check(mdb_cursor_put(cursor->cur, &key, &value, flags));
         | 
| 567 660 | 
             
                    return Qnil;
         | 
| 568 661 | 
             
            }
         | 
| 569 662 |  | 
| 663 | 
            +
            #define METHOD cursor_delete_flags
         | 
| 664 | 
            +
            #define FILE "cursor_delete_flags.h"
         | 
| 665 | 
            +
            #include "flag_parser.h"
         | 
| 666 | 
            +
            #undef METHOD
         | 
| 667 | 
            +
            #undef FILE
         | 
| 668 | 
            +
             | 
| 570 669 | 
             
            static VALUE cursor_delete(int argc, VALUE *argv, VALUE self) {
         | 
| 571 670 | 
             
                    CURSOR(self, cursor);
         | 
| 572 | 
            -
             | 
| 573 | 
            -
                     | 
| 574 | 
            -
                     | 
| 671 | 
            +
             | 
| 672 | 
            +
                    VALUE option_hash;
         | 
| 673 | 
            +
                    rb_scan_args(argc, argv, ":", &option_hash);
         | 
| 674 | 
            +
             | 
| 675 | 
            +
                    int flags = 0;
         | 
| 676 | 
            +
                    if (!NIL_P(option_hash))
         | 
| 677 | 
            +
                            rb_hash_foreach(option_hash, cursor_delete_flags, (VALUE)&flags);
         | 
| 678 | 
            +
             | 
| 679 | 
            +
                    check(mdb_cursor_del(cursor->cur, flags));
         | 
| 575 680 | 
             
                    return Qnil;
         | 
| 576 681 | 
             
            }
         | 
| 577 682 |  | 
| @@ -586,43 +691,14 @@ void Init_lmdb_ext() { | |
| 586 691 | 
             
                    VALUE mLMDB;
         | 
| 587 692 |  | 
| 588 693 | 
             
                    mLMDB = rb_define_module("LMDB");
         | 
| 589 | 
            -
                    rb_define_const(mLMDB, " | 
| 590 | 
            -
                    rb_define_singleton_method(mLMDB, " | 
| 591 | 
            -
             | 
| 592 | 
            -
            #define  | 
| 593 | 
            -
             | 
| 594 | 
            -
                     | 
| 595 | 
            -
                     | 
| 596 | 
            -
             | 
| 597 | 
            -
                    NUM_CONST(VERSION_PATCH);
         | 
| 598 | 
            -
             | 
| 599 | 
            -
                    // Environment flags
         | 
| 600 | 
            -
                    NUM_CONST(FIXEDMAP);
         | 
| 601 | 
            -
                    NUM_CONST(NOSUBDIR);
         | 
| 602 | 
            -
                    NUM_CONST(NOSYNC);
         | 
| 603 | 
            -
                    NUM_CONST(RDONLY);
         | 
| 604 | 
            -
                    NUM_CONST(NOMETASYNC);
         | 
| 605 | 
            -
                    NUM_CONST(WRITEMAP);
         | 
| 606 | 
            -
                    NUM_CONST(MAPASYNC);
         | 
| 607 | 
            -
                    NUM_CONST(NOTLS);
         | 
| 608 | 
            -
             | 
| 609 | 
            -
                    // Database flags
         | 
| 610 | 
            -
                    NUM_CONST(REVERSEKEY);
         | 
| 611 | 
            -
                    NUM_CONST(DUPSORT);
         | 
| 612 | 
            -
                    NUM_CONST(INTEGERKEY);
         | 
| 613 | 
            -
                    NUM_CONST(DUPFIXED);
         | 
| 614 | 
            -
                    NUM_CONST(INTEGERDUP);
         | 
| 615 | 
            -
                    NUM_CONST(REVERSEDUP);
         | 
| 616 | 
            -
                    NUM_CONST(CREATE);
         | 
| 617 | 
            -
             | 
| 618 | 
            -
                    // Write flags
         | 
| 619 | 
            -
                    NUM_CONST(NOOVERWRITE);
         | 
| 620 | 
            -
                    NUM_CONST(NODUPDATA);
         | 
| 621 | 
            -
                    NUM_CONST(CURRENT);
         | 
| 622 | 
            -
                    NUM_CONST(RESERVE);
         | 
| 623 | 
            -
                    NUM_CONST(APPEND);
         | 
| 624 | 
            -
                    NUM_CONST(APPENDDUP);
         | 
| 625 | 
            -
                    NUM_CONST(MULTIPLE);
         | 
| 694 | 
            +
                    rb_define_const(mLMDB, "LIB_VERSION", rb_str_new2(MDB_VERSION_STRING));
         | 
| 695 | 
            +
                    rb_define_singleton_method(mLMDB, "new", environment_new, -1);
         | 
| 696 | 
            +
             | 
| 697 | 
            +
            #define VERSION_CONST(name) rb_define_const(mLMDB, "LIB_VERSION_"#name, INT2NUM(MDB_VERSION_##name));
         | 
| 698 | 
            +
                    VERSION_CONST(MAJOR)
         | 
| 699 | 
            +
                    VERSION_CONST(MINOR)
         | 
| 700 | 
            +
                    VERSION_CONST(PATCH)
         | 
| 701 | 
            +
            #undef VERSION_CONST
         | 
| 626 702 |  | 
| 627 703 | 
             
                    cError = rb_define_class_under(mLMDB, "Error", rb_eRuntimeError);
         | 
| 628 704 | 
             
            #define ERROR(name) cError_##name = rb_define_class_under(cError, #name, cError);
         | 
| @@ -630,15 +706,16 @@ void Init_lmdb_ext() { | |
| 630 706 | 
             
            #undef ERROR
         | 
| 631 707 |  | 
| 632 708 | 
             
                    cEnvironment = rb_define_class_under(mLMDB, "Environment", rb_cObject);
         | 
| 633 | 
            -
                     | 
| 634 | 
            -
                    rb_define_singleton_method(cEnvironment, "open", environment_open, -1);
         | 
| 709 | 
            +
                    rb_define_singleton_method(cEnvironment, "new", environment_new, -1);
         | 
| 635 710 | 
             
                    rb_define_method(cEnvironment, "database", environment_database, -1);
         | 
| 711 | 
            +
                    rb_define_method(cEnvironment, "active_txn", environment_active_txn, 0);
         | 
| 636 712 | 
             
                    rb_define_method(cEnvironment, "close", environment_close, 0);
         | 
| 637 713 | 
             
                    rb_define_method(cEnvironment, "stat", environment_stat, 0);
         | 
| 638 714 | 
             
                    rb_define_method(cEnvironment, "info", environment_info, 0);
         | 
| 639 715 | 
             
                    rb_define_method(cEnvironment, "copy", environment_copy, 1);
         | 
| 640 716 | 
             
                    rb_define_method(cEnvironment, "sync", environment_sync, -1);
         | 
| 641 | 
            -
                    rb_define_method(cEnvironment, " | 
| 717 | 
            +
                    rb_define_method(cEnvironment, "set_flags", environment_set_flags, -1);
         | 
| 718 | 
            +
                    rb_define_method(cEnvironment, "clear_flags", environment_clear_flags, -1);
         | 
| 642 719 | 
             
                    rb_define_method(cEnvironment, "flags", environment_flags, 0);
         | 
| 643 720 | 
             
                    rb_define_method(cEnvironment, "path", environment_path, 0);
         | 
| 644 721 | 
             
                    rb_define_method(cEnvironment, "transaction", environment_transaction, -1);
         | 
    
        data/ext/lmdb_ext/lmdb_ext.h
    CHANGED
    
    | @@ -4,16 +4,6 @@ | |
| 4 4 | 
             
            #include "ruby.h"
         | 
| 5 5 | 
             
            #include "lmdb.h"
         | 
| 6 6 |  | 
| 7 | 
            -
            #define ENV_FLAGS (                             \
         | 
| 8 | 
            -
                            MDB_FIXEDMAP    |               \
         | 
| 9 | 
            -
                            MDB_NOSUBDIR    |               \
         | 
| 10 | 
            -
                            MDB_NOSYNC      |               \
         | 
| 11 | 
            -
                            MDB_RDONLY      |               \
         | 
| 12 | 
            -
                            MDB_NOMETASYNC  |               \
         | 
| 13 | 
            -
                            MDB_WRITEMAP    |               \
         | 
| 14 | 
            -
                            MDB_MAPASYNC    |               \
         | 
| 15 | 
            -
                            MDB_NOTLS)
         | 
| 16 | 
            -
             | 
| 17 7 | 
             
            #define ENVIRONMENT(var, var_env)                       \
         | 
| 18 8 | 
             
                    Environment* var_env;                           \
         | 
| 19 9 | 
             
                    Data_Get_Struct(var, Environment, var_env);     \
         | 
| @@ -37,13 +27,15 @@ typedef struct Transaction Transaction; | |
| 37 27 | 
             
            typedef struct Transaction {
         | 
| 38 28 | 
             
                    VALUE    env;
         | 
| 39 29 | 
             
                    VALUE    parent;
         | 
| 30 | 
            +
                    VALUE    thread;
         | 
| 40 31 | 
             
                    MDB_txn* txn;
         | 
| 41 32 | 
             
                    int      refcount;
         | 
| 42 33 | 
             
            } Transaction;
         | 
| 43 34 |  | 
| 44 35 | 
             
            typedef struct {
         | 
| 45 36 | 
             
                    MDB_env* env;
         | 
| 46 | 
            -
                    VALUE     | 
| 37 | 
            +
                    VALUE    thread_txn_hash;
         | 
| 38 | 
            +
                    VALUE    txn_thread_hash;
         | 
| 47 39 | 
             
                    int      refcount;
         | 
| 48 40 | 
             
            } Environment;
         | 
| 49 41 |  | 
| @@ -65,6 +57,14 @@ typedef struct { | |
| 65 57 | 
             
                    const VALUE* argv;
         | 
| 66 58 | 
             
            } HelperArgs;
         | 
| 67 59 |  | 
| 60 | 
            +
            typedef struct {
         | 
| 61 | 
            +
                    mode_t mode;
         | 
| 62 | 
            +
                    int    flags;
         | 
| 63 | 
            +
                    int    maxreaders;
         | 
| 64 | 
            +
                    int    maxdbs;
         | 
| 65 | 
            +
                    size_t mapsize;
         | 
| 66 | 
            +
            } EnvironmentOptions;
         | 
| 67 | 
            +
             | 
| 68 68 | 
             
            static VALUE cEnvironment, cDatabase, cTransaction, cCursor, cError;
         | 
| 69 69 |  | 
| 70 70 | 
             
            #define ERROR(name) static VALUE cError_##name;
         | 
| @@ -73,6 +73,7 @@ static VALUE cEnvironment, cDatabase, cTransaction, cCursor, cError; | |
| 73 73 |  | 
| 74 74 | 
             
            // BEGIN PROTOTYPES
         | 
| 75 75 | 
             
            void Init_lmdb_ext();
         | 
| 76 | 
            +
            static MDB_txn* active_txn(VALUE self);
         | 
| 76 77 | 
             
            static VALUE call_with_transaction(VALUE venv, VALUE self, const char* name, int argc, const VALUE* argv, int flags);
         | 
| 77 78 | 
             
            static VALUE call_with_transaction_helper(VALUE arg);
         | 
| 78 79 | 
             
            static void check(int code);
         | 
| @@ -98,25 +99,31 @@ static VALUE database_get(VALUE self, VALUE vkey); | |
| 98 99 | 
             
            static void database_mark(Database* database);
         | 
| 99 100 | 
             
            static VALUE database_put(int argc, VALUE *argv, VALUE self);
         | 
| 100 101 | 
             
            static VALUE database_stat(VALUE self);
         | 
| 102 | 
            +
            static VALUE environment_active_txn(VALUE self);
         | 
| 103 | 
            +
            static VALUE environment_change_flags(int argc, VALUE* argv, VALUE self, int set);
         | 
| 101 104 | 
             
            static void environment_check(Environment* environment);
         | 
| 105 | 
            +
            static VALUE environment_clear_flags(int argc, VALUE* argv, VALUE self);
         | 
| 102 106 | 
             
            static VALUE environment_close(VALUE self);
         | 
| 103 107 | 
             
            static VALUE environment_copy(VALUE self, VALUE path);
         | 
| 104 108 | 
             
            static VALUE environment_database(int argc, VALUE *argv, VALUE self);
         | 
| 105 109 | 
             
            static void environment_deref(Environment *environment);
         | 
| 106 110 | 
             
            static VALUE environment_flags(VALUE self);
         | 
| 107 111 | 
             
            static VALUE environment_info(VALUE self);
         | 
| 108 | 
            -
            static  | 
| 109 | 
            -
            static VALUE  | 
| 112 | 
            +
            static void environment_mark(Environment* environment);
         | 
| 113 | 
            +
            static VALUE environment_new(int argc, VALUE *argv, VALUE klass);
         | 
| 114 | 
            +
            static int environment_options(VALUE key, VALUE value, EnvironmentOptions* options);
         | 
| 110 115 | 
             
            static VALUE environment_path(VALUE self);
         | 
| 111 | 
            -
            static  | 
| 116 | 
            +
            static void environment_set_active_txn(VALUE self, VALUE thread, VALUE txn);
         | 
| 117 | 
            +
            static VALUE environment_set_flags(int argc, VALUE* argv, VALUE self);
         | 
| 112 118 | 
             
            static VALUE environment_stat(VALUE self);
         | 
| 113 119 | 
             
            static VALUE environment_sync(int argc, VALUE *argv, VALUE self);
         | 
| 114 120 | 
             
            static VALUE environment_transaction(int argc, VALUE *argv, VALUE self);
         | 
| 115 | 
            -
            static MDB_txn*  | 
| 121 | 
            +
            static MDB_txn* need_txn(VALUE self);
         | 
| 116 122 | 
             
            static VALUE stat2hash(const MDB_stat* stat);
         | 
| 117 123 | 
             
            static VALUE transaction_abort(VALUE self);
         | 
| 118 124 | 
             
            static VALUE transaction_commit(VALUE self);
         | 
| 119 125 | 
             
            static void transaction_deref(Transaction* transaction);
         | 
| 126 | 
            +
            static void transaction_finish(VALUE self, int commit);
         | 
| 120 127 | 
             
            static void transaction_mark(Transaction* transaction);
         | 
| 121 128 | 
             
            static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flags);
         | 
| 122 129 | 
             
            // END PROTOTYPES
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            module LMDB
         | 
| 2 | 
            +
              class Database
         | 
| 3 | 
            +
                include Enumerable
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def each
         | 
| 6 | 
            +
                  cursor do |c|
         | 
| 7 | 
            +
                    while i = c.next
         | 
| 8 | 
            +
                      yield(i)
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def [](key)
         | 
| 14 | 
            +
                  get(key)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def []=(key, value)
         | 
| 18 | 
            +
                  put(key, value)
         | 
| 19 | 
            +
                  value
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def size
         | 
| 23 | 
            +
                  stat[:entries]
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
    
        data/lib/lmdb/version.rb
    ADDED
    
    
    
        data/lib/lmdb.rb
    CHANGED
    
    | @@ -1,29 +1,3 @@ | |
| 1 1 | 
             
            require 'lmdb_ext'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
              class Database
         | 
| 5 | 
            -
                include Enumerable
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                def each
         | 
| 8 | 
            -
                  cursor do |c|
         | 
| 9 | 
            -
                    while i = c.next
         | 
| 10 | 
            -
                      yield(i)
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                def [](key)
         | 
| 16 | 
            -
                  get(key)
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                def []=(key, value)
         | 
| 20 | 
            -
                  put(key, value)
         | 
| 21 | 
            -
                  value
         | 
| 22 | 
            -
                end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                def size
         | 
| 25 | 
            -
                  stat[:entries]
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
              end
         | 
| 28 | 
            -
            end
         | 
| 29 | 
            -
             | 
| 2 | 
            +
            require 'lmdb/version'
         | 
| 3 | 
            +
            require 'lmdb/database'
         | 
    
        data/lmdb.gemspec
    CHANGED
    
    | @@ -1,9 +1,12 @@ | |
| 1 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            require File.dirname(__FILE__) + '/lib/lmdb/version'
         | 
| 3 | 
            +
            require 'date'
         | 
| 2 4 |  | 
| 3 5 | 
             
            Gem::Specification.new do |s|
         | 
| 4 6 | 
             
              s.name        = File.basename(__FILE__, '.gemspec')
         | 
| 5 | 
            -
              s.version     =  | 
| 7 | 
            +
              s.version     = LMDB::VERSION
         | 
| 6 8 | 
             
              s.platform    = Gem::Platform::RUBY
         | 
| 9 | 
            +
              s.date        = Date.today.to_s
         | 
| 7 10 | 
             
              s.licenses    = ['MIT']
         | 
| 8 11 | 
             
              s.summary     = 'Ruby bindings to Lightning MDB'
         | 
| 9 12 | 
             
              s.email       = 'mail@daniel-mendler.de'
         | 
    
        data/spec/lmdb_spec.rb
    CHANGED
    
    | @@ -2,71 +2,50 @@ | |
| 2 2 | 
             
            require 'helper'
         | 
| 3 3 |  | 
| 4 4 | 
             
            describe LMDB do
         | 
| 5 | 
            -
              let(:env) { LMDB. | 
| 5 | 
            +
              let(:env) { LMDB.new(path) }
         | 
| 6 6 | 
             
              after     { env.close rescue nil }
         | 
| 7 7 |  | 
| 8 8 | 
             
              let(:db)  { env.database }
         | 
| 9 9 |  | 
| 10 10 | 
             
              it 'has version constants' do
         | 
| 11 | 
            -
                LMDB:: | 
| 12 | 
            -
                LMDB:: | 
| 13 | 
            -
                LMDB:: | 
| 11 | 
            +
                LMDB::LIB_VERSION_MAJOR.should be_instance_of(Fixnum)
         | 
| 12 | 
            +
                LMDB::LIB_VERSION_MINOR.should be_instance_of(Fixnum)
         | 
| 13 | 
            +
                LMDB::LIB_VERSION_PATCH.should be_instance_of(Fixnum)
         | 
| 14 | 
            +
                LMDB::LIB_VERSION.should be_instance_of(String)
         | 
| 14 15 | 
             
                LMDB::VERSION.should be_instance_of(String)
         | 
| 15 16 | 
             
              end
         | 
| 16 17 |  | 
| 17 | 
            -
              it 'has environment flags' do
         | 
| 18 | 
            -
                LMDB::FIXEDMAP.should be_instance_of(Fixnum)
         | 
| 19 | 
            -
                LMDB::NOSUBDIR.should be_instance_of(Fixnum)
         | 
| 20 | 
            -
                LMDB::NOSYNC.should be_instance_of(Fixnum)
         | 
| 21 | 
            -
                LMDB::RDONLY.should be_instance_of(Fixnum)
         | 
| 22 | 
            -
                LMDB::NOMETASYNC.should be_instance_of(Fixnum)
         | 
| 23 | 
            -
                LMDB::WRITEMAP.should be_instance_of(Fixnum)
         | 
| 24 | 
            -
                LMDB::MAPASYNC.should be_instance_of(Fixnum)
         | 
| 25 | 
            -
                LMDB::NOTLS.should be_instance_of(Fixnum)
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
              it 'has database flags' do
         | 
| 29 | 
            -
                LMDB::REVERSEKEY.should be_instance_of(Fixnum)
         | 
| 30 | 
            -
                LMDB::DUPSORT.should be_instance_of(Fixnum)
         | 
| 31 | 
            -
                LMDB::INTEGERKEY.should be_instance_of(Fixnum)
         | 
| 32 | 
            -
                LMDB::DUPFIXED.should be_instance_of(Fixnum)
         | 
| 33 | 
            -
                LMDB::INTEGERDUP.should be_instance_of(Fixnum)
         | 
| 34 | 
            -
                LMDB::REVERSEDUP.should be_instance_of(Fixnum)
         | 
| 35 | 
            -
                LMDB::CREATE.should be_instance_of(Fixnum)
         | 
| 36 | 
            -
                LMDB::NOOVERWRITE.should be_instance_of(Fixnum)
         | 
| 37 | 
            -
                LMDB::NODUPDATA.should be_instance_of(Fixnum)
         | 
| 38 | 
            -
                LMDB::CURRENT.should be_instance_of(Fixnum)
         | 
| 39 | 
            -
                LMDB::RESERVE.should be_instance_of(Fixnum)
         | 
| 40 | 
            -
                LMDB::APPEND.should be_instance_of(Fixnum)
         | 
| 41 | 
            -
                LMDB::APPENDDUP.should be_instance_of(Fixnum)
         | 
| 42 | 
            -
                LMDB::MULTIPLE.should be_instance_of(Fixnum)
         | 
| 43 | 
            -
              end
         | 
| 44 | 
            -
             | 
| 45 18 | 
             
              describe LMDB::Environment do
         | 
| 46 19 | 
             
                subject { env }
         | 
| 47 20 |  | 
| 48 | 
            -
                 | 
| 49 | 
            -
             | 
| 21 | 
            +
                it 'should return flags' do
         | 
| 22 | 
            +
                  subject.flags.should be_instance_of(Array)
         | 
| 23 | 
            +
                end
         | 
| 50 24 |  | 
| 51 | 
            -
                describe ' | 
| 25 | 
            +
                describe 'new' do
         | 
| 52 26 | 
             
                  it 'returns environment' do
         | 
| 53 | 
            -
                    env = LMDB::Environment. | 
| 27 | 
            +
                    env = LMDB::Environment.new(path)
         | 
| 54 28 | 
             
                    env.should be_instance_of(described_class::Environment)
         | 
| 55 29 | 
             
                    env.close
         | 
| 56 30 | 
             
                  end
         | 
| 57 31 |  | 
| 58 32 | 
             
                  it 'accepts block' do
         | 
| 59 | 
            -
                    LMDB::Environment. | 
| 33 | 
            +
                    LMDB::Environment.new(path) do |env|
         | 
| 60 34 | 
             
                      env.should be_instance_of(described_class::Environment)
         | 
| 61 35 | 
             
                      42
         | 
| 62 36 | 
             
                    end.should == 42
         | 
| 63 37 | 
             
                  end
         | 
| 64 38 |  | 
| 65 39 | 
             
                  it 'accepts options' do
         | 
| 66 | 
            -
                    env = LMDB::Environment. | 
| 40 | 
            +
                    env = LMDB::Environment.new(path, :nosync => true, :mode => 0777, :maxreaders => 777, :mapsize => 111111, :maxdbs => 666)
         | 
| 67 41 | 
             
                    env.should be_instance_of(described_class::Environment)
         | 
| 68 42 | 
             
                    env.info[:maxreaders].should == 777
         | 
| 69 43 | 
             
                    env.info[:mapsize].should == 111111
         | 
| 44 | 
            +
                    env.flags.should include(:nosync)
         | 
| 45 | 
            +
                    env.close
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    env = LMDB::Environment.new(path, :nosync => false)
         | 
| 48 | 
            +
                    env.flags.should_not include(:nosync)
         | 
| 70 49 | 
             
                    env.close
         | 
| 71 50 | 
             
                  end
         | 
| 72 51 | 
             
                end
         | 
| @@ -105,58 +84,84 @@ describe LMDB do | |
| 105 84 | 
             
                end
         | 
| 106 85 |  | 
| 107 86 | 
             
                it 'should accept custom flags' do
         | 
| 108 | 
            -
                   | 
| 109 | 
            -
                  subject.flags.should == LMDB::NOSYNC
         | 
| 87 | 
            +
                  subject.flags.should_not include(:nosync)
         | 
| 110 88 |  | 
| 111 | 
            -
                   | 
| 112 | 
            -
                  subject.flags.should  | 
| 89 | 
            +
                  subject.set_flags :nosync
         | 
| 90 | 
            +
                  subject.flags.should include(:nosync)
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  subject.clear_flags :nosync
         | 
| 93 | 
            +
                  subject.flags.should_not include(:nosync)
         | 
| 113 94 | 
             
                end
         | 
| 114 95 |  | 
| 115 96 | 
             
                describe 'transaction' do
         | 
| 116 97 | 
             
                  subject { env}
         | 
| 117 98 |  | 
| 118 99 | 
             
                  it 'should create transactions' do
         | 
| 100 | 
            +
                    subject.active_txn.should == nil
         | 
| 119 101 | 
             
                    subject.transaction do |txn|
         | 
| 102 | 
            +
                      subject.active_txn.should == txn
         | 
| 120 103 | 
             
                      txn.should be_instance_of(described_class::Transaction)
         | 
| 121 104 | 
             
                      txn.abort
         | 
| 105 | 
            +
                      subject.active_txn.should == nil
         | 
| 122 106 | 
             
                    end
         | 
| 107 | 
            +
                    subject.active_txn.should == nil
         | 
| 123 108 | 
             
                  end
         | 
| 124 109 |  | 
| 125 110 | 
             
                  it 'should create read-only transactions' do
         | 
| 111 | 
            +
                    subject.active_txn.should == nil
         | 
| 126 112 | 
             
                    subject.transaction(true) do |txn|
         | 
| 113 | 
            +
                      subject.active_txn.should == txn
         | 
| 127 114 | 
             
                      txn.should be_instance_of(described_class::Transaction)
         | 
| 128 115 | 
             
                      txn.abort
         | 
| 116 | 
            +
                      subject.active_txn.should == nil
         | 
| 129 117 | 
             
                    end
         | 
| 118 | 
            +
                    subject.active_txn.should == nil
         | 
| 130 119 | 
             
                  end
         | 
| 131 120 |  | 
| 132 121 | 
             
                  it 'can create child transactions' do
         | 
| 122 | 
            +
                    subject.active_txn.should == nil
         | 
| 133 123 | 
             
                    env.transaction do |txn|
         | 
| 134 | 
            -
                       | 
| 124 | 
            +
                      subject.active_txn.should == txn
         | 
| 135 125 | 
             
                      env.transaction do |ctxn|
         | 
| 136 | 
            -
                         | 
| 126 | 
            +
                        subject.active_txn.should == ctxn
         | 
| 137 127 | 
             
                        ctxn.abort
         | 
| 128 | 
            +
                        subject.active_txn.should == txn
         | 
| 138 129 | 
             
                      end
         | 
| 130 | 
            +
                      subject.active_txn.should == txn
         | 
| 139 131 | 
             
                    end
         | 
| 132 | 
            +
                    subject.active_txn.should == nil
         | 
| 140 133 | 
             
                  end
         | 
| 141 134 |  | 
| 142 135 | 
             
                  it 'should support aborting parent transaction' do
         | 
| 136 | 
            +
                    subject.active_txn.should == nil
         | 
| 143 137 | 
             
                    env.transaction do |txn|
         | 
| 138 | 
            +
                      subject.active_txn.should == txn
         | 
| 144 139 | 
             
                      env.transaction do |ctxn|
         | 
| 140 | 
            +
                        subject.active_txn.should == ctxn
         | 
| 145 141 | 
             
                        db['key'] = 'value'
         | 
| 146 142 | 
             
                        txn.abort
         | 
| 143 | 
            +
                        subject.active_txn.should == nil
         | 
| 147 144 | 
             
                      end
         | 
| 145 | 
            +
                      subject.active_txn.should == nil
         | 
| 148 146 | 
             
                    end
         | 
| 149 147 | 
             
                    db['key'].should be(nil)
         | 
| 148 | 
            +
                    subject.active_txn.should == nil
         | 
| 150 149 | 
             
                  end
         | 
| 151 150 |  | 
| 152 151 | 
             
                  it 'should support comitting parent transaction' do
         | 
| 152 | 
            +
                    subject.active_txn.should == nil
         | 
| 153 153 | 
             
                    env.transaction do |txn|
         | 
| 154 | 
            +
                      subject.active_txn.should == txn
         | 
| 154 155 | 
             
                      env.transaction do |ctxn|
         | 
| 156 | 
            +
                        subject.active_txn.should == ctxn
         | 
| 155 157 | 
             
                        db['key'] = 'value'
         | 
| 156 158 | 
             
                        txn.commit
         | 
| 159 | 
            +
                        subject.active_txn.should == nil
         | 
| 157 160 | 
             
                      end
         | 
| 161 | 
            +
                      subject.active_txn.should == nil
         | 
| 158 162 | 
             
                    end
         | 
| 159 163 | 
             
                    db['key'].should == 'value'
         | 
| 164 | 
            +
                    subject.active_txn.should == nil
         | 
| 160 165 | 
             
                  end
         | 
| 161 166 | 
             
                end
         | 
| 162 167 | 
             
              end
         | 
| @@ -164,6 +169,20 @@ describe LMDB do | |
| 164 169 | 
             
              describe LMDB::Database do
         | 
| 165 170 | 
             
                subject { db }
         | 
| 166 171 |  | 
| 172 | 
            +
                it 'should support named databases' do
         | 
| 173 | 
            +
                  main = env.database
         | 
| 174 | 
            +
                  db1 = env.database('db1', :create => true)
         | 
| 175 | 
            +
                  db2 = env.database('db2', :create => true)
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                  main['key'] = '1'
         | 
| 178 | 
            +
                  db1['key'] = '2'
         | 
| 179 | 
            +
                  db2['key'] = '3'
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                  main['key'].should == '1'
         | 
| 182 | 
            +
                  db1['key'].should == '2'
         | 
| 183 | 
            +
                  db2['key'].should == '3'
         | 
| 184 | 
            +
                end
         | 
| 185 | 
            +
             | 
| 167 186 | 
             
                it 'should get/put data' do
         | 
| 168 187 | 
             
                  subject.get('cat').should be_nil
         | 
| 169 188 | 
             
                  subject.put('cat', 'garfield').should be_nil
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: lmdb
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Daniel Mendler
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2013-09- | 
| 11 | 
            +
            date: 2013-09-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rake
         | 
| @@ -66,8 +66,13 @@ files: | |
| 66 66 | 
             
            - Gemfile
         | 
| 67 67 | 
             
            - README.md
         | 
| 68 68 | 
             
            - Rakefile
         | 
| 69 | 
            +
            - ext/lmdb_ext/cursor_delete_flags.h
         | 
| 70 | 
            +
            - ext/lmdb_ext/cursor_put_flags.h
         | 
| 71 | 
            +
            - ext/lmdb_ext/dbi_flags.h
         | 
| 72 | 
            +
            - ext/lmdb_ext/env_flags.h
         | 
| 69 73 | 
             
            - ext/lmdb_ext/errors.h
         | 
| 70 74 | 
             
            - ext/lmdb_ext/extconf.rb
         | 
| 75 | 
            +
            - ext/lmdb_ext/flag_parser.h
         | 
| 71 76 | 
             
            - ext/lmdb_ext/liblmdb/.gitignore
         | 
| 72 77 | 
             
            - ext/lmdb_ext/liblmdb/CHANGES
         | 
| 73 78 | 
             
            - ext/lmdb_ext/liblmdb/COPYRIGHT
         | 
| @@ -79,7 +84,10 @@ files: | |
| 79 84 | 
             
            - ext/lmdb_ext/lmdb_ext.c
         | 
| 80 85 | 
             
            - ext/lmdb_ext/lmdb_ext.h
         | 
| 81 86 | 
             
            - ext/lmdb_ext/prototypes.sh
         | 
| 87 | 
            +
            - ext/lmdb_ext/put_flags.h
         | 
| 82 88 | 
             
            - lib/lmdb.rb
         | 
| 89 | 
            +
            - lib/lmdb/database.rb
         | 
| 90 | 
            +
            - lib/lmdb/version.rb
         | 
| 83 91 | 
             
            - lmdb.gemspec
         | 
| 84 92 | 
             
            - spec/helper.rb
         | 
| 85 93 | 
             
            - spec/lmdb_spec.rb
         | 
| @@ -103,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 103 111 | 
             
                  version: '0'
         | 
| 104 112 | 
             
            requirements: []
         | 
| 105 113 | 
             
            rubyforge_project: 
         | 
| 106 | 
            -
            rubygems_version: 2.0. | 
| 114 | 
            +
            rubygems_version: 2.0.3
         | 
| 107 115 | 
             
            signing_key: 
         | 
| 108 116 | 
             
            specification_version: 4
         | 
| 109 117 | 
             
            summary: Ruby bindings to Lightning MDB
         |