memorystoragemanager.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package storage
  11. import (
  12. "bytes"
  13. "fmt"
  14. "sync"
  15. "devt.de/krotik/common/datautil"
  16. "devt.de/krotik/eliasdb/storage/file"
  17. )
  18. /*
  19. Special flags which cause the manager to return errors on specific function calls
  20. */
  21. const (
  22. AccessNotInCache = 1 // The address will not be accessible via FetchCached
  23. AccessFetchError = 2 // The address will not be accessible via Fetch
  24. AccessUpdateError = 3 // The address will not be accessible via Update
  25. AccessFreeError = 4 // The address will not be accessible via Free
  26. AccessInsertError = 5 // The address will not be accessible via Insert
  27. AccessCacheAndFetchError = 6 // The address will not be accessible via FetchCached nor Fetch
  28. AccessCacheAndFetchSeriousError = 7 // The address will not be accessible via FetchCached nor Fetch
  29. )
  30. /*
  31. MsmRetClose nil or the error which should be returned by a Close call
  32. */
  33. var MsmRetClose error
  34. /*
  35. MsmCallNumClose counter how often Close is called
  36. */
  37. var MsmCallNumClose int
  38. /*
  39. MsmRetFlush nil or the error which should be returned by a Flush call
  40. */
  41. var MsmRetFlush error
  42. /*
  43. MsmCallNumFlush counter how often Flush is called
  44. */
  45. var MsmCallNumFlush int
  46. /*
  47. MsmRetRollback nil or the error which should be returned by a Rollback call
  48. */
  49. var MsmRetRollback error
  50. /*
  51. MsmCallNumRollback counter how often Rollback is called
  52. */
  53. var MsmCallNumRollback int
  54. /*
  55. MemoryStorageManager data structure
  56. */
  57. type MemoryStorageManager struct {
  58. name string // Name of the storage manager
  59. Roots map[int]uint64 // Map of roots
  60. Data map[uint64]interface{} // Map of data
  61. mutex *sync.Mutex // Mutex to protect map operations
  62. LocCount uint64 // Counter for locations
  63. AccessMap map[uint64]int // Special map to simulate access issues
  64. }
  65. /*
  66. NewMemoryStorageManager creates a new MemoryStorageManager
  67. */
  68. func NewMemoryStorageManager(name string) *MemoryStorageManager {
  69. return &MemoryStorageManager{name, make(map[int]uint64),
  70. make(map[uint64]interface{}), &sync.Mutex{}, 1, make(map[uint64]int)}
  71. }
  72. /*
  73. Name returns the name of the StorageManager instance.
  74. */
  75. func (msm *MemoryStorageManager) Name() string {
  76. return msm.name
  77. }
  78. /*
  79. Root returns a root value.
  80. */
  81. func (msm *MemoryStorageManager) Root(root int) uint64 {
  82. msm.mutex.Lock()
  83. defer msm.mutex.Unlock()
  84. return msm.Roots[root]
  85. }
  86. /*
  87. SetRoot writes a root value.
  88. */
  89. func (msm *MemoryStorageManager) SetRoot(root int, val uint64) {
  90. msm.mutex.Lock()
  91. defer msm.mutex.Unlock()
  92. msm.Roots[root] = val
  93. }
  94. /*
  95. Insert inserts an object and return its storage location.
  96. */
  97. func (msm *MemoryStorageManager) Insert(o interface{}) (uint64, error) {
  98. msm.mutex.Lock()
  99. defer msm.mutex.Unlock()
  100. if msm.AccessMap[msm.LocCount] == AccessInsertError {
  101. return 0, file.ErrAlreadyInUse
  102. }
  103. loc := msm.LocCount
  104. msm.LocCount++
  105. msm.Data[loc] = o
  106. return loc, nil
  107. }
  108. /*
  109. Update updates a storage location.
  110. */
  111. func (msm *MemoryStorageManager) Update(loc uint64, o interface{}) error {
  112. msm.mutex.Lock()
  113. defer msm.mutex.Unlock()
  114. if msm.AccessMap[loc] == AccessUpdateError {
  115. return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
  116. }
  117. msm.Data[loc] = o
  118. return nil
  119. }
  120. /*
  121. Free frees a storage location.
  122. */
  123. func (msm *MemoryStorageManager) Free(loc uint64) error {
  124. msm.mutex.Lock()
  125. defer msm.mutex.Unlock()
  126. if msm.AccessMap[loc] == AccessFreeError {
  127. return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
  128. }
  129. delete(msm.Data, loc)
  130. return nil
  131. }
  132. /*
  133. Fetch fetches an object from a given storage location and writes it to
  134. a given data container.
  135. */
  136. func (msm *MemoryStorageManager) Fetch(loc uint64, o interface{}) error {
  137. var err error
  138. msm.mutex.Lock()
  139. defer msm.mutex.Unlock()
  140. if msm.AccessMap[loc] == AccessFetchError || msm.AccessMap[loc] == AccessCacheAndFetchError {
  141. return ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
  142. } else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
  143. return file.ErrAlreadyInUse
  144. }
  145. if obj, ok := msm.Data[loc]; ok {
  146. err = datautil.CopyObject(obj, o)
  147. } else {
  148. err = ErrSlotNotFound.fireError(msm, fmt.Sprint("Location:", loc))
  149. }
  150. return err
  151. }
  152. /*
  153. FetchCached fetches an object from a cache and returns its reference.
  154. Returns a storage.ErrNotInCache error if the entry is not in the cache.
  155. */
  156. func (msm *MemoryStorageManager) FetchCached(loc uint64) (interface{}, error) {
  157. msm.mutex.Lock()
  158. defer msm.mutex.Unlock()
  159. if msm.AccessMap[loc] == AccessNotInCache || msm.AccessMap[loc] == AccessCacheAndFetchError {
  160. return nil, ErrNotInCache
  161. } else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
  162. return nil, file.ErrAlreadyInUse
  163. }
  164. return msm.Data[loc], nil
  165. }
  166. /*
  167. Flush writes all pending changes to disk.
  168. */
  169. func (msm *MemoryStorageManager) Flush() error {
  170. MsmCallNumFlush++
  171. return MsmRetFlush
  172. }
  173. /*
  174. Rollback cancels all pending changes which have not yet been written to disk.
  175. */
  176. func (msm *MemoryStorageManager) Rollback() error {
  177. MsmCallNumRollback++
  178. return MsmRetRollback
  179. }
  180. /*
  181. Close the StorageManager and write all pending changes to disk.
  182. */
  183. func (msm *MemoryStorageManager) Close() error {
  184. MsmCallNumClose++
  185. return MsmRetClose
  186. }
  187. /*
  188. Show a string representation of the storage manager.
  189. */
  190. func (msm *MemoryStorageManager) String() string {
  191. buf := new(bytes.Buffer)
  192. buf.WriteString(fmt.Sprintf("MemoryStorageManager %v\n", msm.name))
  193. for k, v := range msm.Data {
  194. buf.WriteString(fmt.Sprintf("%v - %v\n", k, v))
  195. }
  196. return buf.String()
  197. }