File: dbm_leveldb.cpp

package info (click to toggle)
freecell-solver 3.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 4,332 kB
  • sloc: ansic: 29,493; perl: 8,911; xml: 5,162; python: 1,124; sh: 777; ruby: 358; cpp: 304; makefile: 150
file content (128 lines) | stat: -rw-r--r-- 3,096 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <cassert>
#include "leveldb/db.h"
#include "leveldb/write_batch.h"

#include "dbm_common.h"
#include "dbm_solver.h"
#include "dbm_cache.h"

extern "C" void fc_solve_dbm_store_init(fcs_dbm_store_t * store, const char * path)
{
    leveldb::DB * db;
    leveldb::Options options;
    options.create_if_missing = true;
    leveldb::Status status = leveldb::DB::Open(options, path, &db);
    assert(status.ok());

    *store = (fcs_dbm_store_t)db;
}

extern "C" fcs_bool_t fc_solve_dbm_store_does_key_exist(
    fcs_dbm_store_t store,
    const unsigned char * key_raw
)
{
    leveldb::Slice key((const char *)(key_raw+1),key_raw[0]);
    std::string value;

    return
        ((leveldb::DB *)store)->Get(leveldb::ReadOptions(), key, &value).ok();
}

fcs_bool_t fc_solve_dbm_store_lookup_parent_and_move(
    fcs_dbm_store_t store,
    const unsigned char * key_raw,
    unsigned char * parent_and_move
    )
{
    leveldb::Slice key((const char *)(key_raw+1),key_raw[0]);
    std::string value;

    leveldb::Status status =
        ((leveldb::DB *)store)->Get(leveldb::ReadOptions(), key, &value);

    if (status.ok())
    {
        memcpy(
            parent_and_move+1,
            value.data()+1,
            (parent_and_move[0] = value.length()-1)+1
        );

        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

#define MAX_ITEMS_IN_TRANSACTION 10000
extern "C" void fc_solve_dbm_store_offload_pre_cache(
    fcs_dbm_store_t store,
    fcs_pre_cache_t * pre_cache
)
{
    leveldb::DB * db;
#ifdef FCS_DBM_USE_LIBAVL
    struct avl_traverser trav;
    dict_key_t item;
#else
    dnode_t * node;
#endif
    dict_t * kaz_tree;
    int num_left_in_transaction = MAX_ITEMS_IN_TRANSACTION;
    leveldb::WriteBatch batch;
    fcs_pre_cache_key_val_pair_t * kv;

    db = (leveldb::DB *)store;
    kaz_tree = pre_cache->kaz_tree;

#ifdef FCS_DBM_USE_LIBAVL
    avl_t_init(&trav, kaz_tree);
#endif

#ifdef FCS_DBM_USE_LIBAVL
    for (
        item = avl_t_first(&trav, kaz_tree)
            ;
        item
            ;
        item = avl_t_next(&trav)
        )
#else
    for (node = fc_solve_kaz_tree_first(kaz_tree);
            node ;
            node = fc_solve_kaz_tree_next(kaz_tree, node)
            )
#define item (node->dict_key)
#endif
    {
        kv = (fcs_pre_cache_key_val_pair_t *)(item);

    leveldb::Slice key((const char *)(kv->key.s+1),kv->key.s[0]);
    /* We add 1 to the parent and move's length because it includes the
     * trailing one-char move.
     * */
    leveldb::Slice parent_and_move((const char *)(kv->parent_and_move.s+1),kv->parent_and_move.s[0]+1);
        batch.Put(key, parent_and_move);

        if ((--num_left_in_transaction) <= 0)
        {
#define WRITE() assert(db->Write(leveldb::WriteOptions(), &batch).ok())
            WRITE();
            batch.Clear();
            num_left_in_transaction = MAX_ITEMS_IN_TRANSACTION;
        }
    }
    WRITE();
#undef WRITE
}
#ifndef FCS_DBM_USE_LIBAVL
#undef item
#endif

extern "C" void fc_solve_dbm_store_destroy(fcs_dbm_store_t store)
{
    delete ((leveldb::DB *)store);
}