1// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2// All rights reserved. 3// 4// Use of this source code is governed by a BSD-style license that can be 5// found in the LICENSE file. 6 7// Package storage provides storage abstraction for LevelDB. 8package storage 9 10import ( 11 "errors" 12 "fmt" 13 "io" 14) 15 16// FileType represent a file type. 17type FileType int 18 19// File types. 20const ( 21 TypeManifest FileType = 1 << iota 22 TypeJournal 23 TypeTable 24 TypeTemp 25 26 TypeAll = TypeManifest | TypeJournal | TypeTable | TypeTemp 27) 28 29func (t FileType) String() string { 30 switch t { 31 case TypeManifest: 32 return "manifest" 33 case TypeJournal: 34 return "journal" 35 case TypeTable: 36 return "table" 37 case TypeTemp: 38 return "temp" 39 } 40 return fmt.Sprintf("<unknown:%d>", t) 41} 42 43// Common error. 44var ( 45 ErrInvalidFile = errors.New("leveldb/storage: invalid file for argument") 46 ErrLocked = errors.New("leveldb/storage: already locked") 47 ErrClosed = errors.New("leveldb/storage: closed") 48) 49 50// ErrCorrupted is the type that wraps errors that indicate corruption of 51// a file. Package storage has its own type instead of using 52// errors.ErrCorrupted to prevent circular import. 53type ErrCorrupted struct { 54 Fd FileDesc 55 Err error 56} 57 58func (e *ErrCorrupted) Error() string { 59 if !e.Fd.Zero() { 60 return fmt.Sprintf("%v [file=%v]", e.Err, e.Fd) 61 } 62 return e.Err.Error() 63} 64 65// Syncer is the interface that wraps basic Sync method. 66type Syncer interface { 67 // Sync commits the current contents of the file to stable storage. 68 Sync() error 69} 70 71// Reader is the interface that groups the basic Read, Seek, ReadAt and Close 72// methods. 73type Reader interface { 74 io.ReadSeeker 75 io.ReaderAt 76 io.Closer 77} 78 79// Writer is the interface that groups the basic Write, Sync and Close 80// methods. 81type Writer interface { 82 io.WriteCloser 83 Syncer 84} 85 86// Locker is the interface that wraps Unlock method. 87type Locker interface { 88 Unlock() 89} 90 91// FileDesc is a 'file descriptor'. 92type FileDesc struct { 93 Type FileType 94 Num int64 95} 96 97func (fd FileDesc) String() string { 98 switch fd.Type { 99 case TypeManifest: 100 return fmt.Sprintf("MANIFEST-%06d", fd.Num) 101 case TypeJournal: 102 return fmt.Sprintf("%06d.log", fd.Num) 103 case TypeTable: 104 return fmt.Sprintf("%06d.ldb", fd.Num) 105 case TypeTemp: 106 return fmt.Sprintf("%06d.tmp", fd.Num) 107 default: 108 return fmt.Sprintf("%#x-%d", fd.Type, fd.Num) 109 } 110} 111 112// Zero returns true if fd == (FileDesc{}). 113func (fd FileDesc) Zero() bool { 114 return fd == (FileDesc{}) 115} 116 117// FileDescOk returns true if fd is a valid 'file descriptor'. 118func FileDescOk(fd FileDesc) bool { 119 switch fd.Type { 120 case TypeManifest: 121 case TypeJournal: 122 case TypeTable: 123 case TypeTemp: 124 default: 125 return false 126 } 127 return fd.Num >= 0 128} 129 130// Storage is the storage. A storage instance must be safe for concurrent use. 131type Storage interface { 132 // Lock locks the storage. Any subsequent attempt to call Lock will fail 133 // until the last lock released. 134 // Caller should call Unlock method after use. 135 Lock() (Locker, error) 136 137 // Log logs a string. This is used for logging. 138 // An implementation may write to a file, stdout or simply do nothing. 139 Log(str string) 140 141 // SetMeta store 'file descriptor' that can later be acquired using GetMeta 142 // method. The 'file descriptor' should point to a valid file. 143 // SetMeta should be implemented in such way that changes should happen 144 // atomically. 145 SetMeta(fd FileDesc) error 146 147 // GetMeta returns 'file descriptor' stored in meta. The 'file descriptor' 148 // can be updated using SetMeta method. 149 // Returns os.ErrNotExist if meta doesn't store any 'file descriptor', or 150 // 'file descriptor' point to nonexistent file. 151 GetMeta() (FileDesc, error) 152 153 // List returns file descriptors that match the given file types. 154 // The file types may be OR'ed together. 155 List(ft FileType) ([]FileDesc, error) 156 157 // Open opens file with the given 'file descriptor' read-only. 158 // Returns os.ErrNotExist error if the file does not exist. 159 // Returns ErrClosed if the underlying storage is closed. 160 Open(fd FileDesc) (Reader, error) 161 162 // Create creates file with the given 'file descriptor', truncate if already 163 // exist and opens write-only. 164 // Returns ErrClosed if the underlying storage is closed. 165 Create(fd FileDesc) (Writer, error) 166 167 // Remove removes file with the given 'file descriptor'. 168 // Returns ErrClosed if the underlying storage is closed. 169 Remove(fd FileDesc) error 170 171 // Rename renames file from oldfd to newfd. 172 // Returns ErrClosed if the underlying storage is closed. 173 Rename(oldfd, newfd FileDesc) error 174 175 // Close closes the storage. 176 // It is valid to call Close multiple times. Other methods should not be 177 // called after the storage has been closed. 178 Close() error 179} 180