Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 375 lines (333 sloc) 16.693 kb
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
// leveldb-sharp
//
// Copyright (c) 2012 Mirco Bauer <meebey@meebey.net>
// Copyright (c) 2011 The LevelDB Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace LevelDB
{
    public static class Native
    {
        static void CheckError(string error)
        {
            if (String.IsNullOrEmpty(error)) {
                return;
            }
            throw new ApplicationException(error);
        }

        static UIntPtr GetStringLength(string value)
        {
            return new UIntPtr((uint) Encoding.UTF8.GetByteCount(value));
        }

        // extern leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name, char** errptr);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_open(IntPtr options, string name, out string error);
        public static IntPtr leveldb_open(IntPtr options, string name)
        {
            string error;
            var db = leveldb_open(options, name, out error);
            CheckError(error);
            return db;
        }

        // extern void leveldb_close(leveldb_t* db);
[DllImport("leveldb")]
        public static extern void leveldb_close(IntPtr db);

        // extern void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options, const char* key, size_t keylen, const char* val, size_t vallen, char** errptr);
[DllImport("leveldb")]
        public static extern void leveldb_put(IntPtr db,
                                              IntPtr writeOptions,
                                              string key,
                                              UIntPtr keyLength,
                                              string value,
                                              UIntPtr valueLength,
                                              out string error);
        public static void leveldb_put(IntPtr db,
                                       IntPtr writeOptions,
                                       string key,
                                       string value)
        {
            string error;
            var keyLength = GetStringLength(key);
            var valueLength = GetStringLength(value);
            Native.leveldb_put(db, writeOptions,
                               key, keyLength,
                               value, valueLength, out error);
            CheckError(error);
        }

        // extern void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options, const char* key, size_t keylen, char** errptr);
[DllImport("leveldb")]
        public static extern void leveldb_delete(IntPtr db, IntPtr writeOptions, string key, UIntPtr keylen, out string error);
        public static void leveldb_delete(IntPtr db, IntPtr writeOptions, string key)
        {
            string error;
            var keyLength = GetStringLength(key);
            leveldb_delete(db, writeOptions, key, keyLength, out error);
            CheckError(error);
        }

        // extern void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options, leveldb_writebatch_t* batch, char** errptr);
[DllImport("leveldb")]
        public static extern void leveldb_write(IntPtr db, IntPtr options, IntPtr batch, out string error);

        // extern char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options, const char* key, size_t keylen, size_t* vallen, char** errptr);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_get(IntPtr db,
                                                IntPtr readOptions,
                                                string key,
                                                UIntPtr keyLength,
                                                out UIntPtr valueLength,
                                                out string error);
        public static string leveldb_get(IntPtr db,
                                         IntPtr readOptions,
                                         string key)
        {
            UIntPtr valueLength;
            string error;
            var keyLength = GetStringLength(key);
            var valuePtr = leveldb_get(db, readOptions, key, keyLength,
                                       out valueLength, out error);
            CheckError(error);
            if (valuePtr == IntPtr.Zero || valueLength == UIntPtr.Zero) {
                return null;
            }
            var value = Marshal.PtrToStringAnsi(valuePtr, (int) valueLength);
            return value;
        }

        // extern leveldb_iterator_t* leveldb_create_iterator(leveldb_t* db, const leveldb_readoptions_t* options);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_create_iterator(IntPtr db, IntPtr readOptions);

#region Options
        // extern leveldb_options_t* leveldb_options_create();
[DllImport("leveldb")]
        public static extern IntPtr leveldb_options_create();

        // extern void leveldb_options_destroy(leveldb_options_t*);
[DllImport("leveldb")]
        public static extern void leveldb_options_destroy(IntPtr options);

        // extern void leveldb_options_set_comparator(leveldb_options_t*, leveldb_comparator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_comparator(IntPtr options, IntPtr comparator);

        /// <summary>
        /// If true, the database will be created if it is missing.
        /// Default: false
        /// </summary>
        // extern void leveldb_options_set_create_if_missing(leveldb_options_t*, unsigned char);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_create_if_missing(IntPtr options, bool value);

        /// <summary>
        /// If true, an error is raised if the database already exists.
        /// Default: false
        /// </summary>
        // extern void leveldb_options_set_error_if_exists(leveldb_options_t*, unsigned char);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_error_if_exists(IntPtr options, bool value);

        /// <summary>
        /// If true, the implementation will do aggressive checking of the
        /// data it is processing and will stop early if it detects any
        /// errors. This may have unforeseen ramifications: for example, a
        /// corruption of one DB entry may cause a large number of entries to
        /// become unreadable or for the entire DB to become unopenable.
        /// Default: false
        /// </summary>
        // extern void leveldb_options_set_paranoid_checks(leveldb_options_t*, unsigned char);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_paranoid_checks(IntPtr options, bool value);

        /// <summary>
        /// Number of open files that can be used by the DB. You may need to
        /// increase this if your database has a large working set (budget
        /// one open file per 2MB of working set).
        ///
        /// Default: 1000
        /// </summary>
        // extern void leveldb_options_set_max_open_files(leveldb_options_t*, int);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_max_open_files(IntPtr options, int value);

        // extern void leveldb_options_set_compression(leveldb_options_t*, int);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_compression(IntPtr options, int value);

        /// <summary>
        /// Control over blocks (user data is stored in a set of blocks, and
        /// a block is the unit of reading from disk).
        ///
        /// If non-NULL, use the specified cache for blocks.
        /// If NULL, leveldb will automatically create and use an 8MB internal cache.
        /// Default: NULL
        /// </summary>
        // extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*);
[DllImport("leveldb")]
        public static extern void leveldb_options_set_cache(IntPtr options, IntPtr cache);
        public static void leveldb_options_set_cache_size(IntPtr options, int capacity)
        {
            var cache = leveldb_cache_create_lru((UIntPtr) capacity);
            leveldb_options_set_cache(options, cache);
        }

        /// <summary>
        /// Approximate size of user data packed per block. Note that the
        /// block size specified here corresponds to uncompressed data. The
        /// actual size of the unit read from disk may be smaller if
        /// compression is enabled. This parameter can be changed dynamically.
        ///
        /// Default: 4K
        /// </summary>
        // extern void leveldb_options_set_block_size(leveldb_options_t*, size_t);

        /// <summary>
        /// Amount of data to build up in memory (backed by an unsorted log
        /// on disk) before converting to a sorted on-disk file.
        ///
        /// Larger values increase performance, especially during bulk loads.
        /// Up to two write buffers may be held in memory at the same time,
        /// so you may wish to adjust this parameter to control memory usage.
        /// Also, a larger write buffer will result in a longer recovery time
        /// the next time the database is opened.
        ///
        /// Default: 4MB
        /// </summary>
        // extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t);

        // TODO:
        /*
extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t);
extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*);
extern void leveldb_options_set_block_size(leveldb_options_t*, size_t);
extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int);
enum {
leveldb_no_compression = 0,
leveldb_snappy_compression = 1
};
*/
#endregion

#region Read Options
        // extern leveldb_readoptions_t* leveldb_readoptions_create();
[DllImport("leveldb")]
        public static extern IntPtr leveldb_readoptions_create();

        // extern void leveldb_readoptions_destroy(leveldb_readoptions_t*);
[DllImport("leveldb")]
        public static extern void leveldb_readoptions_destroy(IntPtr readOptions);

        /*
extern void leveldb_readoptions_set_verify_checksums(
leveldb_readoptions_t*,
unsigned char);
extern void leveldb_readoptions_set_snapshot(
leveldb_readoptions_t*,
const leveldb_snapshot_t*);
*/

        // extern void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t*, unsigned char);
[DllImport("leveldb")]
        public static extern void leveldb_readoptions_set_fill_cache(IntPtr readOptions, bool value);
#endregion

#region Write Options
        // extern leveldb_writeoptions_t* leveldb_writeoptions_create();
[DllImport("leveldb")]
        public static extern IntPtr leveldb_writeoptions_create();

        // extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*);
[DllImport("leveldb")]
        public static extern void leveldb_writeoptions_destroy(IntPtr writeOptions);

        /*
extern void leveldb_writeoptions_set_sync(
leveldb_writeoptions_t*, unsigned char);
*/
#endregion

#region Iterator
        // extern void leveldb_iter_seek_to_first(leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_iter_seek_to_first(IntPtr iter);

        // extern void leveldb_iter_seek_to_last(leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_iter_seek_to_last(IntPtr iter);

        // extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen);
[DllImport("leveldb")]
        public static extern void leveldb_iter_seek(IntPtr iter, string key, UIntPtr keyLength);
        public static void leveldb_iter_seek(IntPtr iter, string key)
        {
            var keyLength = GetStringLength(key);
            leveldb_iter_seek(iter, key, keyLength);
        }

        // extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern bool leveldb_iter_valid(IntPtr iter);

        // extern void leveldb_iter_prev(leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_iter_prev(IntPtr iter);

        // extern void leveldb_iter_next(leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_iter_next(IntPtr iter);

        // extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_iter_key(IntPtr iter, out UIntPtr keyLength);
        public static string leveldb_iter_key(IntPtr iter)
        {
            UIntPtr keyLength;
            var keyPtr = leveldb_iter_key(iter, out keyLength);
            if (keyPtr == IntPtr.Zero || keyLength == UIntPtr.Zero) {
                return null;
            }
            var key = Marshal.PtrToStringAnsi(keyPtr, (int) keyLength);
            return key;
        }

        // extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_iter_value(IntPtr iter, out UIntPtr valueLength);
        public static string leveldb_iter_value(IntPtr iter)
        {
            UIntPtr valueLength;
            var valuePtr = leveldb_iter_value(iter, out valueLength);
            if (valuePtr == IntPtr.Zero || valueLength == UIntPtr.Zero) {
                return null;
            }
            var value = Marshal.PtrToStringAnsi(valuePtr, (int) valueLength);
            return value;
        }

        // extern void leveldb_iter_destroy(leveldb_iterator_t*);
[DllImport("leveldb")]
        public static extern void leveldb_iter_destroy(IntPtr iter);

        /*
extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr);
*/
#endregion

#region Cache
        // extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity);
[DllImport("leveldb")]
        public static extern IntPtr leveldb_cache_create_lru(UIntPtr capacity);

        // extern void leveldb_cache_destroy(leveldb_cache_t* cache);
[DllImport("leveldb")]
        public static extern void leveldb_cache_destroy(IntPtr cache);
#endregion

        public static void Dump(IntPtr db)
        {
            var options = Native.leveldb_readoptions_create();
            IntPtr iter = Native.leveldb_create_iterator(db, options);
            for (Native.leveldb_iter_seek_to_first(iter);
                 Native.leveldb_iter_valid(iter);
                 Native.leveldb_iter_next(iter)) {
                string key = Native.leveldb_iter_key(iter);
                string value = Native.leveldb_iter_value(iter);
                Console.WriteLine("'{0}' => '{1}'", key, value);
            }
            Native.leveldb_iter_destroy(iter);
        }
    }
}
Something went wrong with that request. Please try again.