github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/db.go (about)

     1  // Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package leveldb
     6  
     7  import (
     8  	"runtime"
     9  )
    10  
    11  const (
    12  	MajorVersion = 1
    13  	MinorVersion = 14
    14  )
    15  
    16  // Snapshot provides a consistent view of read operations in a DB. It is set
    17  // on to a ReadOptions and passed in. It is only created by DB.NewSnapshot.
    18  type Snapshot struct {
    19  	snap *leveldb_snapshot_t
    20  }
    21  
    22  // Range is a key range.
    23  type Range struct {
    24  	Start []byte // Start of the key range, include in the range.
    25  	Limit []byte // Limit of the key range, not include in the range.
    26  }
    27  
    28  // DB is a reusable handle to a LevelDB database on disk, created by Open.
    29  //
    30  // To avoid memory and file descriptor leaks, call Close when the process no
    31  // longer needs the handle. Calls to any DB method made after Close will
    32  // panic.
    33  //
    34  // The DB instance may be shared between goroutines. The usual data race
    35  // conditions will occur if the same key is written to from more than one, of
    36  // course.
    37  type DB struct {
    38  	*dbHandler
    39  }
    40  type dbHandler struct {
    41  	db              *leveldb_t
    42  	defaultOpt      *leveldb_options_t
    43  	defaultReadOpt  *leveldb_readoptions_t
    44  	defaultWriteOpt *leveldb_writeoptions_t
    45  	optState        optStateContainer
    46  	opt             Options
    47  }
    48  
    49  // Open opens a database.
    50  //
    51  // Creating a new database is done by calling SetCreateIfMissing(true) on the
    52  // Options passed to Open.
    53  //
    54  // It is usually wise to set a Cache object on the Options with SetCache to
    55  // keep recently used data from that database in memory.
    56  func Open(name string, opt *Options) (*DB, error) {
    57  	var err error
    58  
    59  	h := &dbHandler{}
    60  	if opt != nil {
    61  		h.opt = *opt
    62  	}
    63  	h.defaultOpt = leveldb_options_create_copy(&h.optState, &h.opt)
    64  	h.defaultReadOpt = leveldb_readoptions_create()
    65  	h.defaultWriteOpt = leveldb_writeoptions_create()
    66  	defer func() {
    67  		if err != nil {
    68  			leveldb_options_destroy(h.defaultOpt)
    69  			leveldb_readoptions_destroy(h.defaultReadOpt)
    70  			leveldb_writeoptions_destroy(h.defaultWriteOpt)
    71  		}
    72  	}()
    73  
    74  	h.db, err = leveldb_open(name, h.defaultOpt)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	runtime.SetFinalizer(h, (*dbHandler).Close)
    80  	return &DB{h}, nil
    81  }
    82  
    83  // Close closes the database, rendering it unusable for I/O, by deallocating
    84  // the underlying handle.
    85  //
    86  // Any attempts to use the DB after Close is called will panic.
    87  func (p *dbHandler) Close() {
    88  	runtime.SetFinalizer(p, nil)
    89  
    90  	leveldb_close(p.db)
    91  	leveldb_options_destroy(p.defaultOpt)
    92  	leveldb_readoptions_destroy(p.defaultReadOpt)
    93  	leveldb_writeoptions_destroy(p.defaultWriteOpt)
    94  	*p = dbHandler{}
    95  }
    96  
    97  // Get returns the data associated with the key from the database.
    98  //
    99  // If the key does not exist in the database, a nil Value is returned. If the
   100  // key does exist, but the data is zero-length in the database, a zero-length
   101  // Value will be returned.
   102  //
   103  // When the process no longer needs the Value, call Value.Release.
   104  func (p *dbHandler) Get(key []byte, opt *ReadOptions) (*Value, error) {
   105  	ro := p.defaultReadOpt
   106  	if opt != nil {
   107  		ro = leveldb_readoptions_create_copy(opt)
   108  		defer leveldb_readoptions_destroy(ro)
   109  	}
   110  	d, err := leveldb_get(p.db, key, ro)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	return newValueHandler(d), nil
   115  }
   116  
   117  // Put writes data associated with a key to the database.
   118  //
   119  // If a nil []byte is passed in as value, it will be returned by Get as an
   120  // zero-length slice.
   121  //
   122  // The key and value byte slices may be reused safely. Put takes a copy of
   123  // them before returning.
   124  func (p *dbHandler) Put(key, value []byte, opt *WriteOptions) error {
   125  	wo := p.defaultWriteOpt
   126  	if opt != nil {
   127  		wo = leveldb_writeoptions_create_copy(opt)
   128  		defer leveldb_writeoptions_destroy(wo)
   129  	}
   130  	return leveldb_put(p.db, key, value, wo)
   131  }
   132  
   133  // Delete removes the data associated with the key from the database.
   134  //
   135  // The key byte slice may be reused safely. Delete takes a copy of
   136  // them before returning.
   137  func (p *dbHandler) Delete(key []byte, opt *WriteOptions) error {
   138  	wo := p.defaultWriteOpt
   139  	if opt != nil {
   140  		wo = leveldb_writeoptions_create_copy(opt)
   141  		defer leveldb_writeoptions_destroy(wo)
   142  	}
   143  	return leveldb_delete(p.db, key, wo)
   144  }
   145  
   146  // Write atomically writes a WriteBatch to disk.
   147  func (p *dbHandler) Write(batch *WriteBatch, opt *WriteOptions) error {
   148  	wo := p.defaultWriteOpt
   149  	if opt != nil {
   150  		wo = leveldb_writeoptions_create_copy(opt)
   151  		defer leveldb_writeoptions_destroy(wo)
   152  	}
   153  	return leveldb_write(p.db, batch.batch, wo)
   154  }
   155  
   156  // GetProperty returns the value of a database property.
   157  //
   158  // Examples of properties include "leveldb.stats", "leveldb.sstables",
   159  // and "leveldb.num-files-at-level0".
   160  //
   161  //
   162  // When the process no longer needs the Value, call Value.Release.
   163  func (p *dbHandler) GetProperty(property string) *Value {
   164  	return newValueHandler(leveldb_property_value(p.db, property))
   165  }
   166  
   167  // GetApproximateSizes returns the approximate number of bytes of file system
   168  // space used by one or more key ranges.
   169  //
   170  // The keys counted will begin at Range.Start and end on the key before
   171  // Range.Limit.
   172  func (p *dbHandler) GetApproximateSizes(keyRanges []Range) []uint64 {
   173  	rangeStartKey := make([][]byte, len(keyRanges))
   174  	rangeLimitKey := make([][]byte, len(keyRanges))
   175  	for i := 0; i < len(keyRanges); i++ {
   176  		rangeStartKey[i] = keyRanges[i].Start
   177  		rangeLimitKey[i] = keyRanges[i].Limit
   178  	}
   179  	return leveldb_approximate_sizes(p.db, rangeStartKey, rangeLimitKey)
   180  }
   181  
   182  // CompactRange runs a manual compaction on the Range of keys given. This is
   183  // not likely to be needed for typical usage.
   184  func (p *dbHandler) CompactRange(begin, end []byte) {
   185  	leveldb_compact_range(p.db, begin, end)
   186  }
   187  
   188  // GetSnapshot creates a new snapshot of the database.
   189  //
   190  // The snapshot, when used in a ReadOptions, provides a consistent view of
   191  // state of the database at the the snapshot was created.
   192  //
   193  // To prevent memory leaks and resource strain in the database, the snapshot
   194  // returned must be released with DB.ReleaseSnapshot method on the DB that
   195  // created it.
   196  //
   197  // See the LevelDB documentation for details.
   198  func (p *dbHandler) GetSnapshot() *Snapshot {
   199  	return &Snapshot{
   200  		snap: leveldb_create_snapshot(p.db),
   201  	}
   202  }
   203  
   204  // ReleaseSnapshot removes the snapshot from the database's list of snapshots,
   205  // and deallocates it.
   206  func (p *dbHandler) ReleaseSnapshot(snap *Snapshot) {
   207  	leveldb_release_snapshot(p.db, snap.snap)
   208  	*snap = Snapshot{}
   209  }
   210  
   211  // RepairDB attempts to repair a database.
   212  // If the database is unrepairable, an error is returned.
   213  func RepairDB(name string, opt *Options) error {
   214  	var opt_ *leveldb_options_t
   215  	var state optStateContainer
   216  	if opt != nil {
   217  		opt_ = leveldb_options_create_copy(&state, opt)
   218  		defer leveldb_options_destroy(opt_)
   219  	}
   220  	return leveldb_repair_db(name, opt_)
   221  }
   222  
   223  // DestroyDB removes a database entirely,
   224  // removing everything from the filesystem.
   225  func DestroyDB(name string, opt *Options) error {
   226  	var opt_ *leveldb_options_t
   227  	var state optStateContainer
   228  	if opt != nil {
   229  		opt_ = leveldb_options_create_copy(&state, opt)
   230  		defer leveldb_options_destroy(opt_)
   231  	}
   232  	return leveldb_destroy_db(name, opt_)
   233  }