github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/simplebft/calendarqueue_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package simplebft 18 19 import ( 20 "sort" 21 "time" 22 ) 23 24 type calendarQueue struct { 25 dayLength time.Duration 26 yearLength time.Duration 27 today time.Duration 28 nextYear time.Duration 29 slots [][]testElem 30 maxLen int 31 } 32 33 func newCalendarQueue(dayLength time.Duration, days int) *calendarQueue { 34 return &calendarQueue{ 35 dayLength: dayLength, 36 yearLength: dayLength * time.Duration(days), 37 nextYear: dayLength * time.Duration(days), 38 slots: make([][]testElem, days), 39 } 40 } 41 42 func (t *calendarQueue) slot(d time.Duration) int { 43 return int(d/t.dayLength) % len(t.slots) 44 } 45 46 func (t *calendarQueue) Add(e testElem) { 47 sl := t.slot(e.at) 48 t.slots[sl] = append(t.slots[sl], e) 49 l := len(t.slots[sl]) 50 if l > t.maxLen { 51 t.maxLen = l 52 } 53 sort.Sort(testElemQueue(t.slots[sl])) 54 } 55 56 func (t *calendarQueue) Pop() (testElem, bool) { 57 var lowest *time.Duration 58 sl := t.slot(t.today) 59 start := sl 60 today := t.today 61 for ; today < t.nextYear; today, sl = today+t.dayLength, sl+1 { 62 if len(t.slots[sl]) == 0 { 63 continue 64 } 65 e := t.slots[sl][0] 66 if e.at >= t.nextYear { 67 if lowest == nil || *lowest > e.at { 68 lowest = &e.at 69 } 70 continue 71 } 72 t.slots[sl] = t.slots[sl][1:] 73 t.today = today 74 return e, true 75 } 76 77 // next deadline is after this year, but we only 78 // searched part of the calendar so far. Search the 79 // remaining prefix. 80 for i := 0; i < start; i++ { 81 if len(t.slots[i]) == 0 { 82 continue 83 } 84 e := t.slots[i][0] 85 if e.at >= t.nextYear { 86 if lowest == nil || *lowest > e.at { 87 lowest = &e.at 88 } 89 } 90 } 91 92 if lowest == nil { 93 return testElem{}, false 94 } 95 96 t.today = *lowest / t.dayLength * t.dayLength 97 t.nextYear = (t.today/t.yearLength + 1) * t.yearLength 98 return t.Pop() // retry! 99 } 100 101 func (t *calendarQueue) filter(fn func(testElem) bool) { 102 for sli, sl := range t.slots { 103 var del []int 104 for i, e := range sl { 105 if !fn(e) { 106 del = append(del, i) 107 } 108 } 109 110 // now delete 111 for i, e := range del { 112 correctedPos := e - i 113 // in-place remove 114 sl = sl[:correctedPos+copy(sl[correctedPos:], sl[correctedPos+1:])] 115 } 116 t.slots[sli] = sl 117 } 118 } 119 120 ///////////////////////////////////////// 121 122 type testElemQueue []testElem 123 124 func (q testElemQueue) Len() int { 125 return len(q) 126 } 127 128 func (q testElemQueue) Less(i, j int) bool { 129 return q[i].at < q[j].at 130 } 131 132 func (q testElemQueue) Swap(i, j int) { 133 q[i], q[j] = q[j], q[i] 134 }