memorystoragemanager.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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 - Must start > 0
  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. // LocCount must start > 0 - so they can be stored in a Root. Roots with
  70. // the value 0 are considered empty. See also graph.getHTree which will
  71. // keep creating new HTrees if a Root is 0.
  72. return &MemoryStorageManager{name, make(map[int]uint64),
  73. make(map[uint64]interface{}), &sync.Mutex{}, 1, make(map[uint64]int)}
  74. }
  75. /*
  76. Name returns the name of the StorageManager instance.
  77. */
  78. func (msm *MemoryStorageManager) Name() string {
  79. return msm.name
  80. }
  81. /*
  82. Root returns a root value. Default (empty) value is 0.
  83. */
  84. func (msm *MemoryStorageManager) Root(root int) uint64 {
  85. msm.mutex.Lock()
  86. defer msm.mutex.Unlock()
  87. return msm.Roots[root]
  88. }
  89. /*
  90. SetRoot writes a root value.
  91. */
  92. func (msm *MemoryStorageManager) SetRoot(root int, val uint64) {
  93. msm.mutex.Lock()
  94. defer msm.mutex.Unlock()
  95. msm.Roots[root] = val
  96. }
  97. /*
  98. Insert inserts an object and return its storage location.
  99. */
  100. func (msm *MemoryStorageManager) Insert(o interface{}) (uint64, error) {
  101. msm.mutex.Lock()
  102. defer msm.mutex.Unlock()
  103. if msm.AccessMap[msm.LocCount] == AccessInsertError {
  104. return 0, file.NewStorageFileError(file.ErrAlreadyInUse, "", "<memory>")
  105. }
  106. loc := msm.LocCount
  107. msm.LocCount++
  108. msm.Data[loc] = o
  109. return loc, nil
  110. }
  111. /*
  112. Update updates a storage location.
  113. */
  114. func (msm *MemoryStorageManager) Update(loc uint64, o interface{}) error {
  115. msm.mutex.Lock()
  116. defer msm.mutex.Unlock()
  117. if msm.AccessMap[loc] == AccessUpdateError {
  118. return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
  119. }
  120. msm.Data[loc] = o
  121. return nil
  122. }
  123. /*
  124. Free frees a storage location.
  125. */
  126. func (msm *MemoryStorageManager) Free(loc uint64) error {
  127. msm.mutex.Lock()
  128. defer msm.mutex.Unlock()
  129. if msm.AccessMap[loc] == AccessFreeError {
  130. return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
  131. }
  132. delete(msm.Data, loc)
  133. return nil
  134. }
  135. /*
  136. Fetch fetches an object from a given storage location and writes it to
  137. a given data container.
  138. */
  139. func (msm *MemoryStorageManager) Fetch(loc uint64, o interface{}) error {
  140. var err error
  141. msm.mutex.Lock()
  142. defer msm.mutex.Unlock()
  143. if msm.AccessMap[loc] == AccessFetchError || msm.AccessMap[loc] == AccessCacheAndFetchError {
  144. return NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
  145. } else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
  146. return file.NewStorageFileError(file.ErrAlreadyInUse, "", "<memory>")
  147. }
  148. if obj, ok := msm.Data[loc]; ok {
  149. err = datautil.CopyObject(obj, o)
  150. } else {
  151. err = NewStorageManagerError(ErrSlotNotFound, fmt.Sprint("Location:", loc), msm.Name())
  152. }
  153. return err
  154. }
  155. /*
  156. FetchCached fetches an object from a cache and returns its reference.
  157. Returns a storage.ErrNotInCache error if the entry is not in the cache.
  158. */
  159. func (msm *MemoryStorageManager) FetchCached(loc uint64) (interface{}, error) {
  160. msm.mutex.Lock()
  161. defer msm.mutex.Unlock()
  162. if msm.AccessMap[loc] == AccessNotInCache || msm.AccessMap[loc] == AccessCacheAndFetchError {
  163. return nil, NewStorageManagerError(ErrNotInCache, "", msm.Name())
  164. } else if msm.AccessMap[loc] == AccessCacheAndFetchSeriousError {
  165. return nil, file.NewStorageFileError(file.ErrAlreadyInUse, "", "<memory>")
  166. }
  167. return msm.Data[loc], nil
  168. }
  169. /*
  170. Flush writes all pending changes to disk.
  171. */
  172. func (msm *MemoryStorageManager) Flush() error {
  173. MsmCallNumFlush++
  174. return MsmRetFlush
  175. }
  176. /*
  177. Rollback cancels all pending changes which have not yet been written to disk.
  178. */
  179. func (msm *MemoryStorageManager) Rollback() error {
  180. MsmCallNumRollback++
  181. return MsmRetRollback
  182. }
  183. /*
  184. Close the StorageManager and write all pending changes to disk.
  185. */
  186. func (msm *MemoryStorageManager) Close() error {
  187. MsmCallNumClose++
  188. return MsmRetClose
  189. }
  190. /*
  191. Show a string representation of the storage manager.
  192. */
  193. func (msm *MemoryStorageManager) String() string {
  194. buf := new(bytes.Buffer)
  195. buf.WriteString(fmt.Sprintf("MemoryStorageManager %v\n", msm.name))
  196. for k, v := range msm.Data {
  197. buf.WriteString(fmt.Sprintf("%v - %v\n", k, v))
  198. }
  199. return buf.String()
  200. }