storage.go 4.7 KB

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