PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/leveldb/iterator/merged_iter.go

https://bitbucket.org/cloudwallet/goleveldb
Go | 304 lines | 259 code | 30 blank | 15 comment | 93 complexity | 2c9156225a3cb7ad4b7c29612030424a MD5 | raw file
Possible License(s): BSD-3-Clause
  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 iterator
  7. import (
  8. "bitbucket.org/cloudwallet/goleveldb/leveldb/comparer"
  9. "bitbucket.org/cloudwallet/goleveldb/leveldb/errors"
  10. "bitbucket.org/cloudwallet/goleveldb/leveldb/util"
  11. )
  12. type dir int
  13. const (
  14. dirReleased dir = iota - 1
  15. dirSOI
  16. dirEOI
  17. dirBackward
  18. dirForward
  19. )
  20. type mergedIterator struct {
  21. cmp comparer.Comparer
  22. iters []Iterator
  23. strict bool
  24. keys [][]byte
  25. index int
  26. dir dir
  27. err error
  28. errf func(err error)
  29. releaser util.Releaser
  30. }
  31. func assertKey(key []byte) []byte {
  32. if key == nil {
  33. panic("leveldb/iterator: nil key")
  34. }
  35. return key
  36. }
  37. func (i *mergedIterator) iterErr(iter Iterator) bool {
  38. if err := iter.Error(); err != nil {
  39. if i.errf != nil {
  40. i.errf(err)
  41. }
  42. if i.strict || !errors.IsCorrupted(err) {
  43. i.err = err
  44. return true
  45. }
  46. }
  47. return false
  48. }
  49. func (i *mergedIterator) Valid() bool {
  50. return i.err == nil && i.dir > dirEOI
  51. }
  52. func (i *mergedIterator) First() bool {
  53. if i.err != nil {
  54. return false
  55. } else if i.dir == dirReleased {
  56. i.err = ErrIterReleased
  57. return false
  58. }
  59. for x, iter := range i.iters {
  60. switch {
  61. case iter.First():
  62. i.keys[x] = assertKey(iter.Key())
  63. case i.iterErr(iter):
  64. return false
  65. default:
  66. i.keys[x] = nil
  67. }
  68. }
  69. i.dir = dirSOI
  70. return i.next()
  71. }
  72. func (i *mergedIterator) Last() bool {
  73. if i.err != nil {
  74. return false
  75. } else if i.dir == dirReleased {
  76. i.err = ErrIterReleased
  77. return false
  78. }
  79. for x, iter := range i.iters {
  80. switch {
  81. case iter.Last():
  82. i.keys[x] = assertKey(iter.Key())
  83. case i.iterErr(iter):
  84. return false
  85. default:
  86. i.keys[x] = nil
  87. }
  88. }
  89. i.dir = dirEOI
  90. return i.prev()
  91. }
  92. func (i *mergedIterator) Seek(key []byte) bool {
  93. if i.err != nil {
  94. return false
  95. } else if i.dir == dirReleased {
  96. i.err = ErrIterReleased
  97. return false
  98. }
  99. for x, iter := range i.iters {
  100. switch {
  101. case iter.Seek(key):
  102. i.keys[x] = assertKey(iter.Key())
  103. case i.iterErr(iter):
  104. return false
  105. default:
  106. i.keys[x] = nil
  107. }
  108. }
  109. i.dir = dirSOI
  110. return i.next()
  111. }
  112. func (i *mergedIterator) next() bool {
  113. var key []byte
  114. if i.dir == dirForward {
  115. key = i.keys[i.index]
  116. }
  117. for x, tkey := range i.keys {
  118. if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) < 0) {
  119. key = tkey
  120. i.index = x
  121. }
  122. }
  123. if key == nil {
  124. i.dir = dirEOI
  125. return false
  126. }
  127. i.dir = dirForward
  128. return true
  129. }
  130. func (i *mergedIterator) Next() bool {
  131. if i.dir == dirEOI || i.err != nil {
  132. return false
  133. } else if i.dir == dirReleased {
  134. i.err = ErrIterReleased
  135. return false
  136. }
  137. switch i.dir {
  138. case dirSOI:
  139. return i.First()
  140. case dirBackward:
  141. key := append([]byte{}, i.keys[i.index]...)
  142. if !i.Seek(key) {
  143. return false
  144. }
  145. return i.Next()
  146. }
  147. x := i.index
  148. iter := i.iters[x]
  149. switch {
  150. case iter.Next():
  151. i.keys[x] = assertKey(iter.Key())
  152. case i.iterErr(iter):
  153. return false
  154. default:
  155. i.keys[x] = nil
  156. }
  157. return i.next()
  158. }
  159. func (i *mergedIterator) prev() bool {
  160. var key []byte
  161. if i.dir == dirBackward {
  162. key = i.keys[i.index]
  163. }
  164. for x, tkey := range i.keys {
  165. if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) > 0) {
  166. key = tkey
  167. i.index = x
  168. }
  169. }
  170. if key == nil {
  171. i.dir = dirSOI
  172. return false
  173. }
  174. i.dir = dirBackward
  175. return true
  176. }
  177. func (i *mergedIterator) Prev() bool {
  178. if i.dir == dirSOI || i.err != nil {
  179. return false
  180. } else if i.dir == dirReleased {
  181. i.err = ErrIterReleased
  182. return false
  183. }
  184. switch i.dir {
  185. case dirEOI:
  186. return i.Last()
  187. case dirForward:
  188. key := append([]byte{}, i.keys[i.index]...)
  189. for x, iter := range i.iters {
  190. if x == i.index {
  191. continue
  192. }
  193. seek := iter.Seek(key)
  194. switch {
  195. case seek && iter.Prev(), !seek && iter.Last():
  196. i.keys[x] = assertKey(iter.Key())
  197. case i.iterErr(iter):
  198. return false
  199. default:
  200. i.keys[x] = nil
  201. }
  202. }
  203. }
  204. x := i.index
  205. iter := i.iters[x]
  206. switch {
  207. case iter.Prev():
  208. i.keys[x] = assertKey(iter.Key())
  209. case i.iterErr(iter):
  210. return false
  211. default:
  212. i.keys[x] = nil
  213. }
  214. return i.prev()
  215. }
  216. func (i *mergedIterator) Key() []byte {
  217. if i.err != nil || i.dir <= dirEOI {
  218. return nil
  219. }
  220. return i.keys[i.index]
  221. }
  222. func (i *mergedIterator) Value() []byte {
  223. if i.err != nil || i.dir <= dirEOI {
  224. return nil
  225. }
  226. return i.iters[i.index].Value()
  227. }
  228. func (i *mergedIterator) Release() {
  229. if i.dir != dirReleased {
  230. i.dir = dirReleased
  231. for _, iter := range i.iters {
  232. iter.Release()
  233. }
  234. i.iters = nil
  235. i.keys = nil
  236. if i.releaser != nil {
  237. i.releaser.Release()
  238. i.releaser = nil
  239. }
  240. }
  241. }
  242. func (i *mergedIterator) SetReleaser(releaser util.Releaser) {
  243. if i.dir == dirReleased {
  244. panic(util.ErrReleased)
  245. }
  246. if i.releaser != nil && releaser != nil {
  247. panic(util.ErrHasReleaser)
  248. }
  249. i.releaser = releaser
  250. }
  251. func (i *mergedIterator) Error() error {
  252. return i.err
  253. }
  254. func (i *mergedIterator) SetErrorCallback(f func(err error)) {
  255. i.errf = f
  256. }
  257. // NewMergedIterator returns an iterator that merges its input. Walking the
  258. // resultant iterator will return all key/value pairs of all input iterators
  259. // in strictly increasing key order, as defined by cmp.
  260. // The input's key ranges may overlap, but there are assumed to be no duplicate
  261. // keys: if iters[i] contains a key k then iters[j] will not contain that key k.
  262. // None of the iters may be nil.
  263. //
  264. // If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true)
  265. // won't be ignored and will halt 'merged iterator', otherwise the iterator will
  266. // continue to the next 'input iterator'.
  267. func NewMergedIterator(iters []Iterator, cmp comparer.Comparer, strict bool) Iterator {
  268. return &mergedIterator{
  269. iters: iters,
  270. cmp: cmp,
  271. strict: strict,
  272. keys: make([][]byte, len(iters)),
  273. }
  274. }