mirror of
https://github.com/muun/recovery.git
synced 2025-11-10 14:09:50 -05:00
Release v0.3.0
This commit is contained in:
116
vendor/github.com/lightningnetwork/lnd/queue/circular_buf.go
generated
vendored
Normal file
116
vendor/github.com/lightningnetwork/lnd/queue/circular_buf.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// errInvalidSize is returned when an invalid size for a buffer is provided.
|
||||
var errInvalidSize = errors.New("buffer size must be > 0")
|
||||
|
||||
// CircularBuffer is a buffer which retains a set of values in memory, and
|
||||
// overwrites the oldest item in the buffer when a new item needs to be
|
||||
// written.
|
||||
type CircularBuffer struct {
|
||||
// total is the total number of items that have been added to the
|
||||
// buffer.
|
||||
total int
|
||||
|
||||
// items is the set of buffered items.
|
||||
items []interface{}
|
||||
}
|
||||
|
||||
// NewCircularBuffer returns a new circular buffer with the size provided. It
|
||||
// will fail if a zero or negative size parameter is provided.
|
||||
func NewCircularBuffer(size int) (*CircularBuffer, error) {
|
||||
if size <= 0 {
|
||||
return nil, errInvalidSize
|
||||
}
|
||||
|
||||
return &CircularBuffer{
|
||||
total: 0,
|
||||
|
||||
// Create a slice with length and capacity equal to the size of
|
||||
// the buffer so that we do not need to resize the underlying
|
||||
// array when we add items.
|
||||
items: make([]interface{}, size),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// index returns the index that should be written to next.
|
||||
func (c *CircularBuffer) index() int {
|
||||
return c.total % len(c.items)
|
||||
}
|
||||
|
||||
// Add adds an item to the buffer, overwriting the oldest item if the buffer
|
||||
// is full.
|
||||
func (c *CircularBuffer) Add(item interface{}) {
|
||||
// Set the item in the next free index in the items array.
|
||||
c.items[c.index()] = item
|
||||
|
||||
// Increment the total number of items that we have stored.
|
||||
c.total++
|
||||
}
|
||||
|
||||
// List returns a copy of the items in the buffer ordered from the oldest to
|
||||
// newest item.
|
||||
func (c *CircularBuffer) List() []interface{} {
|
||||
size := cap(c.items)
|
||||
index := c.index()
|
||||
|
||||
switch {
|
||||
// If no items have been stored yet, we can just return a nil list.
|
||||
case c.total == 0:
|
||||
return nil
|
||||
|
||||
// If we have added fewer items than the buffer size, we can simply
|
||||
// return the total number of items from the beginning of the list
|
||||
// to the index. This special case is added because the oldest item
|
||||
// is at the beginning of the underlying array, not at the index when
|
||||
// we have not filled the array yet.
|
||||
case c.total < size:
|
||||
resp := make([]interface{}, c.total)
|
||||
copy(resp, c.items[:c.index()])
|
||||
return resp
|
||||
}
|
||||
|
||||
resp := make([]interface{}, size)
|
||||
|
||||
// Get the items in the underlying array from index to end, the first
|
||||
// item in this slice will be the oldest item in the list.
|
||||
firstHalf := c.items[index:]
|
||||
|
||||
// Copy the first set into our response slice from index 0, so that
|
||||
// the response returned is from oldest to newest.
|
||||
copy(resp, firstHalf)
|
||||
|
||||
// Get the items in the underlying array from beginning until the write
|
||||
// index, the last item in this slice will be the newest item in the
|
||||
// list.
|
||||
secondHalf := c.items[:index]
|
||||
|
||||
// Copy the second set of items into the response slice offset by the
|
||||
// length of the first set of items so that we return a response which
|
||||
// is ordered from oldest to newest entry.
|
||||
copy(resp[len(firstHalf):], secondHalf)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// Total returns the total number of items that have been added to the buffer.
|
||||
func (c *CircularBuffer) Total() int {
|
||||
return c.total
|
||||
}
|
||||
|
||||
// Latest returns the item that was most recently added to the buffer.
|
||||
func (c *CircularBuffer) Latest() interface{} {
|
||||
// If no items have been added yet, return nil.
|
||||
if c.total == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The latest item is one before our total, mod by length.
|
||||
latest := (c.total - 1) % len(c.items)
|
||||
|
||||
// Return the latest item added.
|
||||
return c.items[latest]
|
||||
}
|
||||
2
vendor/github.com/lightningnetwork/lnd/queue/gc_queue.go
generated
vendored
2
vendor/github.com/lightningnetwork/lnd/queue/gc_queue.go
generated
vendored
@@ -2,7 +2,6 @@ package queue
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
@@ -44,7 +43,6 @@ type GCQueue struct {
|
||||
// increasing time of arrival.
|
||||
freeList *list.List
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/lightningnetwork/lnd/queue/go.mod
generated
vendored
2
vendor/github.com/lightningnetwork/lnd/queue/go.mod
generated
vendored
@@ -3,3 +3,5 @@ module github.com/lightningnetwork/lnd/queue
|
||||
require github.com/lightningnetwork/lnd/ticker v1.0.0
|
||||
|
||||
replace github.com/lightningnetwork/lnd/ticker v1.0.0 => ../ticker
|
||||
|
||||
go 1.12
|
||||
|
||||
2
vendor/github.com/lightningnetwork/lnd/queue/go.sum
generated
vendored
2
vendor/github.com/lightningnetwork/lnd/queue/go.sum
generated
vendored
@@ -1,2 +0,0 @@
|
||||
github.com/lightningnetwork/lnd/ticker v1.0.0 h1:S1b60TEGoTtCe2A0yeB+ecoj/kkS4qpwh6l+AkQEZwU=
|
||||
github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0=
|
||||
|
||||
76
vendor/github.com/lightningnetwork/lnd/queue/priority_queue.go
generated
vendored
Normal file
76
vendor/github.com/lightningnetwork/lnd/queue/priority_queue.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
)
|
||||
|
||||
// PriorityQueueItem is an interface that represents items in a PriorityQueue.
|
||||
// Users of PriorityQueue will need to define a Less function such that
|
||||
// PriorityQueue will be able to use that to build and restore an underlying
|
||||
// heap.
|
||||
type PriorityQueueItem interface {
|
||||
// Less must return true if this item is ordered before other and false
|
||||
// otherwise.
|
||||
Less(other PriorityQueueItem) bool
|
||||
}
|
||||
|
||||
type priorityQueue []PriorityQueueItem
|
||||
|
||||
// Len returns the length of the priorityQueue.
|
||||
func (pq priorityQueue) Len() int { return len(pq) }
|
||||
|
||||
// Less is used to order PriorityQueueItem items in the queue.
|
||||
func (pq priorityQueue) Less(i, j int) bool {
|
||||
return pq[i].Less(pq[j])
|
||||
}
|
||||
|
||||
// Swap swaps two items in the priorityQueue. Swap is used by heap.Interface.
|
||||
func (pq priorityQueue) Swap(i, j int) {
|
||||
pq[i], pq[j] = pq[j], pq[i]
|
||||
}
|
||||
|
||||
// Push adds a new item the the priorityQueue.
|
||||
func (pq *priorityQueue) Push(x interface{}) {
|
||||
item := x.(PriorityQueueItem)
|
||||
*pq = append(*pq, item)
|
||||
}
|
||||
|
||||
// Pop removes the top item from the priorityQueue.
|
||||
func (pq *priorityQueue) Pop() interface{} {
|
||||
old := *pq
|
||||
n := len(old)
|
||||
item := old[n-1]
|
||||
old[n-1] = nil
|
||||
*pq = old[0 : n-1]
|
||||
return item
|
||||
}
|
||||
|
||||
// PriorityQueue wraps a standard heap into a self contained class.
|
||||
type PriorityQueue struct {
|
||||
queue priorityQueue
|
||||
}
|
||||
|
||||
// Len returns the length of the queue.
|
||||
func (pq *PriorityQueue) Len() int {
|
||||
return len(pq.queue)
|
||||
}
|
||||
|
||||
// Empty returns true if the queue is empty.
|
||||
func (pq *PriorityQueue) Empty() bool {
|
||||
return len(pq.queue) == 0
|
||||
}
|
||||
|
||||
// Push adds an item to the priority queue.
|
||||
func (pq *PriorityQueue) Push(item PriorityQueueItem) {
|
||||
heap.Push(&pq.queue, item)
|
||||
}
|
||||
|
||||
// Pop removes the top most item from the queue.
|
||||
func (pq *PriorityQueue) Pop() PriorityQueueItem {
|
||||
return heap.Pop(&pq.queue).(PriorityQueueItem)
|
||||
}
|
||||
|
||||
// Top returns the top most item from the queue without removing it.
|
||||
func (pq *PriorityQueue) Top() PriorityQueueItem {
|
||||
return pq.queue[0]
|
||||
}
|
||||
48
vendor/github.com/lightningnetwork/lnd/queue/queue.go
generated
vendored
48
vendor/github.com/lightningnetwork/lnd/queue/queue.go
generated
vendored
@@ -3,7 +3,6 @@ package queue
|
||||
import (
|
||||
"container/list"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// ConcurrentQueue is a concurrent-safe FIFO queue with unbounded capacity.
|
||||
@@ -12,8 +11,8 @@ import (
|
||||
// items from the in channel to the out channel in the correct order that must
|
||||
// be started by calling Start().
|
||||
type ConcurrentQueue struct {
|
||||
started uint32 // to be used atomically
|
||||
stopped uint32 // to be used atomically
|
||||
started sync.Once
|
||||
stopped sync.Once
|
||||
|
||||
chanIn chan interface{}
|
||||
chanOut chan interface{}
|
||||
@@ -51,14 +50,15 @@ func (cq *ConcurrentQueue) ChanOut() <-chan interface{} {
|
||||
// minimize overhead, but if the out channel is full it pushes items to an
|
||||
// overflow queue. This must be called before using the queue.
|
||||
func (cq *ConcurrentQueue) Start() {
|
||||
if !atomic.CompareAndSwapUint32(&cq.started, 0, 1) {
|
||||
return
|
||||
}
|
||||
cq.started.Do(cq.start)
|
||||
}
|
||||
|
||||
func (cq *ConcurrentQueue) start() {
|
||||
cq.wg.Add(1)
|
||||
go func() {
|
||||
defer cq.wg.Done()
|
||||
|
||||
readLoop:
|
||||
for {
|
||||
nextElement := cq.overflow.Front()
|
||||
if nextElement == nil {
|
||||
@@ -66,7 +66,10 @@ func (cq *ConcurrentQueue) Start() {
|
||||
// directly to the output channel. If output channel is full
|
||||
// though, push to overflow.
|
||||
select {
|
||||
case item := <-cq.chanIn:
|
||||
case item, ok := <-cq.chanIn:
|
||||
if !ok {
|
||||
break readLoop
|
||||
}
|
||||
select {
|
||||
case cq.chanOut <- item:
|
||||
// Optimistically push directly to chanOut
|
||||
@@ -80,7 +83,10 @@ func (cq *ConcurrentQueue) Start() {
|
||||
// Overflow queue is not empty, so any new items get pushed to
|
||||
// the back to preserve order.
|
||||
select {
|
||||
case item := <-cq.chanIn:
|
||||
case item, ok := <-cq.chanIn:
|
||||
if !ok {
|
||||
break readLoop
|
||||
}
|
||||
cq.overflow.PushBack(item)
|
||||
case cq.chanOut <- nextElement.Value:
|
||||
cq.overflow.Remove(nextElement)
|
||||
@@ -89,6 +95,22 @@ func (cq *ConcurrentQueue) Start() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Incoming channel has been closed. Empty overflow queue into
|
||||
// the outgoing channel.
|
||||
nextElement := cq.overflow.Front()
|
||||
for nextElement != nil {
|
||||
select {
|
||||
case cq.chanOut <- nextElement.Value:
|
||||
cq.overflow.Remove(nextElement)
|
||||
case <-cq.quit:
|
||||
return
|
||||
}
|
||||
nextElement = cq.overflow.Front()
|
||||
}
|
||||
|
||||
// Close outgoing channel.
|
||||
close(cq.chanOut)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -96,10 +118,8 @@ func (cq *ConcurrentQueue) Start() {
|
||||
// channel. This does not clear the queue state, so the queue can be restarted
|
||||
// without dropping items.
|
||||
func (cq *ConcurrentQueue) Stop() {
|
||||
if !atomic.CompareAndSwapUint32(&cq.stopped, 0, 1) {
|
||||
return
|
||||
}
|
||||
|
||||
close(cq.quit)
|
||||
cq.wg.Wait()
|
||||
cq.stopped.Do(func() {
|
||||
close(cq.quit)
|
||||
cq.wg.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user