mirror of
				https://github.com/taigrr/bitcask
				synced 2025-01-18 04:03:17 -08:00 
			
		
		
		
	Add docs for bitcask
This commit is contained in:
		
							parent
							
								
									27eb922ba2
								
							
						
					
					
						commit
						2400dd86d5
					
				
							
								
								
									
										51
									
								
								bitcask.go
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								bitcask.go
									
									
									
									
									
								
							@ -16,13 +16,29 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 | 
						// ErrKeyNotFound is the error returned when a key is not found
 | 
				
			||||||
	ErrKeyNotFound = errors.New("error: key not found")
 | 
						ErrKeyNotFound = errors.New("error: key not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrKeyTooLarge is the error returned for a key that exceeds the
 | 
				
			||||||
 | 
						// maximum allowed key size (configured with WithMaxKeySize).
 | 
				
			||||||
	ErrKeyTooLarge = errors.New("error: key too large")
 | 
						ErrKeyTooLarge = errors.New("error: key too large")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrValueTooLarge is the error returned for a value that exceeds the
 | 
				
			||||||
 | 
						// maximum allowed value size (configured with WithMaxValueSize).
 | 
				
			||||||
	ErrValueTooLarge = errors.New("error: value too large")
 | 
						ErrValueTooLarge = errors.New("error: value too large")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrChecksumFailed is the error returned if a key/valie retrieved does
 | 
				
			||||||
 | 
						// not match its CRC checksum
 | 
				
			||||||
	ErrChecksumFailed = errors.New("error: checksum failed")
 | 
						ErrChecksumFailed = errors.New("error: checksum failed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ErrDatabaseLocked is the error returned if the database is locked
 | 
				
			||||||
 | 
						// (typically opened by another process)
 | 
				
			||||||
	ErrDatabaseLocked = errors.New("error: database locked")
 | 
						ErrDatabaseLocked = errors.New("error: database locked")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Bitcask is a struct that represents a on-disk LSM and WAL data structure
 | 
				
			||||||
 | 
					// and in-memory hash of key/value pairs as per the Bitcask paper and seen
 | 
				
			||||||
 | 
					// in the Riak database.
 | 
				
			||||||
type Bitcask struct {
 | 
					type Bitcask struct {
 | 
				
			||||||
	*flock.Flock
 | 
						*flock.Flock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,10 +48,11 @@ type Bitcask struct {
 | 
				
			|||||||
	keydir    *internal.Keydir
 | 
						keydir    *internal.Keydir
 | 
				
			||||||
	datafiles []*internal.Datafile
 | 
						datafiles []*internal.Datafile
 | 
				
			||||||
	trie      *trie.Trie
 | 
						trie      *trie.Trie
 | 
				
			||||||
 | 
					 | 
				
			||||||
	maxDatafileSize int64
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close closes the database and removes the lock. It is important to call
 | 
				
			||||||
 | 
					// Close() as this is the only wat to cleanup the lock held by the open
 | 
				
			||||||
 | 
					// database.
 | 
				
			||||||
func (b *Bitcask) Close() error {
 | 
					func (b *Bitcask) Close() error {
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		b.Flock.Unlock()
 | 
							b.Flock.Unlock()
 | 
				
			||||||
@ -48,10 +65,13 @@ func (b *Bitcask) Close() error {
 | 
				
			|||||||
	return b.curr.Close()
 | 
						return b.curr.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sync flushes all buffers to disk ensuring all data is written
 | 
				
			||||||
func (b *Bitcask) Sync() error {
 | 
					func (b *Bitcask) Sync() error {
 | 
				
			||||||
	return b.curr.Sync()
 | 
						return b.curr.Sync()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get retrieves the value of the given key. If the key is not found or an/I/O
 | 
				
			||||||
 | 
					// error occurs a null byte slice is returend along with the error.
 | 
				
			||||||
func (b *Bitcask) Get(key string) ([]byte, error) {
 | 
					func (b *Bitcask) Get(key string) ([]byte, error) {
 | 
				
			||||||
	var df *internal.Datafile
 | 
						var df *internal.Datafile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,11 +99,13 @@ func (b *Bitcask) Get(key string) ([]byte, error) {
 | 
				
			|||||||
	return e.Value, nil
 | 
						return e.Value, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Has returns true if the key exists in the database, false otherwise.
 | 
				
			||||||
func (b *Bitcask) Has(key string) bool {
 | 
					func (b *Bitcask) Has(key string) bool {
 | 
				
			||||||
	_, ok := b.keydir.Get(key)
 | 
						_, ok := b.keydir.Get(key)
 | 
				
			||||||
	return ok
 | 
						return ok
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Put stores the key and value in the database.
 | 
				
			||||||
func (b *Bitcask) Put(key string, value []byte) error {
 | 
					func (b *Bitcask) Put(key string, value []byte) error {
 | 
				
			||||||
	if len(key) > b.config.maxKeySize {
 | 
						if len(key) > b.config.maxKeySize {
 | 
				
			||||||
		return ErrKeyTooLarge
 | 
							return ErrKeyTooLarge
 | 
				
			||||||
@ -103,6 +125,8 @@ func (b *Bitcask) Put(key string, value []byte) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Delete deletes the named key. If the key doesn't exist or an I/O error
 | 
				
			||||||
 | 
					// occurs the error is returned.
 | 
				
			||||||
func (b *Bitcask) Delete(key string) error {
 | 
					func (b *Bitcask) Delete(key string) error {
 | 
				
			||||||
	_, err := b.put(key, []byte{})
 | 
						_, err := b.put(key, []byte{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -115,6 +139,9 @@ func (b *Bitcask) Delete(key string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Scan performa a prefix scan of keys matching the given prefix and calling
 | 
				
			||||||
 | 
					// the function `f` with the keys found. If the function returns an error
 | 
				
			||||||
 | 
					// no further keys are processed and the first error returned.
 | 
				
			||||||
func (b *Bitcask) Scan(prefix string, f func(key string) error) error {
 | 
					func (b *Bitcask) Scan(prefix string, f func(key string) error) error {
 | 
				
			||||||
	keys := b.trie.PrefixSearch(prefix)
 | 
						keys := b.trie.PrefixSearch(prefix)
 | 
				
			||||||
	for _, key := range keys {
 | 
						for _, key := range keys {
 | 
				
			||||||
@ -125,14 +152,19 @@ func (b *Bitcask) Scan(prefix string, f func(key string) error) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Len returns the total number of keys in the database
 | 
				
			||||||
func (b *Bitcask) Len() int {
 | 
					func (b *Bitcask) Len() int {
 | 
				
			||||||
	return b.keydir.Len()
 | 
						return b.keydir.Len()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Keys returns all keys in the database as a channel of string(s)
 | 
				
			||||||
func (b *Bitcask) Keys() chan string {
 | 
					func (b *Bitcask) Keys() chan string {
 | 
				
			||||||
	return b.keydir.Keys()
 | 
						return b.keydir.Keys()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Fold iterates over all keys in the database calling the function `f` for
 | 
				
			||||||
 | 
					// each key. If the function returns an error, no further keys are processed
 | 
				
			||||||
 | 
					// and the error returned.
 | 
				
			||||||
func (b *Bitcask) Fold(f func(key string) error) error {
 | 
					func (b *Bitcask) Fold(f func(key string) error) error {
 | 
				
			||||||
	for key := range b.keydir.Keys() {
 | 
						for key := range b.keydir.Keys() {
 | 
				
			||||||
		if err := f(key); err != nil {
 | 
							if err := f(key); err != nil {
 | 
				
			||||||
@ -148,7 +180,7 @@ func (b *Bitcask) put(key string, value []byte) (int64, error) {
 | 
				
			|||||||
		return -1, err
 | 
							return -1, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if size >= b.maxDatafileSize {
 | 
						if size >= int64(b.config.maxDatafileSize) {
 | 
				
			||||||
		err := b.curr.Close()
 | 
							err := b.curr.Close()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return -1, err
 | 
								return -1, err
 | 
				
			||||||
@ -173,11 +205,9 @@ func (b *Bitcask) put(key string, value []byte) (int64, error) {
 | 
				
			|||||||
	return b.curr.Write(e)
 | 
						return b.curr.Write(e)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *Bitcask) setMaxDatafileSize(size int64) error {
 | 
					// Merge merges all datafiles in the database creating hint files for faster
 | 
				
			||||||
	b.maxDatafileSize = size
 | 
					// startup. Old keys are squashed and deleted keys removes. Call this function
 | 
				
			||||||
	return nil
 | 
					// periodically to reclaim disk space.
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func Merge(path string, force bool) error {
 | 
					func Merge(path string, force bool) error {
 | 
				
			||||||
	fns, err := internal.GetDatafiles(path)
 | 
						fns, err := internal.GetDatafiles(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -284,6 +314,9 @@ func Merge(path string, force bool) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Open opens the database at the given path with optional options.
 | 
				
			||||||
 | 
					// Options can be provided with the `WithXXX` functions that provide
 | 
				
			||||||
 | 
					// configuration options as functions.
 | 
				
			||||||
func Open(path string, options ...Option) (*Bitcask, error) {
 | 
					func Open(path string, options ...Option) (*Bitcask, error) {
 | 
				
			||||||
	if err := os.MkdirAll(path, 0755); err != nil {
 | 
						if err := os.MkdirAll(path, 0755); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -373,8 +406,6 @@ func Open(path string, options ...Option) (*Bitcask, error) {
 | 
				
			|||||||
		keydir:    keydir,
 | 
							keydir:    keydir,
 | 
				
			||||||
		datafiles: datafiles,
 | 
							datafiles: datafiles,
 | 
				
			||||||
		trie:      trie,
 | 
							trie:      trie,
 | 
				
			||||||
 | 
					 | 
				
			||||||
		maxDatafileSize: DefaultMaxDatafileSize,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, opt := range options {
 | 
						for _, opt := range options {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user