You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
12 KiB

  1. package redis3
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "github.com/chrislusf/seaweedfs/weed/util/skiplist"
  7. "github.com/go-redis/redis/v8"
  8. )
  9. type ItemList struct {
  10. skipList *skiplist.SkipList
  11. batchSize int
  12. client redis.UniversalClient
  13. prefix string
  14. }
  15. func newItemList(client redis.UniversalClient, prefix string, store skiplist.ListStore, batchSize int) *ItemList {
  16. return &ItemList{
  17. skipList: skiplist.New(store),
  18. batchSize: batchSize,
  19. client: client,
  20. prefix: prefix,
  21. }
  22. }
  23. /*
  24. Be reluctant to create new nodes. Try to fit into either previous node or next node.
  25. Prefer to add to previous node.
  26. There are multiple cases after finding the name for greater or equal node
  27. 1. found and node.Key == name
  28. The node contains a batch with leading key the same as the name
  29. nothing to do
  30. 2. no such node found or node.Key > name
  31. if no such node found
  32. prevNode = list.LargestNode
  33. // case 2.1
  34. if previousNode contains name
  35. nothing to do
  36. // prefer to add to previous node
  37. if prevNode != nil {
  38. // case 2.2
  39. if prevNode has capacity
  40. prevNode.add name, and save
  41. return
  42. // case 2.3
  43. split prevNode by name
  44. }
  45. // case 2.4
  46. // merge into next node. Avoid too many nodes if adding data in reverse order.
  47. if nextNode is not nil and nextNode has capacity
  48. delete nextNode.Key
  49. nextNode.Key = name
  50. nextNode.batch.add name
  51. insert nodeNode.Key
  52. return
  53. // case 2.5
  54. if prevNode is nil
  55. insert new node with key = name, value = batch{name}
  56. return
  57. */
  58. func (nl *ItemList) WriteName(name string) error {
  59. lookupKey := []byte(name)
  60. prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
  61. if err != nil {
  62. return err
  63. }
  64. // case 1: the name already exists as one leading key in the batch
  65. if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
  66. return nil
  67. }
  68. if !found {
  69. prevNode, err = nl.skipList.GetLargestNode()
  70. if err != nil {
  71. return err
  72. }
  73. }
  74. if nextNode != nil && prevNode == nil {
  75. prevNode, err = nl.skipList.LoadElement(nextNode.Prev)
  76. if err != nil {
  77. return err
  78. }
  79. }
  80. if prevNode != nil {
  81. // case 2.1
  82. if nl.NodeContainsItem(prevNode.Reference(), name) {
  83. return nil
  84. }
  85. // case 2.2
  86. nodeSize := nl.NodeSize(prevNode.Reference())
  87. if nodeSize < nl.batchSize {
  88. return nl.NodeAddMember(prevNode.Reference(), name)
  89. }
  90. // case 2.3
  91. x := nl.NodeInnerPosition(prevNode.Reference(), name)
  92. y := nodeSize - x
  93. addToX := x <= y
  94. // add to a new node
  95. if x == 0 || y == 0 {
  96. if err := nl.ItemAdd(lookupKey, 0, name); err != nil {
  97. return err
  98. }
  99. return nil
  100. }
  101. if addToX {
  102. // collect names before name, add them to X
  103. namesToX, err := nl.NodeRangeBeforeExclusive(prevNode.Reference(), name)
  104. if err != nil {
  105. return nil
  106. }
  107. // delete skiplist reference to old node
  108. if _, err := nl.skipList.DeleteByKey(prevNode.Key); err != nil {
  109. return err
  110. }
  111. // add namesToY and name to a new X
  112. namesToX = append(namesToX, name)
  113. if err := nl.ItemAdd([]byte(namesToX[0]), 0, namesToX...); err != nil {
  114. return nil
  115. }
  116. // remove names less than name from current Y
  117. if err := nl.NodeDeleteBeforeExclusive(prevNode.Reference(), name); err != nil {
  118. return nil
  119. }
  120. // point skip list to current Y
  121. if err := nl.ItemAdd(lookupKey, prevNode.Id); err != nil {
  122. return nil
  123. }
  124. return nil
  125. } else {
  126. // collect names after name, add them to Y
  127. namesToY, err := nl.NodeRangeAfterExclusive(prevNode.Reference(), name)
  128. if err != nil {
  129. return nil
  130. }
  131. // add namesToY and name to a new Y
  132. namesToY = append(namesToY, name)
  133. if err := nl.ItemAdd(lookupKey, 0, namesToY...); err != nil {
  134. return nil
  135. }
  136. // remove names after name from current X
  137. if err := nl.NodeDeleteAfterExclusive(prevNode.Reference(), name); err != nil {
  138. return nil
  139. }
  140. return nil
  141. }
  142. }
  143. // case 2.4
  144. if nextNode != nil {
  145. nodeSize := nl.NodeSize(nextNode.Reference())
  146. if nodeSize < nl.batchSize {
  147. if id, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
  148. return err
  149. } else {
  150. if err := nl.ItemAdd(lookupKey, id, name); err != nil {
  151. return err
  152. }
  153. }
  154. return nil
  155. }
  156. }
  157. // case 2.5
  158. // now prevNode is nil
  159. return nl.ItemAdd(lookupKey, 0, name)
  160. }
  161. /*
  162. // case 1: exists in nextNode
  163. if nextNode != nil && nextNode.Key == name {
  164. remove from nextNode, update nextNode
  165. // TODO: merge with prevNode if possible?
  166. return
  167. }
  168. if nextNode is nil
  169. prevNode = list.Largestnode
  170. if prevNode == nil and nextNode.Prev != nil
  171. prevNode = load(nextNode.Prev)
  172. // case 2: does not exist
  173. // case 2.1
  174. if prevNode == nil {
  175. return
  176. }
  177. // case 2.2
  178. if prevNameBatch does not contain name {
  179. return
  180. }
  181. // case 3
  182. delete from prevNameBatch
  183. if prevNameBatch + nextNode < capacityList
  184. // case 3.1
  185. merge
  186. else
  187. // case 3.2
  188. update prevNode
  189. */
  190. func (nl *ItemList) DeleteName(name string) error {
  191. lookupKey := []byte(name)
  192. prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
  193. if err != nil {
  194. return err
  195. }
  196. // case 1
  197. if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
  198. if _, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
  199. return err
  200. }
  201. if err := nl.NodeDeleteMember(nextNode.Reference(), name); err != nil {
  202. return err
  203. }
  204. minName := nl.NodeMin(nextNode.Reference())
  205. if minName == "" {
  206. return nl.NodeDelete(nextNode.Reference())
  207. }
  208. return nl.ItemAdd([]byte(minName), nextNode.Id)
  209. }
  210. if !found {
  211. prevNode, err = nl.skipList.GetLargestNode()
  212. if err != nil {
  213. return err
  214. }
  215. }
  216. if nextNode != nil && prevNode == nil {
  217. prevNode, err = nl.skipList.LoadElement(nextNode.Prev)
  218. if err != nil {
  219. return err
  220. }
  221. }
  222. // case 2
  223. if prevNode == nil {
  224. // case 2.1
  225. return nil
  226. }
  227. if !nl.NodeContainsItem(prevNode.Reference(), name) {
  228. return nil
  229. }
  230. // case 3
  231. if err := nl.NodeDeleteMember(prevNode.Reference(), name); err != nil {
  232. return err
  233. }
  234. prevSize := nl.NodeSize(prevNode.Reference())
  235. if prevSize == 0 {
  236. if _, err := nl.skipList.DeleteByKey(prevNode.Key); err != nil {
  237. return err
  238. }
  239. return nil
  240. }
  241. nextSize := nl.NodeSize(nextNode.Reference())
  242. if nextSize > 0 && prevSize + nextSize < nl.batchSize {
  243. // case 3.1 merge nextNode and prevNode
  244. if _, err := nl.skipList.DeleteByKey(nextNode.Key); err != nil {
  245. return err
  246. }
  247. nextNames, err := nl.NodeRangeBeforeExclusive(nextNode.Reference(), "")
  248. if err != nil {
  249. return err
  250. }
  251. if err := nl.NodeAddMember(prevNode.Reference(), nextNames...); err != nil {
  252. return err
  253. }
  254. return nl.NodeDelete(nextNode.Reference())
  255. } else {
  256. // case 3.2 update prevNode
  257. // no action to take
  258. return nil
  259. }
  260. return nil
  261. }
  262. func (nl *ItemList) ListNames(startFrom string, visitNamesFn func(name string) bool) error {
  263. lookupKey := []byte(startFrom)
  264. prevNode, nextNode, found, err := nl.skipList.FindGreaterOrEqual(lookupKey)
  265. if err != nil {
  266. return err
  267. }
  268. if found && bytes.Compare(nextNode.Key, lookupKey) == 0 {
  269. prevNode = nil
  270. }
  271. if !found {
  272. prevNode, err = nl.skipList.GetLargestNode()
  273. if err != nil {
  274. return err
  275. }
  276. }
  277. if prevNode != nil {
  278. if !nl.NodeScanIncluseiveAfter(prevNode.Reference(), startFrom, visitNamesFn) {
  279. return nil
  280. }
  281. }
  282. for nextNode != nil {
  283. if !nl.NodeScanIncluseiveAfter(nextNode.Reference(), startFrom, visitNamesFn) {
  284. return nil
  285. }
  286. nextNode, err = nl.skipList.LoadElement(nextNode.Next[0])
  287. if err != nil {
  288. return err
  289. }
  290. }
  291. return nil
  292. }
  293. func (nl *ItemList) RemoteAllListElement() error {
  294. t := nl.skipList
  295. nodeRef := t.StartLevels[0]
  296. for nodeRef != nil {
  297. node, err := t.LoadElement(nodeRef)
  298. if err != nil {
  299. return err
  300. }
  301. if node == nil {
  302. return nil
  303. }
  304. if err := t.DeleteElement(node); err != nil {
  305. return err
  306. }
  307. if err := nl.NodeDelete(node.Reference()); err != nil {
  308. return err
  309. }
  310. nodeRef = node.Next[0]
  311. }
  312. return nil
  313. }
  314. func (nl *ItemList) NodeContainsItem(node *skiplist.SkipListElementReference, item string) bool {
  315. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  316. _, err := nl.client.ZScore(context.Background(), key, item).Result()
  317. if err == redis.Nil {
  318. return false
  319. }
  320. if err == nil {
  321. return true
  322. }
  323. return false
  324. }
  325. func (nl *ItemList) NodeSize(node *skiplist.SkipListElementReference) int {
  326. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  327. return int(nl.client.ZLexCount(context.Background(), key, "-", "+").Val())
  328. }
  329. func (nl *ItemList) NodeAddMember(node *skiplist.SkipListElementReference, names ...string) error {
  330. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  331. var members []*redis.Z
  332. for _, name := range names {
  333. members = append(members, &redis.Z{
  334. Score: 0,
  335. Member: name,
  336. })
  337. }
  338. return nl.client.ZAddNX(context.Background(), key, members...).Err()
  339. }
  340. func (nl *ItemList) NodeDeleteMember(node *skiplist.SkipListElementReference, name string) error {
  341. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  342. return nl.client.ZRem(context.Background(), key, name).Err()
  343. }
  344. func (nl *ItemList) NodeDelete(node *skiplist.SkipListElementReference) error {
  345. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  346. return nl.client.Del(context.Background(), key).Err()
  347. }
  348. func (nl *ItemList) NodeInnerPosition(node *skiplist.SkipListElementReference, name string) int {
  349. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  350. return int(nl.client.ZLexCount(context.Background(), key, "-", "("+name).Val())
  351. }
  352. func (nl *ItemList) NodeMin(node *skiplist.SkipListElementReference) string {
  353. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  354. slice := nl.client.ZPopMin(context.Background(), key).Val()
  355. if len(slice)>0{
  356. s := slice[0].Member.(string)
  357. return s
  358. }
  359. return ""
  360. }
  361. func (nl *ItemList) NodeScanIncluseiveAfter(node *skiplist.SkipListElementReference, startFrom string, visitNamesFn func(name string) bool) bool {
  362. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  363. if startFrom == "" {
  364. startFrom = "-"
  365. } else {
  366. startFrom = "[" + startFrom
  367. }
  368. names := nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
  369. Min: startFrom,
  370. Max: "+",
  371. }).Val()
  372. for _, n := range names {
  373. if !visitNamesFn(n) {
  374. return false
  375. }
  376. }
  377. return true
  378. }
  379. func (nl *ItemList) NodeRangeBeforeExclusive(node *skiplist.SkipListElementReference, stopAt string) ([]string, error) {
  380. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  381. if stopAt == "" {
  382. stopAt = "+"
  383. } else {
  384. stopAt = "(" + stopAt
  385. }
  386. return nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
  387. Min: "-",
  388. Max: stopAt,
  389. }).Result()
  390. }
  391. func (nl *ItemList) NodeRangeAfterExclusive(node *skiplist.SkipListElementReference, startFrom string) ([]string, error) {
  392. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  393. if startFrom == "" {
  394. startFrom = "-"
  395. } else {
  396. startFrom = "(" + startFrom
  397. }
  398. return nl.client.ZRangeByLex(context.Background(), key, &redis.ZRangeBy{
  399. Min: startFrom,
  400. Max: "+",
  401. }).Result()
  402. }
  403. func (nl *ItemList) NodeDeleteBeforeExclusive(node *skiplist.SkipListElementReference, stopAt string) error {
  404. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  405. if stopAt == "" {
  406. stopAt = "+"
  407. } else {
  408. stopAt = "(" + stopAt
  409. }
  410. return nl.client.ZRemRangeByLex(context.Background(), key, "-", stopAt).Err()
  411. }
  412. func (nl *ItemList) NodeDeleteAfterExclusive(node *skiplist.SkipListElementReference, startFrom string) error {
  413. key := fmt.Sprintf("%s%dm", nl.prefix, node.ElementPointer)
  414. if startFrom == "" {
  415. startFrom = "-"
  416. } else {
  417. startFrom = "(" + startFrom
  418. }
  419. return nl.client.ZRemRangeByLex(context.Background(), key, startFrom, "+").Err()
  420. }
  421. func (nl *ItemList) ItemAdd(lookupKey []byte, idIfKnown int64, names ...string) error {
  422. if id, err := nl.skipList.InsertByKey(lookupKey, idIfKnown, nil); err != nil {
  423. return err
  424. } else {
  425. if len(names) > 0 {
  426. return nl.NodeAddMember(&skiplist.SkipListElementReference{
  427. ElementPointer: id,
  428. Key: lookupKey,
  429. }, names...)
  430. }
  431. }
  432. return nil
  433. }