log_unstable.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. Copyright 2014 CoreOS, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package raft
  14. import (
  15. "log"
  16. pb "github.com/coreos/etcd/raft/raftpb"
  17. )
  18. // unstable.entris[i] has raft log position i+unstable.offset.
  19. // Note that unstable.offset may be less than the highest log
  20. // position in storage; this means that the next write to storage
  21. // might need to truncate the log before persisting unstable.entries.
  22. type unstable struct {
  23. // the incoming unstable snapshot, if any.
  24. snapshot *pb.Snapshot
  25. // all entries that have not yet been written to storage.
  26. entries []pb.Entry
  27. offset uint64
  28. }
  29. // maybeFirstIndex returns the first index if it has a snapshot.
  30. func (u *unstable) maybeFirstIndex() (uint64, bool) {
  31. if u.snapshot != nil {
  32. return u.snapshot.Metadata.Index, true
  33. }
  34. return 0, false
  35. }
  36. // maybeLastIndex returns the last index if it has at least one
  37. // unstable entry or snapshot.
  38. func (u *unstable) maybeLastIndex() (uint64, bool) {
  39. if l := len(u.entries); l != 0 {
  40. return u.offset + uint64(l) - 1, true
  41. }
  42. if u.snapshot != nil {
  43. return u.snapshot.Metadata.Index, true
  44. }
  45. return 0, false
  46. }
  47. // myabeTerm returns the term of the entry at index i, if there
  48. // is any.
  49. func (u *unstable) maybeTerm(i uint64) (uint64, bool) {
  50. if i < u.offset {
  51. if u.snapshot == nil {
  52. return 0, false
  53. }
  54. if u.snapshot.Metadata.Index == i {
  55. return u.snapshot.Metadata.Term, true
  56. }
  57. return 0, false
  58. }
  59. last, ok := u.maybeLastIndex()
  60. if !ok {
  61. return 0, false
  62. }
  63. if i > last {
  64. return 0, false
  65. }
  66. return u.entries[i-u.offset].Term, true
  67. }
  68. func (u *unstable) stableTo(i uint64) {
  69. if i < u.offset || i+1-u.offset > uint64(len(u.entries)) {
  70. log.Panicf("stableTo(%d) is out of range [unstable(%d), len(unstableEnts)(%d)]",
  71. i, u.offset, len(u.entries))
  72. }
  73. u.entries = u.entries[i+1-u.offset:]
  74. u.offset = i + 1
  75. }
  76. func (u *unstable) stableSnapTo(i uint64) {
  77. if u.snapshot != nil && u.snapshot.Metadata.Index == i {
  78. u.snapshot = nil
  79. }
  80. }
  81. func (u *unstable) restore(s pb.Snapshot) {
  82. u.offset = s.Metadata.Index + 1
  83. u.entries = nil
  84. u.snapshot = &s
  85. }
  86. func (u *unstable) resetEntries(offset uint64) {
  87. u.entries = nil
  88. u.offset = offset
  89. }
  90. func (u *unstable) truncateAndAppend(after uint64, ents []pb.Entry) {
  91. if after < u.offset {
  92. // The log is being truncated to before our current unstable
  93. // portion, so discard it and reset unstable.
  94. u.resetEntries(after + 1)
  95. }
  96. u.entries = append(u.slice(u.offset, after+1), ents...)
  97. }
  98. func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry {
  99. if lo >= hi {
  100. return nil
  101. }
  102. if u.isOutOfBounds(lo) || u.isOutOfBounds(hi-1) {
  103. return nil
  104. }
  105. return u.entries[lo-u.offset : hi-u.offset]
  106. }
  107. func (u *unstable) isOutOfBounds(i uint64) bool {
  108. if len(u.entries) == 0 {
  109. return true
  110. }
  111. last := u.offset + uint64(len(u.entries)) - 1
  112. if i < u.offset || i > last {
  113. return true
  114. }
  115. return false
  116. }