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 isCorrupted(err error) bool { 59 switch err.(type) { 60 case *ErrCorrupted: 61 return true 62 } 63 return false 64} 65 66func (e *ErrCorrupted) Error() string { 67 if !e.Fd.Zero() { 68 return fmt.Sprintf("%v [file=%v]", e.Err, e.Fd) 69 } 70 return e.Err.Error() 71} 72 73// Syncer is the interface that wraps basic Sync method. 74type Syncer interface { 75 // Sync commits the current contents of the file to stable storage. 76 Sync() error 77} 78 79// Reader is the interface that groups the basic Read, Seek, ReadAt and Close 80// methods. 81type Reader interface { 82 io.ReadSeeker 83 io.ReaderAt 84 io.Closer 85} 86 87// Writer is the interface that groups the basic Write, Sync and Close 88// methods. 89type Writer interface { 90 io.WriteCloser 91 Syncer 92} 93 94// Locker is the interface that wraps Unlock method. 95type Locker interface { 96 Unlock() 97} 98 99// FileDesc is a 'file descriptor'. 100type FileDesc struct { 101 Type FileType 102 Num int64 103} 104 105func (fd FileDesc) String() string { 106 switch fd.Type { 107 case TypeManifest: 108 return fmt.Sprintf("MANIFEST-%06d", fd.Num) 109 case TypeJournal: 110 return fmt.Sprintf("%06d.log", fd.Num) 111 case TypeTable: 112 return fmt.Sprintf("%06d.ldb", fd.Num) 113 case TypeTemp: 114 return fmt.Sprintf("%06d.tmp", fd.Num) 115 default: 116 return fmt.Sprintf("%#x-%d", fd.Type, fd.Num) 117 } 118} 119 120// Zero returns true if fd == (FileDesc{}). 121func (fd FileDesc) Zero() bool { 122 return fd == (FileDesc{}) 123} 124 125// FileDescOk returns true if fd is a valid 'file descriptor'. 126func FileDescOk(fd FileDesc) bool { 127 switch fd.Type { 128 case TypeManifest: 129 case TypeJournal: 130 case TypeTable: 131 case TypeTemp: 132 default: 133 return false 134 } 135 return fd.Num >= 0 136} 137 138// Storage is the storage. A storage instance must be safe for concurrent use. 139type Storage interface { 140 // Lock locks the storage. Any subsequent attempt to call Lock will fail 141 // until the last lock released. 142 // Caller should call Unlock method after use. 143 Lock() (Locker, error) 144 145 // Log logs a string. This is used for logging. 146 // An implementation may write to a file, stdout or simply do nothing. 147 Log(str string) 148 149 // SetMeta store 'file descriptor' that can later be acquired using GetMeta 150 // method. The 'file descriptor' should point to a valid file. 151 // SetMeta should be implemented in such way that changes should happen 152 // atomically. 153 SetMeta(fd FileDesc) error 154 155 // GetMeta returns 'file descriptor' stored in meta. The 'file descriptor' 156 // can be updated using SetMeta method. 157 // Returns os.ErrNotExist if meta doesn't store any 'file descriptor', or 158 // 'file descriptor' point to nonexistent file. 159 GetMeta() (FileDesc, error) 160 161 // List returns file descriptors that match the given file types. 162 // The file types may be OR'ed together. 163 List(ft FileType) ([]FileDesc, error) 164 165 // Open opens file with the given 'file descriptor' read-only. 166 // Returns os.ErrNotExist error if the file does not exist. 167 // Returns ErrClosed if the underlying storage is closed. 168 Open(fd FileDesc) (Reader, error) 169 170 // Create creates file with the given 'file descriptor', truncate if already 171 // exist and opens write-only. 172 // Returns ErrClosed if the underlying storage is closed. 173 Create(fd FileDesc) (Writer, error) 174 175 // Remove removes file with the given 'file descriptor'. 176 // Returns ErrClosed if the underlying storage is closed. 177 Remove(fd FileDesc) error 178 179 // Rename renames file from oldfd to newfd. 180 // Returns ErrClosed if the underlying storage is closed. 181 Rename(oldfd, newfd FileDesc) error 182 183 // Close closes the storage. 184 // It is valid to call Close multiple times. Other methods should not be 185 // called after the storage has been closed. 186 Close() error 187} 188