all: switch out defunct set library to different one (#16873)
* keystore, ethash, eth, miner, rpc, whisperv6: tech debt with now defunct set. * whisperv5: swap out gopkg.in/fatih/set.v0 with supported set
This commit is contained in:
parent
eb7f901289
commit
5d30be412b
1
AUTHORS
1
AUTHORS
@ -171,3 +171,4 @@ xiekeyang <xiekeyang@users.noreply.github.com>
|
|||||||
yoza <yoza.is12s@gmail.com>
|
yoza <yoza.is12s@gmail.com>
|
||||||
ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com>
|
ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com>
|
||||||
Максим Чусовлянов <mchusovlianov@gmail.com>
|
Максим Чусовлянов <mchusovlianov@gmail.com>
|
||||||
|
Ralph Caraveo <deckarep@gmail.com>
|
||||||
|
@ -27,10 +27,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Minimum amount of time between cache reloads. This limit applies if the platform does
|
// Minimum amount of time between cache reloads. This limit applies if the platform does
|
||||||
@ -79,7 +79,7 @@ func newAccountCache(keydir string) (*accountCache, chan struct{}) {
|
|||||||
keydir: keydir,
|
keydir: keydir,
|
||||||
byAddr: make(map[common.Address][]accounts.Account),
|
byAddr: make(map[common.Address][]accounts.Account),
|
||||||
notify: make(chan struct{}, 1),
|
notify: make(chan struct{}, 1),
|
||||||
fileC: fileCache{all: set.NewNonTS()},
|
fileC: fileCache{all: mapset.NewThreadUnsafeSet()},
|
||||||
}
|
}
|
||||||
ac.watcher = newWatcher(ac)
|
ac.watcher = newWatcher(ac)
|
||||||
return ac, ac.notify
|
return ac, ac.notify
|
||||||
@ -237,7 +237,7 @@ func (ac *accountCache) scanAccounts() error {
|
|||||||
log.Debug("Failed to reload keystore contents", "err", err)
|
log.Debug("Failed to reload keystore contents", "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if creates.Size() == 0 && deletes.Size() == 0 && updates.Size() == 0 {
|
if creates.Cardinality() == 0 && deletes.Cardinality() == 0 && updates.Cardinality() == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Create a helper method to scan the contents of the key files
|
// Create a helper method to scan the contents of the key files
|
||||||
@ -272,15 +272,15 @@ func (ac *accountCache) scanAccounts() error {
|
|||||||
// Process all the file diffs
|
// Process all the file diffs
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
for _, p := range creates.List() {
|
for _, p := range creates.ToSlice() {
|
||||||
if a := readAccount(p.(string)); a != nil {
|
if a := readAccount(p.(string)); a != nil {
|
||||||
ac.add(*a)
|
ac.add(*a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range deletes.List() {
|
for _, p := range deletes.ToSlice() {
|
||||||
ac.deleteByFile(p.(string))
|
ac.deleteByFile(p.(string))
|
||||||
}
|
}
|
||||||
for _, p := range updates.List() {
|
for _, p := range updates.ToSlice() {
|
||||||
path := p.(string)
|
path := p.(string)
|
||||||
ac.deleteByFile(path)
|
ac.deleteByFile(path)
|
||||||
if a := readAccount(path); a != nil {
|
if a := readAccount(path); a != nil {
|
||||||
|
@ -24,20 +24,20 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// fileCache is a cache of files seen during scan of keystore.
|
// fileCache is a cache of files seen during scan of keystore.
|
||||||
type fileCache struct {
|
type fileCache struct {
|
||||||
all *set.SetNonTS // Set of all files from the keystore folder
|
all mapset.Set // Set of all files from the keystore folder
|
||||||
lastMod time.Time // Last time instance when a file was modified
|
lastMod time.Time // Last time instance when a file was modified
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan performs a new scan on the given directory, compares against the already
|
// scan performs a new scan on the given directory, compares against the already
|
||||||
// cached filenames, and returns file sets: creates, deletes, updates.
|
// cached filenames, and returns file sets: creates, deletes, updates.
|
||||||
func (fc *fileCache) scan(keyDir string) (set.Interface, set.Interface, set.Interface, error) {
|
func (fc *fileCache) scan(keyDir string) (mapset.Set, mapset.Set, mapset.Set, error) {
|
||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
|
|
||||||
// List all the failes from the keystore folder
|
// List all the failes from the keystore folder
|
||||||
@ -51,8 +51,8 @@ func (fc *fileCache) scan(keyDir string) (set.Interface, set.Interface, set.Inte
|
|||||||
defer fc.mu.Unlock()
|
defer fc.mu.Unlock()
|
||||||
|
|
||||||
// Iterate all the files and gather their metadata
|
// Iterate all the files and gather their metadata
|
||||||
all := set.NewNonTS()
|
all := mapset.NewThreadUnsafeSet()
|
||||||
mods := set.NewNonTS()
|
mods := mapset.NewThreadUnsafeSet()
|
||||||
|
|
||||||
var newLastMod time.Time
|
var newLastMod time.Time
|
||||||
for _, fi := range files {
|
for _, fi := range files {
|
||||||
@ -76,9 +76,9 @@ func (fc *fileCache) scan(keyDir string) (set.Interface, set.Interface, set.Inte
|
|||||||
t2 := time.Now()
|
t2 := time.Now()
|
||||||
|
|
||||||
// Update the tracked files and return the three sets
|
// Update the tracked files and return the three sets
|
||||||
deletes := set.Difference(fc.all, all) // Deletes = previous - current
|
deletes := fc.all.Difference(all) // Deletes = previous - current
|
||||||
creates := set.Difference(all, fc.all) // Creates = current - previous
|
creates := all.Difference(fc.all) // Creates = current - previous
|
||||||
updates := set.Difference(mods, creates) // Updates = modified - creates
|
updates := mods.Difference(creates) // Updates = modified - creates
|
||||||
|
|
||||||
fc.all, fc.lastMod = all, newLastMod
|
fc.all, fc.lastMod = all, newLastMod
|
||||||
t3 := time.Now()
|
t3 := time.Now()
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
@ -31,7 +32,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ethash proof-of-work protocol constants.
|
// Ethash proof-of-work protocol constants.
|
||||||
@ -177,7 +177,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
|
|||||||
return errTooManyUncles
|
return errTooManyUncles
|
||||||
}
|
}
|
||||||
// Gather the set of past uncles and ancestors
|
// Gather the set of past uncles and ancestors
|
||||||
uncles, ancestors := set.New(), make(map[common.Hash]*types.Header)
|
uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header)
|
||||||
|
|
||||||
number, parent := block.NumberU64()-1, block.ParentHash()
|
number, parent := block.NumberU64()-1, block.ParentHash()
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
@ -198,7 +198,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
|
|||||||
for _, uncle := range block.Uncles() {
|
for _, uncle := range block.Uncles() {
|
||||||
// Make sure every uncle is rewarded only once
|
// Make sure every uncle is rewarded only once
|
||||||
hash := uncle.Hash()
|
hash := uncle.Hash()
|
||||||
if uncles.Has(hash) {
|
if uncles.Contains(hash) {
|
||||||
return errDuplicateUncle
|
return errDuplicateUncle
|
||||||
}
|
}
|
||||||
uncles.Add(hash)
|
uncles.Add(hash)
|
||||||
|
18
eth/peer.go
18
eth/peer.go
@ -23,11 +23,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -85,8 +85,8 @@ type peer struct {
|
|||||||
td *big.Int
|
td *big.Int
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
knownTxs *set.Set // Set of transaction hashes known to be known by this peer
|
knownTxs mapset.Set // Set of transaction hashes known to be known by this peer
|
||||||
knownBlocks *set.Set // Set of block hashes known to be known by this peer
|
knownBlocks mapset.Set // Set of block hashes known to be known by this peer
|
||||||
queuedTxs chan []*types.Transaction // Queue of transactions to broadcast to the peer
|
queuedTxs chan []*types.Transaction // Queue of transactions to broadcast to the peer
|
||||||
queuedProps chan *propEvent // Queue of blocks to broadcast to the peer
|
queuedProps chan *propEvent // Queue of blocks to broadcast to the peer
|
||||||
queuedAnns chan *types.Block // Queue of blocks to announce to the peer
|
queuedAnns chan *types.Block // Queue of blocks to announce to the peer
|
||||||
@ -99,8 +99,8 @@ func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
|
|||||||
rw: rw,
|
rw: rw,
|
||||||
version: version,
|
version: version,
|
||||||
id: fmt.Sprintf("%x", p.ID().Bytes()[:8]),
|
id: fmt.Sprintf("%x", p.ID().Bytes()[:8]),
|
||||||
knownTxs: set.New(),
|
knownTxs: mapset.NewSet(),
|
||||||
knownBlocks: set.New(),
|
knownBlocks: mapset.NewSet(),
|
||||||
queuedTxs: make(chan []*types.Transaction, maxQueuedTxs),
|
queuedTxs: make(chan []*types.Transaction, maxQueuedTxs),
|
||||||
queuedProps: make(chan *propEvent, maxQueuedProps),
|
queuedProps: make(chan *propEvent, maxQueuedProps),
|
||||||
queuedAnns: make(chan *types.Block, maxQueuedAnns),
|
queuedAnns: make(chan *types.Block, maxQueuedAnns),
|
||||||
@ -177,7 +177,7 @@ func (p *peer) SetHead(hash common.Hash, td *big.Int) {
|
|||||||
// never be propagated to this particular peer.
|
// never be propagated to this particular peer.
|
||||||
func (p *peer) MarkBlock(hash common.Hash) {
|
func (p *peer) MarkBlock(hash common.Hash) {
|
||||||
// If we reached the memory allowance, drop a previously known block hash
|
// If we reached the memory allowance, drop a previously known block hash
|
||||||
for p.knownBlocks.Size() >= maxKnownBlocks {
|
for p.knownBlocks.Cardinality() >= maxKnownBlocks {
|
||||||
p.knownBlocks.Pop()
|
p.knownBlocks.Pop()
|
||||||
}
|
}
|
||||||
p.knownBlocks.Add(hash)
|
p.knownBlocks.Add(hash)
|
||||||
@ -187,7 +187,7 @@ func (p *peer) MarkBlock(hash common.Hash) {
|
|||||||
// will never be propagated to this particular peer.
|
// will never be propagated to this particular peer.
|
||||||
func (p *peer) MarkTransaction(hash common.Hash) {
|
func (p *peer) MarkTransaction(hash common.Hash) {
|
||||||
// If we reached the memory allowance, drop a previously known transaction hash
|
// If we reached the memory allowance, drop a previously known transaction hash
|
||||||
for p.knownTxs.Size() >= maxKnownTxs {
|
for p.knownTxs.Cardinality() >= maxKnownTxs {
|
||||||
p.knownTxs.Pop()
|
p.knownTxs.Pop()
|
||||||
}
|
}
|
||||||
p.knownTxs.Add(hash)
|
p.knownTxs.Add(hash)
|
||||||
@ -470,7 +470,7 @@ func (ps *peerSet) PeersWithoutBlock(hash common.Hash) []*peer {
|
|||||||
|
|
||||||
list := make([]*peer, 0, len(ps.peers))
|
list := make([]*peer, 0, len(ps.peers))
|
||||||
for _, p := range ps.peers {
|
for _, p := range ps.peers {
|
||||||
if !p.knownBlocks.Has(hash) {
|
if !p.knownBlocks.Contains(hash) {
|
||||||
list = append(list, p)
|
list = append(list, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,7 +485,7 @@ func (ps *peerSet) PeersWithoutTx(hash common.Hash) []*peer {
|
|||||||
|
|
||||||
list := make([]*peer, 0, len(ps.peers))
|
list := make([]*peer, 0, len(ps.peers))
|
||||||
for _, p := range ps.peers {
|
for _, p := range ps.peers {
|
||||||
if !p.knownTxs.Has(hash) {
|
if !p.knownTxs.Contains(hash) {
|
||||||
list = append(list, p)
|
list = append(list, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
@ -35,7 +36,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -67,9 +67,9 @@ type Work struct {
|
|||||||
signer types.Signer
|
signer types.Signer
|
||||||
|
|
||||||
state *state.StateDB // apply state changes here
|
state *state.StateDB // apply state changes here
|
||||||
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
|
ancestors mapset.Set // ancestor set (used for checking uncle parent validity)
|
||||||
family *set.Set // family set (used for checking uncle invalidity)
|
family mapset.Set // family set (used for checking uncle invalidity)
|
||||||
uncles *set.Set // uncle set
|
uncles mapset.Set // uncle set
|
||||||
tcount int // tx count in cycle
|
tcount int // tx count in cycle
|
||||||
gasPool *core.GasPool // available gas used to pack transactions
|
gasPool *core.GasPool // available gas used to pack transactions
|
||||||
|
|
||||||
@ -362,9 +362,9 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error
|
|||||||
config: self.config,
|
config: self.config,
|
||||||
signer: types.NewEIP155Signer(self.config.ChainID),
|
signer: types.NewEIP155Signer(self.config.ChainID),
|
||||||
state: state,
|
state: state,
|
||||||
ancestors: set.New(),
|
ancestors: mapset.NewSet(),
|
||||||
family: set.New(),
|
family: mapset.NewSet(),
|
||||||
uncles: set.New(),
|
uncles: mapset.NewSet(),
|
||||||
header: header,
|
header: header,
|
||||||
createdAt: time.Now(),
|
createdAt: time.Now(),
|
||||||
}
|
}
|
||||||
@ -492,13 +492,13 @@ func (self *worker) commitNewWork() {
|
|||||||
|
|
||||||
func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
|
func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
|
||||||
hash := uncle.Hash()
|
hash := uncle.Hash()
|
||||||
if work.uncles.Has(hash) {
|
if work.uncles.Contains(hash) {
|
||||||
return fmt.Errorf("uncle not unique")
|
return fmt.Errorf("uncle not unique")
|
||||||
}
|
}
|
||||||
if !work.ancestors.Has(uncle.ParentHash) {
|
if !work.ancestors.Contains(uncle.ParentHash) {
|
||||||
return fmt.Errorf("uncle's parent unknown (%x)", uncle.ParentHash[0:4])
|
return fmt.Errorf("uncle's parent unknown (%x)", uncle.ParentHash[0:4])
|
||||||
}
|
}
|
||||||
if work.family.Has(hash) {
|
if work.family.Contains(hash) {
|
||||||
return fmt.Errorf("uncle already in family (%x)", hash)
|
return fmt.Errorf("uncle already in family (%x)", hash)
|
||||||
}
|
}
|
||||||
work.uncles.Add(uncle.Hash())
|
work.uncles.Add(uncle.Hash())
|
||||||
|
@ -25,8 +25,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const MetadataApi = "rpc"
|
const MetadataApi = "rpc"
|
||||||
@ -46,7 +46,7 @@ const (
|
|||||||
func NewServer() *Server {
|
func NewServer() *Server {
|
||||||
server := &Server{
|
server := &Server{
|
||||||
services: make(serviceRegistry),
|
services: make(serviceRegistry),
|
||||||
codecs: set.New(),
|
codecs: mapset.NewSet(),
|
||||||
run: 1,
|
run: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// API describes the set of methods offered over the RPC interface
|
// API describes the set of methods offered over the RPC interface
|
||||||
@ -73,7 +73,7 @@ type Server struct {
|
|||||||
|
|
||||||
run int32
|
run int32
|
||||||
codecsMu sync.Mutex
|
codecsMu sync.Mutex
|
||||||
codecs *set.Set
|
codecs mapset.Set
|
||||||
}
|
}
|
||||||
|
|
||||||
// rpcRequest represents a raw incoming RPC request
|
// rpcRequest represents a raw incoming RPC request
|
||||||
|
@ -29,9 +29,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
"gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// websocketJSONCodec is a custom JSON codec with payload size enforcement and
|
// websocketJSONCodec is a custom JSON codec with payload size enforcement and
|
||||||
@ -84,7 +84,7 @@ func NewWSServer(allowedOrigins []string, srv *Server) *http.Server {
|
|||||||
// websocket upgrade process. When a '*' is specified as an allowed origins all
|
// websocket upgrade process. When a '*' is specified as an allowed origins all
|
||||||
// connections are accepted.
|
// connections are accepted.
|
||||||
func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http.Request) error {
|
func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http.Request) error {
|
||||||
origins := set.New()
|
origins := mapset.NewSet()
|
||||||
allowAllOrigins := false
|
allowAllOrigins := false
|
||||||
|
|
||||||
for _, origin := range allowedOrigins {
|
for _, origin := range allowedOrigins {
|
||||||
@ -97,18 +97,18 @@ func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allow localhost if no allowedOrigins are specified.
|
// allow localhost if no allowedOrigins are specified.
|
||||||
if len(origins.List()) == 0 {
|
if len(origins.ToSlice()) == 0 {
|
||||||
origins.Add("http://localhost")
|
origins.Add("http://localhost")
|
||||||
if hostname, err := os.Hostname(); err == nil {
|
if hostname, err := os.Hostname(); err == nil {
|
||||||
origins.Add("http://" + strings.ToLower(hostname))
|
origins.Add("http://" + strings.ToLower(hostname))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v\n", origins.List()))
|
log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v\n", origins.ToSlice()))
|
||||||
|
|
||||||
f := func(cfg *websocket.Config, req *http.Request) error {
|
f := func(cfg *websocket.Config, req *http.Request) error {
|
||||||
origin := strings.ToLower(req.Header.Get("Origin"))
|
origin := strings.ToLower(req.Header.Get("Origin"))
|
||||||
if allowAllOrigins || origins.Has(origin) {
|
if allowAllOrigins || origins.Contains(origin) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Warn(fmt.Sprintf("origin '%s' not allowed on WS-RPC interface\n", origin))
|
log.Warn(fmt.Sprintf("origin '%s' not allowed on WS-RPC interface\n", origin))
|
||||||
|
22
vendor/gopkg.in/fatih/set.v0/LICENSE.md → vendor/github.com/deckarep/golang-set/LICENSE
generated
vendored
22
vendor/gopkg.in/fatih/set.v0/LICENSE.md → vendor/github.com/deckarep/golang-set/LICENSE
generated
vendored
@ -1,20 +1,22 @@
|
|||||||
The MIT License (MIT)
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
Copyright (c) 2013 Fatih Arslan
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
subject to the following conditions:
|
so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
95
vendor/github.com/deckarep/golang-set/README.md
generated
vendored
Normal file
95
vendor/github.com/deckarep/golang-set/README.md
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
[![Build Status](https://travis-ci.org/deckarep/golang-set.svg?branch=master)](https://travis-ci.org/deckarep/golang-set)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set)](https://goreportcard.com/report/github.com/deckarep/golang-set)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/deckarep/golang-set?status.svg)](http://godoc.org/github.com/deckarep/golang-set)
|
||||||
|
|
||||||
|
## golang-set
|
||||||
|
|
||||||
|
|
||||||
|
The missing set collection for the Go language. Until Go has sets built-in...use this.
|
||||||
|
|
||||||
|
Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set from Python.
|
||||||
|
You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository
|
||||||
|
and carry-on and to the rest that find this useful please contribute in helping me make it better by:
|
||||||
|
|
||||||
|
* Helping to make more idiomatic improvements to the code.
|
||||||
|
* Helping to increase the performance of it. ~~(So far, no attempt has been made, but since it uses a map internally, I expect it to be mostly performant.)~~
|
||||||
|
* Helping to make the unit-tests more robust and kick-ass.
|
||||||
|
* Helping to fill in the [documentation.](http://godoc.org/github.com/deckarep/golang-set)
|
||||||
|
* Simply offering feedback and suggestions. (Positive, constructive feedback is appreciated.)
|
||||||
|
|
||||||
|
I have to give some credit for helping seed the idea with this post on [stackoverflow.](http://programmers.stackexchange.com/questions/177428/sets-data-structure-in-golang)
|
||||||
|
|
||||||
|
*Update* - as of 3/9/2014, you can use a compile-time generic version of this package in the [gen](http://clipperhouse.github.io/gen/) framework. This framework allows you to use the golang-set in a completely generic and type-safe way by allowing you to generate a supporting .go file based on your custom types.
|
||||||
|
|
||||||
|
## Features (as of 9/22/2014)
|
||||||
|
|
||||||
|
* a CartesianProduct() method has been added with unit-tests: [Read more about the cartesian product](http://en.wikipedia.org/wiki/Cartesian_product)
|
||||||
|
|
||||||
|
## Features (as of 9/15/2014)
|
||||||
|
|
||||||
|
* a PowerSet() method has been added with unit-tests: [Read more about the Power set](http://en.wikipedia.org/wiki/Power_set)
|
||||||
|
|
||||||
|
## Features (as of 4/22/2014)
|
||||||
|
|
||||||
|
* One common interface to both implementations
|
||||||
|
* Two set implementations to choose from
|
||||||
|
* a thread-safe implementation designed for concurrent use
|
||||||
|
* a non-thread-safe implementation designed for performance
|
||||||
|
* 75 benchmarks for both implementations
|
||||||
|
* 35 unit tests for both implementations
|
||||||
|
* 14 concurrent tests for the thread-safe implementation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Please see the unit test file for additional usage examples. The Python set documentation will also do a better job than I can of explaining how a set typically [works.](http://docs.python.org/2/library/sets.html) Please keep in mind
|
||||||
|
however that the Python set is a built-in type and supports additional features and syntax that make it awesome.
|
||||||
|
|
||||||
|
## Examples but not exhaustive:
|
||||||
|
|
||||||
|
```go
|
||||||
|
requiredClasses := mapset.NewSet()
|
||||||
|
requiredClasses.Add("Cooking")
|
||||||
|
requiredClasses.Add("English")
|
||||||
|
requiredClasses.Add("Math")
|
||||||
|
requiredClasses.Add("Biology")
|
||||||
|
|
||||||
|
scienceSlice := []interface{}{"Biology", "Chemistry"}
|
||||||
|
scienceClasses := mapset.NewSetFromSlice(scienceSlice)
|
||||||
|
|
||||||
|
electiveClasses := mapset.NewSet()
|
||||||
|
electiveClasses.Add("Welding")
|
||||||
|
electiveClasses.Add("Music")
|
||||||
|
electiveClasses.Add("Automotive")
|
||||||
|
|
||||||
|
bonusClasses := mapset.NewSet()
|
||||||
|
bonusClasses.Add("Go Programming")
|
||||||
|
bonusClasses.Add("Python Programming")
|
||||||
|
|
||||||
|
//Show me all the available classes I can take
|
||||||
|
allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
|
||||||
|
fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming}
|
||||||
|
|
||||||
|
|
||||||
|
//Is cooking considered a science class?
|
||||||
|
fmt.Println(scienceClasses.Contains("Cooking")) //false
|
||||||
|
|
||||||
|
//Show me all classes that are not science classes, since I hate science.
|
||||||
|
fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding}
|
||||||
|
|
||||||
|
//Which science classes are also required classes?
|
||||||
|
fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
|
||||||
|
|
||||||
|
//How many bonus classes do you offer?
|
||||||
|
fmt.Println(bonusClasses.Cardinality()) //2
|
||||||
|
|
||||||
|
//Do you have the following classes? Welding, Automotive and English?
|
||||||
|
fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
-Ralph
|
||||||
|
|
||||||
|
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/deckarep/golang-set/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
||||||
|
|
||||||
|
[![Analytics](https://ga-beacon.appspot.com/UA-42584447-2/deckarep/golang-set)](https://github.com/igrigorik/ga-beacon)
|
58
vendor/github.com/deckarep/golang-set/iterator.go
generated
vendored
Normal file
58
vendor/github.com/deckarep/golang-set/iterator.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
|
||||||
|
// elements.
|
||||||
|
type Iterator struct {
|
||||||
|
C <-chan interface{}
|
||||||
|
stop chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
|
||||||
|
func (i *Iterator) Stop() {
|
||||||
|
// Allows for Stop() to be called multiple times
|
||||||
|
// (close() panics when called on already closed channel)
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
}()
|
||||||
|
|
||||||
|
close(i.stop)
|
||||||
|
|
||||||
|
// Exhaust any remaining elements.
|
||||||
|
for range i.C {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIterator returns a new Iterator instance together with its item and stop channels.
|
||||||
|
func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
|
||||||
|
itemChan := make(chan interface{})
|
||||||
|
stopChan := make(chan struct{})
|
||||||
|
return &Iterator{
|
||||||
|
C: itemChan,
|
||||||
|
stop: stopChan,
|
||||||
|
}, itemChan, stopChan
|
||||||
|
}
|
217
vendor/github.com/deckarep/golang-set/set.go
generated
vendored
Normal file
217
vendor/github.com/deckarep/golang-set/set.go
generated
vendored
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package mapset implements a simple and generic set collection.
|
||||||
|
// Items stored within it are unordered and unique. It supports
|
||||||
|
// typical set operations: membership testing, intersection, union,
|
||||||
|
// difference, symmetric difference and cloning.
|
||||||
|
//
|
||||||
|
// Package mapset provides two implementations of the Set
|
||||||
|
// interface. The default implementation is safe for concurrent
|
||||||
|
// access, but a non-thread-safe implementation is also provided for
|
||||||
|
// programs that can benefit from the slight speed improvement and
|
||||||
|
// that can enforce mutual exclusion through other means.
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
// Set is the primary interface provided by the mapset package. It
|
||||||
|
// represents an unordered set of data and a large number of
|
||||||
|
// operations that can be applied to that set.
|
||||||
|
type Set interface {
|
||||||
|
// Adds an element to the set. Returns whether
|
||||||
|
// the item was added.
|
||||||
|
Add(i interface{}) bool
|
||||||
|
|
||||||
|
// Returns the number of elements in the set.
|
||||||
|
Cardinality() int
|
||||||
|
|
||||||
|
// Removes all elements from the set, leaving
|
||||||
|
// the empty set.
|
||||||
|
Clear()
|
||||||
|
|
||||||
|
// Returns a clone of the set using the same
|
||||||
|
// implementation, duplicating all keys.
|
||||||
|
Clone() Set
|
||||||
|
|
||||||
|
// Returns whether the given items
|
||||||
|
// are all in the set.
|
||||||
|
Contains(i ...interface{}) bool
|
||||||
|
|
||||||
|
// Returns the difference between this set
|
||||||
|
// and other. The returned set will contain
|
||||||
|
// all elements of this set that are not also
|
||||||
|
// elements of other.
|
||||||
|
//
|
||||||
|
// Note that the argument to Difference
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, Difference will
|
||||||
|
// panic.
|
||||||
|
Difference(other Set) Set
|
||||||
|
|
||||||
|
// Determines if two sets are equal to each
|
||||||
|
// other. If they have the same cardinality
|
||||||
|
// and contain the same elements, they are
|
||||||
|
// considered equal. The order in which
|
||||||
|
// the elements were added is irrelevant.
|
||||||
|
//
|
||||||
|
// Note that the argument to Equal must be
|
||||||
|
// of the same type as the receiver of the
|
||||||
|
// method. Otherwise, Equal will panic.
|
||||||
|
Equal(other Set) bool
|
||||||
|
|
||||||
|
// Returns a new set containing only the elements
|
||||||
|
// that exist only in both sets.
|
||||||
|
//
|
||||||
|
// Note that the argument to Intersect
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, Intersect will
|
||||||
|
// panic.
|
||||||
|
Intersect(other Set) Set
|
||||||
|
|
||||||
|
// Determines if every element in this set is in
|
||||||
|
// the other set but the two sets are not equal.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsProperSubset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsProperSubset
|
||||||
|
// will panic.
|
||||||
|
IsProperSubset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in the other set
|
||||||
|
// is in this set but the two sets are not
|
||||||
|
// equal.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSuperset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSuperset will
|
||||||
|
// panic.
|
||||||
|
IsProperSuperset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in this set is in
|
||||||
|
// the other set.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSubset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSubset will
|
||||||
|
// panic.
|
||||||
|
IsSubset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in the other set
|
||||||
|
// is in this set.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSuperset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSuperset will
|
||||||
|
// panic.
|
||||||
|
IsSuperset(other Set) bool
|
||||||
|
|
||||||
|
// Iterates over elements and executes the passed func against each element.
|
||||||
|
// If passed func returns true, stop iteration at the time.
|
||||||
|
Each(func(interface{}) bool)
|
||||||
|
|
||||||
|
// Returns a channel of elements that you can
|
||||||
|
// range over.
|
||||||
|
Iter() <-chan interface{}
|
||||||
|
|
||||||
|
// Returns an Iterator object that you can
|
||||||
|
// use to range over the set.
|
||||||
|
Iterator() *Iterator
|
||||||
|
|
||||||
|
// Remove a single element from the set.
|
||||||
|
Remove(i interface{})
|
||||||
|
|
||||||
|
// Provides a convenient string representation
|
||||||
|
// of the current state of the set.
|
||||||
|
String() string
|
||||||
|
|
||||||
|
// Returns a new set with all elements which are
|
||||||
|
// in either this set or the other set but not in both.
|
||||||
|
//
|
||||||
|
// Note that the argument to SymmetricDifference
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, SymmetricDifference
|
||||||
|
// will panic.
|
||||||
|
SymmetricDifference(other Set) Set
|
||||||
|
|
||||||
|
// Returns a new set with all elements in both sets.
|
||||||
|
//
|
||||||
|
// Note that the argument to Union must be of the
|
||||||
|
|
||||||
|
// same type as the receiver of the method.
|
||||||
|
// Otherwise, IsSuperset will panic.
|
||||||
|
Union(other Set) Set
|
||||||
|
|
||||||
|
// Pop removes and returns an arbitrary item from the set.
|
||||||
|
Pop() interface{}
|
||||||
|
|
||||||
|
// Returns all subsets of a given set (Power Set).
|
||||||
|
PowerSet() Set
|
||||||
|
|
||||||
|
// Returns the Cartesian Product of two sets.
|
||||||
|
CartesianProduct(other Set) Set
|
||||||
|
|
||||||
|
// Returns the members of the set as a slice.
|
||||||
|
ToSlice() []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSet creates and returns a reference to an empty set. Operations
|
||||||
|
// on the resulting set are thread-safe.
|
||||||
|
func NewSet(s ...interface{}) Set {
|
||||||
|
set := newThreadSafeSet()
|
||||||
|
for _, item := range s {
|
||||||
|
set.Add(item)
|
||||||
|
}
|
||||||
|
return &set
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetWith creates and returns a new set with the given elements.
|
||||||
|
// Operations on the resulting set are thread-safe.
|
||||||
|
func NewSetWith(elts ...interface{}) Set {
|
||||||
|
return NewSetFromSlice(elts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetFromSlice creates and returns a reference to a set from an
|
||||||
|
// existing slice. Operations on the resulting set are thread-safe.
|
||||||
|
func NewSetFromSlice(s []interface{}) Set {
|
||||||
|
a := NewSet(s...)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewThreadUnsafeSet creates and returns a reference to an empty set.
|
||||||
|
// Operations on the resulting set are not thread-safe.
|
||||||
|
func NewThreadUnsafeSet() Set {
|
||||||
|
set := newThreadUnsafeSet()
|
||||||
|
return &set
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
|
||||||
|
// set from an existing slice. Operations on the resulting set are
|
||||||
|
// not thread-safe.
|
||||||
|
func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
|
||||||
|
a := NewThreadUnsafeSet()
|
||||||
|
for _, item := range s {
|
||||||
|
a.Add(item)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
277
vendor/github.com/deckarep/golang-set/threadsafe.go
generated
vendored
Normal file
277
vendor/github.com/deckarep/golang-set/threadsafe.go
generated
vendored
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type threadSafeSet struct {
|
||||||
|
s threadUnsafeSet
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newThreadSafeSet() threadSafeSet {
|
||||||
|
return threadSafeSet{s: newThreadUnsafeSet()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Add(i interface{}) bool {
|
||||||
|
set.Lock()
|
||||||
|
ret := set.s.Add(i)
|
||||||
|
set.Unlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Contains(i ...interface{}) bool {
|
||||||
|
set.RLock()
|
||||||
|
ret := set.s.Contains(i...)
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsSubset(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
ret := set.s.IsSubset(&o.s)
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsProperSubset(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
defer set.RUnlock()
|
||||||
|
o.RLock()
|
||||||
|
defer o.RUnlock()
|
||||||
|
|
||||||
|
return set.s.IsProperSubset(&o.s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsSuperset(other Set) bool {
|
||||||
|
return other.IsSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsProperSuperset(other Set) bool {
|
||||||
|
return other.IsProperSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Union(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeUnion}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Intersect(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeIntersection}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Difference(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeDifference}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) SymmetricDifference(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeDifference}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Clear() {
|
||||||
|
set.Lock()
|
||||||
|
set.s = newThreadUnsafeSet()
|
||||||
|
set.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Remove(i interface{}) {
|
||||||
|
set.Lock()
|
||||||
|
delete(set.s, i)
|
||||||
|
set.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Cardinality() int {
|
||||||
|
set.RLock()
|
||||||
|
defer set.RUnlock()
|
||||||
|
return len(set.s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Each(cb func(interface{}) bool) {
|
||||||
|
set.RLock()
|
||||||
|
for elem := range set.s {
|
||||||
|
if cb(elem) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Iter() <-chan interface{} {
|
||||||
|
ch := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
set.RLock()
|
||||||
|
|
||||||
|
for elem := range set.s {
|
||||||
|
ch <- elem
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
set.RUnlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Iterator() *Iterator {
|
||||||
|
iterator, ch, stopCh := newIterator()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
set.RLock()
|
||||||
|
L:
|
||||||
|
for elem := range set.s {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
break L
|
||||||
|
case ch <- elem:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
set.RUnlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Equal(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
ret := set.s.Equal(&o.s)
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Clone() Set {
|
||||||
|
set.RLock()
|
||||||
|
|
||||||
|
unsafeClone := set.s.Clone().(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeClone}
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) String() string {
|
||||||
|
set.RLock()
|
||||||
|
ret := set.s.String()
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) PowerSet() Set {
|
||||||
|
set.RLock()
|
||||||
|
ret := set.s.PowerSet()
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Pop() interface{} {
|
||||||
|
set.Lock()
|
||||||
|
defer set.Unlock()
|
||||||
|
return set.s.Pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) CartesianProduct(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeCartProduct}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) ToSlice() []interface{} {
|
||||||
|
keys := make([]interface{}, 0, set.Cardinality())
|
||||||
|
set.RLock()
|
||||||
|
for elem := range set.s {
|
||||||
|
keys = append(keys, elem)
|
||||||
|
}
|
||||||
|
set.RUnlock()
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) MarshalJSON() ([]byte, error) {
|
||||||
|
set.RLock()
|
||||||
|
b, err := set.s.MarshalJSON()
|
||||||
|
set.RUnlock()
|
||||||
|
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) UnmarshalJSON(p []byte) error {
|
||||||
|
set.RLock()
|
||||||
|
err := set.s.UnmarshalJSON(p)
|
||||||
|
set.RUnlock()
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
337
vendor/github.com/deckarep/golang-set/threadunsafe.go
generated
vendored
Normal file
337
vendor/github.com/deckarep/golang-set/threadunsafe.go
generated
vendored
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type threadUnsafeSet map[interface{}]struct{}
|
||||||
|
|
||||||
|
// An OrderedPair represents a 2-tuple of values.
|
||||||
|
type OrderedPair struct {
|
||||||
|
First interface{}
|
||||||
|
Second interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newThreadUnsafeSet() threadUnsafeSet {
|
||||||
|
return make(threadUnsafeSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal says whether two 2-tuples contain the same values in the same order.
|
||||||
|
func (pair *OrderedPair) Equal(other OrderedPair) bool {
|
||||||
|
if pair.First == other.First &&
|
||||||
|
pair.Second == other.Second {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Add(i interface{}) bool {
|
||||||
|
_, found := (*set)[i]
|
||||||
|
if found {
|
||||||
|
return false //False if it existed already
|
||||||
|
}
|
||||||
|
|
||||||
|
(*set)[i] = struct{}{}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
|
||||||
|
for _, val := range i {
|
||||||
|
if _, ok := (*set)[val]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsSubset(other Set) bool {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsProperSubset(other Set) bool {
|
||||||
|
return set.IsSubset(other) && !set.Equal(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsSuperset(other Set) bool {
|
||||||
|
return other.IsSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsProperSuperset(other Set) bool {
|
||||||
|
return set.IsSuperset(other) && !set.Equal(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Union(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
unionedSet := newThreadUnsafeSet()
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
unionedSet.Add(elem)
|
||||||
|
}
|
||||||
|
for elem := range *o {
|
||||||
|
unionedSet.Add(elem)
|
||||||
|
}
|
||||||
|
return &unionedSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Intersect(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
intersection := newThreadUnsafeSet()
|
||||||
|
// loop over smaller set
|
||||||
|
if set.Cardinality() < other.Cardinality() {
|
||||||
|
for elem := range *set {
|
||||||
|
if other.Contains(elem) {
|
||||||
|
intersection.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for elem := range *o {
|
||||||
|
if set.Contains(elem) {
|
||||||
|
intersection.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &intersection
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Difference(other Set) Set {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
difference := newThreadUnsafeSet()
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
difference.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &difference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
aDiff := set.Difference(other)
|
||||||
|
bDiff := other.Difference(set)
|
||||||
|
return aDiff.Union(bDiff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Clear() {
|
||||||
|
*set = newThreadUnsafeSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Remove(i interface{}) {
|
||||||
|
delete(*set, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Cardinality() int {
|
||||||
|
return len(*set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Each(cb func(interface{}) bool) {
|
||||||
|
for elem := range *set {
|
||||||
|
if cb(elem) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Iter() <-chan interface{} {
|
||||||
|
ch := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
for elem := range *set {
|
||||||
|
ch <- elem
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Iterator() *Iterator {
|
||||||
|
iterator, ch, stopCh := newIterator()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
L:
|
||||||
|
for elem := range *set {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
break L
|
||||||
|
case ch <- elem:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Equal(other Set) bool {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
if set.Cardinality() != other.Cardinality() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Clone() Set {
|
||||||
|
clonedSet := newThreadUnsafeSet()
|
||||||
|
for elem := range *set {
|
||||||
|
clonedSet.Add(elem)
|
||||||
|
}
|
||||||
|
return &clonedSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) String() string {
|
||||||
|
items := make([]string, 0, len(*set))
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
items = append(items, fmt.Sprintf("%v", elem))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String outputs a 2-tuple in the form "(A, B)".
|
||||||
|
func (pair OrderedPair) String() string {
|
||||||
|
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Pop() interface{} {
|
||||||
|
for item := range *set {
|
||||||
|
delete(*set, item)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) PowerSet() Set {
|
||||||
|
powSet := NewThreadUnsafeSet()
|
||||||
|
nullset := newThreadUnsafeSet()
|
||||||
|
powSet.Add(&nullset)
|
||||||
|
|
||||||
|
for es := range *set {
|
||||||
|
u := newThreadUnsafeSet()
|
||||||
|
j := powSet.Iter()
|
||||||
|
for er := range j {
|
||||||
|
p := newThreadUnsafeSet()
|
||||||
|
if reflect.TypeOf(er).Name() == "" {
|
||||||
|
k := er.(*threadUnsafeSet)
|
||||||
|
for ek := range *(k) {
|
||||||
|
p.Add(ek)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.Add(er)
|
||||||
|
}
|
||||||
|
p.Add(es)
|
||||||
|
u.Add(&p)
|
||||||
|
}
|
||||||
|
|
||||||
|
powSet = powSet.Union(&u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return powSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
cartProduct := NewThreadUnsafeSet()
|
||||||
|
|
||||||
|
for i := range *set {
|
||||||
|
for j := range *o {
|
||||||
|
elem := OrderedPair{First: i, Second: j}
|
||||||
|
cartProduct.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cartProduct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) ToSlice() []interface{} {
|
||||||
|
keys := make([]interface{}, 0, set.Cardinality())
|
||||||
|
for elem := range *set {
|
||||||
|
keys = append(keys, elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON creates a JSON array from the set, it marshals all elements
|
||||||
|
func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
|
||||||
|
items := make([]string, 0, set.Cardinality())
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
b, err := json.Marshal(elem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
items = append(items, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON recreates a set from a JSON array, it only decodes
|
||||||
|
// primitive types. Numbers are decoded as json.Number.
|
||||||
|
func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
|
||||||
|
var i []interface{}
|
||||||
|
|
||||||
|
d := json.NewDecoder(bytes.NewReader(b))
|
||||||
|
d.UseNumber()
|
||||||
|
err := d.Decode(&i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range i {
|
||||||
|
switch t := v.(type) {
|
||||||
|
case []interface{}, map[string]interface{}:
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
set.Add(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
245
vendor/gopkg.in/fatih/set.v0/README.md
generated
vendored
245
vendor/gopkg.in/fatih/set.v0/README.md
generated
vendored
@ -1,245 +0,0 @@
|
|||||||
# Set [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/gopkg.in/fatih/set.v0) [![Build Status](http://img.shields.io/travis/fatih/set.svg?style=flat-square)](https://travis-ci.org/fatih/set)
|
|
||||||
|
|
||||||
Set is a basic and simple, hash-based, **Set** data structure implementation
|
|
||||||
in Go (Golang).
|
|
||||||
|
|
||||||
Set provides both threadsafe and non-threadsafe implementations of a generic
|
|
||||||
set data structure. The thread safety encompasses all operations on one set.
|
|
||||||
Operations on multiple sets are consistent in that the elements of each set
|
|
||||||
used was valid at exactly one point in time between the start and the end of
|
|
||||||
the operation. Because it's thread safe, you can use it concurrently with your
|
|
||||||
goroutines.
|
|
||||||
|
|
||||||
For usage see examples below or click on the godoc badge.
|
|
||||||
|
|
||||||
## Install and Usage
|
|
||||||
|
|
||||||
Install the package with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get gopkg.in/fatih/set.v0
|
|
||||||
```
|
|
||||||
|
|
||||||
Import it with:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import "gopkg.in/fatih/set.v0"
|
|
||||||
```
|
|
||||||
|
|
||||||
and use `set` as the package name inside the code.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
#### Initialization of a new Set
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
// create a set with zero items
|
|
||||||
s := set.New()
|
|
||||||
s := set.NewNonTS() // non thread-safe version
|
|
||||||
|
|
||||||
// ... or with some initial values
|
|
||||||
s := set.New("istanbul", "frankfurt", 30.123, "san francisco", 1234)
|
|
||||||
s := set.NewNonTS("kenya", "ethiopia", "sumatra")
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Basic Operations
|
|
||||||
|
|
||||||
```go
|
|
||||||
// add items
|
|
||||||
s.Add("istanbul")
|
|
||||||
s.Add("istanbul") // nothing happens if you add duplicate item
|
|
||||||
|
|
||||||
// add multiple items
|
|
||||||
s.Add("ankara", "san francisco", 3.14)
|
|
||||||
|
|
||||||
// remove item
|
|
||||||
s.Remove("frankfurt")
|
|
||||||
s.Remove("frankfurt") // nothing happes if you remove a nonexisting item
|
|
||||||
|
|
||||||
// remove multiple items
|
|
||||||
s.Remove("barcelona", 3.14, "ankara")
|
|
||||||
|
|
||||||
// removes an arbitary item and return it
|
|
||||||
item := s.Pop()
|
|
||||||
|
|
||||||
// create a new copy
|
|
||||||
other := s.Copy()
|
|
||||||
|
|
||||||
// remove all items
|
|
||||||
s.Clear()
|
|
||||||
|
|
||||||
// number of items in the set
|
|
||||||
len := s.Size()
|
|
||||||
|
|
||||||
// return a list of items
|
|
||||||
items := s.List()
|
|
||||||
|
|
||||||
// string representation of set
|
|
||||||
fmt.Printf("set is %s", s.String())
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Check Operations
|
|
||||||
|
|
||||||
```go
|
|
||||||
// check for set emptiness, returns true if set is empty
|
|
||||||
s.IsEmpty()
|
|
||||||
|
|
||||||
// check for a single item exist
|
|
||||||
s.Has("istanbul")
|
|
||||||
|
|
||||||
// ... or for multiple items. This will return true if all of the items exist.
|
|
||||||
s.Has("istanbul", "san francisco", 3.14)
|
|
||||||
|
|
||||||
// create two sets for the following checks...
|
|
||||||
s := s.New("1", "2", "3", "4", "5")
|
|
||||||
t := s.New("1", "2", "3")
|
|
||||||
|
|
||||||
|
|
||||||
// check if they are the same
|
|
||||||
if !s.IsEqual(t) {
|
|
||||||
fmt.Println("s is not equal to t")
|
|
||||||
}
|
|
||||||
|
|
||||||
// if s contains all elements of t
|
|
||||||
if s.IsSubset(t) {
|
|
||||||
fmt.Println("t is a subset of s")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... or if s is a superset of t
|
|
||||||
if t.IsSuperset(s) {
|
|
||||||
fmt.Println("s is a superset of t")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Set Operations
|
|
||||||
|
|
||||||
|
|
||||||
```go
|
|
||||||
// let us initialize two sets with some values
|
|
||||||
a := set.New("ankara", "berlin", "san francisco")
|
|
||||||
b := set.New("frankfurt", "berlin")
|
|
||||||
|
|
||||||
// creates a new set with the items in a and b combined.
|
|
||||||
// [frankfurt, berlin, ankara, san francisco]
|
|
||||||
c := set.Union(a, b)
|
|
||||||
|
|
||||||
// contains items which is in both a and b
|
|
||||||
// [berlin]
|
|
||||||
c := set.Intersection(a, b)
|
|
||||||
|
|
||||||
// contains items which are in a but not in b
|
|
||||||
// [ankara, san francisco]
|
|
||||||
c := set.Difference(a, b)
|
|
||||||
|
|
||||||
// contains items which are in one of either, but not in both.
|
|
||||||
// [frankfurt, ankara, san francisco]
|
|
||||||
c := set.SymmetricDifference(a, b)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
// like Union but saves the result back into a.
|
|
||||||
a.Merge(b)
|
|
||||||
|
|
||||||
// removes the set items which are in b from a and saves the result back into a.
|
|
||||||
a.Separate(b)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Multiple Set Operations
|
|
||||||
|
|
||||||
```go
|
|
||||||
a := set.New("1", "3", "4", "5")
|
|
||||||
b := set.New("2", "3", "4", "5")
|
|
||||||
c := set.New("4", "5", "6", "7")
|
|
||||||
|
|
||||||
// creates a new set with items in a, b and c
|
|
||||||
// [1 2 3 4 5 6 7]
|
|
||||||
u := set.Union(a, b, c)
|
|
||||||
|
|
||||||
// creates a new set with items in a but not in b and c
|
|
||||||
// [1]
|
|
||||||
u := set.Difference(a, b, c)
|
|
||||||
|
|
||||||
// creates a new set with items that are common to a, b and c
|
|
||||||
// [5]
|
|
||||||
u := set.Intersection(a, b, c)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Helper methods
|
|
||||||
|
|
||||||
The Slice functions below are a convenient way to extract or convert your Set data
|
|
||||||
into basic data types.
|
|
||||||
|
|
||||||
|
|
||||||
```go
|
|
||||||
// create a set of mixed types
|
|
||||||
s := set.New("ankara", "5", "8", "san francisco", 13, 21)
|
|
||||||
|
|
||||||
|
|
||||||
// convert s into a slice of strings (type is []string)
|
|
||||||
// [ankara 5 8 san francisco]
|
|
||||||
t := set.StringSlice(s)
|
|
||||||
|
|
||||||
|
|
||||||
// u contains a slice of ints (type is []int)
|
|
||||||
// [13, 21]
|
|
||||||
u := set.IntSlice(s)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Concurrent safe usage
|
|
||||||
|
|
||||||
Below is an example of a concurrent way that uses set. We call ten functions
|
|
||||||
concurrently and wait until they are finished. It basically creates a new
|
|
||||||
string for each goroutine and adds it to our set.
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/fatih/set"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var wg sync.WaitGroup // this is just for waiting until all goroutines finish
|
|
||||||
|
|
||||||
// Initialize our thread safe Set
|
|
||||||
s := set.New()
|
|
||||||
|
|
||||||
// Add items concurrently (item1, item2, and so on)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go func(i int) {
|
|
||||||
item := "item" + strconv.Itoa(i)
|
|
||||||
fmt.Println("adding", item)
|
|
||||||
s.Add(item)
|
|
||||||
wg.Done()
|
|
||||||
}(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until all concurrent calls finished and print our set
|
|
||||||
wg.Wait()
|
|
||||||
fmt.Println(s)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
* [Fatih Arslan](https://github.com/fatih)
|
|
||||||
* [Arne Hormann](https://github.com/arnehormann)
|
|
||||||
* [Sam Boyer](https://github.com/sdboyer)
|
|
||||||
* [Ralph Loizzo](https://github.com/friartech)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The MIT License (MIT) - see LICENSE.md for more details
|
|
||||||
|
|
121
vendor/gopkg.in/fatih/set.v0/set.go
generated
vendored
121
vendor/gopkg.in/fatih/set.v0/set.go
generated
vendored
@ -1,121 +0,0 @@
|
|||||||
// Package set provides both threadsafe and non-threadsafe implementations of
|
|
||||||
// a generic set data structure. In the threadsafe set, safety encompasses all
|
|
||||||
// operations on one set. Operations on multiple sets are consistent in that
|
|
||||||
// the elements of each set used was valid at exactly one point in time
|
|
||||||
// between the start and the end of the operation.
|
|
||||||
package set
|
|
||||||
|
|
||||||
// Interface is describing a Set. Sets are an unordered, unique list of values.
|
|
||||||
type Interface interface {
|
|
||||||
New(items ...interface{}) Interface
|
|
||||||
Add(items ...interface{})
|
|
||||||
Remove(items ...interface{})
|
|
||||||
Pop() interface{}
|
|
||||||
Has(items ...interface{}) bool
|
|
||||||
Size() int
|
|
||||||
Clear()
|
|
||||||
IsEmpty() bool
|
|
||||||
IsEqual(s Interface) bool
|
|
||||||
IsSubset(s Interface) bool
|
|
||||||
IsSuperset(s Interface) bool
|
|
||||||
Each(func(interface{}) bool)
|
|
||||||
String() string
|
|
||||||
List() []interface{}
|
|
||||||
Copy() Interface
|
|
||||||
Merge(s Interface)
|
|
||||||
Separate(s Interface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// helpful to not write everywhere struct{}{}
|
|
||||||
var keyExists = struct{}{}
|
|
||||||
|
|
||||||
// Union is the merger of multiple sets. It returns a new set with all the
|
|
||||||
// elements present in all the sets that are passed.
|
|
||||||
//
|
|
||||||
// The dynamic type of the returned set is determined by the first passed set's
|
|
||||||
// implementation of the New() method.
|
|
||||||
func Union(set1, set2 Interface, sets ...Interface) Interface {
|
|
||||||
u := set1.Copy()
|
|
||||||
set2.Each(func(item interface{}) bool {
|
|
||||||
u.Add(item)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
for _, set := range sets {
|
|
||||||
set.Each(func(item interface{}) bool {
|
|
||||||
u.Add(item)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
// Difference returns a new set which contains items which are in in the first
|
|
||||||
// set but not in the others. Unlike the Difference() method you can use this
|
|
||||||
// function separately with multiple sets.
|
|
||||||
func Difference(set1, set2 Interface, sets ...Interface) Interface {
|
|
||||||
s := set1.Copy()
|
|
||||||
s.Separate(set2)
|
|
||||||
for _, set := range sets {
|
|
||||||
s.Separate(set) // seperate is thread safe
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intersection returns a new set which contains items that only exist in all given sets.
|
|
||||||
func Intersection(set1, set2 Interface, sets ...Interface) Interface {
|
|
||||||
all := Union(set1, set2, sets...)
|
|
||||||
result := Union(set1, set2, sets...)
|
|
||||||
|
|
||||||
all.Each(func(item interface{}) bool {
|
|
||||||
if !set1.Has(item) || !set2.Has(item) {
|
|
||||||
result.Remove(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, set := range sets {
|
|
||||||
if !set.Has(item) {
|
|
||||||
result.Remove(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SymmetricDifference returns a new set which s is the difference of items which are in
|
|
||||||
// one of either, but not in both.
|
|
||||||
func SymmetricDifference(s Interface, t Interface) Interface {
|
|
||||||
u := Difference(s, t)
|
|
||||||
v := Difference(t, s)
|
|
||||||
return Union(u, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice is a helper function that returns a slice of strings of s. If
|
|
||||||
// the set contains mixed types of items only items of type string are returned.
|
|
||||||
func StringSlice(s Interface) []string {
|
|
||||||
slice := make([]string, 0)
|
|
||||||
for _, item := range s.List() {
|
|
||||||
v, ok := item.(string)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
slice = append(slice, v)
|
|
||||||
}
|
|
||||||
return slice
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSlice is a helper function that returns a slice of ints of s. If
|
|
||||||
// the set contains mixed types of items only items of type int are returned.
|
|
||||||
func IntSlice(s Interface) []int {
|
|
||||||
slice := make([]int, 0)
|
|
||||||
for _, item := range s.List() {
|
|
||||||
v, ok := item.(int)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
slice = append(slice, v)
|
|
||||||
}
|
|
||||||
return slice
|
|
||||||
}
|
|
195
vendor/gopkg.in/fatih/set.v0/set_nots.go
generated
vendored
195
vendor/gopkg.in/fatih/set.v0/set_nots.go
generated
vendored
@ -1,195 +0,0 @@
|
|||||||
package set
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Provides a common set baseline for both threadsafe and non-ts Sets.
|
|
||||||
type set struct {
|
|
||||||
m map[interface{}]struct{} // struct{} doesn't take up space
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNonTS defines a non-thread safe set data structure.
|
|
||||||
type SetNonTS struct {
|
|
||||||
set
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNonTS creates and initialize a new non-threadsafe Set.
|
|
||||||
// It accepts a variable number of arguments to populate the initial set.
|
|
||||||
// If nothing is passed a SetNonTS with zero size is created.
|
|
||||||
func NewNonTS(items ...interface{}) *SetNonTS {
|
|
||||||
s := &SetNonTS{}
|
|
||||||
s.m = make(map[interface{}]struct{})
|
|
||||||
|
|
||||||
// Ensure interface compliance
|
|
||||||
var _ Interface = s
|
|
||||||
|
|
||||||
s.Add(items...)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initalizes a new Set interface. It accepts a variable
|
|
||||||
// number of arguments to populate the initial set. If nothing is passed a
|
|
||||||
// zero size Set based on the struct is created.
|
|
||||||
func (s *set) New(items ...interface{}) Interface {
|
|
||||||
return NewNonTS(items...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add includes the specified items (one or more) to the set. The underlying
|
|
||||||
// Set s is modified. If passed nothing it silently returns.
|
|
||||||
func (s *set) Add(items ...interface{}) {
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range items {
|
|
||||||
s.m[item] = keyExists
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove deletes the specified items from the set. The underlying Set s is
|
|
||||||
// modified. If passed nothing it silently returns.
|
|
||||||
func (s *set) Remove(items ...interface{}) {
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range items {
|
|
||||||
delete(s.m, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop deletes and return an item from the set. The underlying Set s is
|
|
||||||
// modified. If set is empty, nil is returned.
|
|
||||||
func (s *set) Pop() interface{} {
|
|
||||||
for item := range s.m {
|
|
||||||
delete(s.m, item)
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has looks for the existence of items passed. It returns false if nothing is
|
|
||||||
// passed. For multiple items it returns true only if all of the items exist.
|
|
||||||
func (s *set) Has(items ...interface{}) bool {
|
|
||||||
// assume checked for empty item, which not exist
|
|
||||||
if len(items) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
has := true
|
|
||||||
for _, item := range items {
|
|
||||||
if _, has = s.m[item]; !has {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the number of items in a set.
|
|
||||||
func (s *set) Size() int {
|
|
||||||
return len(s.m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear removes all items from the set.
|
|
||||||
func (s *set) Clear() {
|
|
||||||
s.m = make(map[interface{}]struct{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmpty reports whether the Set is empty.
|
|
||||||
func (s *set) IsEmpty() bool {
|
|
||||||
return s.Size() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEqual test whether s and t are the same in size and have the same items.
|
|
||||||
func (s *set) IsEqual(t Interface) bool {
|
|
||||||
// Force locking only if given set is threadsafe.
|
|
||||||
if conv, ok := t.(*Set); ok {
|
|
||||||
conv.l.RLock()
|
|
||||||
defer conv.l.RUnlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// return false if they are no the same size
|
|
||||||
if sameSize := len(s.m) == t.Size(); !sameSize {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
equal := true
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
_, equal = s.m[item]
|
|
||||||
return equal // if false, Each() will end
|
|
||||||
})
|
|
||||||
|
|
||||||
return equal
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSubset tests whether t is a subset of s.
|
|
||||||
func (s *set) IsSubset(t Interface) (subset bool) {
|
|
||||||
subset = true
|
|
||||||
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
_, subset = s.m[item]
|
|
||||||
return subset
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSuperset tests whether t is a superset of s.
|
|
||||||
func (s *set) IsSuperset(t Interface) bool {
|
|
||||||
return t.IsSubset(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each traverses the items in the Set, calling the provided function for each
|
|
||||||
// set member. Traversal will continue until all items in the Set have been
|
|
||||||
// visited, or if the closure returns false.
|
|
||||||
func (s *set) Each(f func(item interface{}) bool) {
|
|
||||||
for item := range s.m {
|
|
||||||
if !f(item) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a string representation of s
|
|
||||||
func (s *set) String() string {
|
|
||||||
t := make([]string, 0, len(s.List()))
|
|
||||||
for _, item := range s.List() {
|
|
||||||
t = append(t, fmt.Sprintf("%v", item))
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("[%s]", strings.Join(t, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a slice of all items. There is also StringSlice() and
|
|
||||||
// IntSlice() methods for returning slices of type string or int.
|
|
||||||
func (s *set) List() []interface{} {
|
|
||||||
list := make([]interface{}, 0, len(s.m))
|
|
||||||
|
|
||||||
for item := range s.m {
|
|
||||||
list = append(list, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy returns a new Set with a copy of s.
|
|
||||||
func (s *set) Copy() Interface {
|
|
||||||
return NewNonTS(s.List()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge is like Union, however it modifies the current set it's applied on
|
|
||||||
// with the given t set.
|
|
||||||
func (s *set) Merge(t Interface) {
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
s.m[item] = keyExists
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's not the opposite of Merge.
|
|
||||||
// Separate removes the set items containing in t from set s. Please aware that
|
|
||||||
func (s *set) Separate(t Interface) {
|
|
||||||
s.Remove(t.List()...)
|
|
||||||
}
|
|
200
vendor/gopkg.in/fatih/set.v0/set_ts.go
generated
vendored
200
vendor/gopkg.in/fatih/set.v0/set_ts.go
generated
vendored
@ -1,200 +0,0 @@
|
|||||||
package set
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set defines a thread safe set data structure.
|
|
||||||
type Set struct {
|
|
||||||
set
|
|
||||||
l sync.RWMutex // we name it because we don't want to expose it
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initialize a new Set. It's accept a variable number of
|
|
||||||
// arguments to populate the initial set. If nothing passed a Set with zero
|
|
||||||
// size is created.
|
|
||||||
func New(items ...interface{}) *Set {
|
|
||||||
s := &Set{}
|
|
||||||
s.m = make(map[interface{}]struct{})
|
|
||||||
|
|
||||||
// Ensure interface compliance
|
|
||||||
var _ Interface = s
|
|
||||||
|
|
||||||
s.Add(items...)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates and initalizes a new Set interface. It accepts a variable
|
|
||||||
// number of arguments to populate the initial set. If nothing is passed a
|
|
||||||
// zero size Set based on the struct is created.
|
|
||||||
func (s *Set) New(items ...interface{}) Interface {
|
|
||||||
return New(items...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add includes the specified items (one or more) to the set. The underlying
|
|
||||||
// Set s is modified. If passed nothing it silently returns.
|
|
||||||
func (s *Set) Add(items ...interface{}) {
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.l.Lock()
|
|
||||||
defer s.l.Unlock()
|
|
||||||
|
|
||||||
for _, item := range items {
|
|
||||||
s.m[item] = keyExists
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove deletes the specified items from the set. The underlying Set s is
|
|
||||||
// modified. If passed nothing it silently returns.
|
|
||||||
func (s *Set) Remove(items ...interface{}) {
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.l.Lock()
|
|
||||||
defer s.l.Unlock()
|
|
||||||
|
|
||||||
for _, item := range items {
|
|
||||||
delete(s.m, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop deletes and return an item from the set. The underlying Set s is
|
|
||||||
// modified. If set is empty, nil is returned.
|
|
||||||
func (s *Set) Pop() interface{} {
|
|
||||||
s.l.RLock()
|
|
||||||
for item := range s.m {
|
|
||||||
s.l.RUnlock()
|
|
||||||
s.l.Lock()
|
|
||||||
delete(s.m, item)
|
|
||||||
s.l.Unlock()
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
s.l.RUnlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has looks for the existence of items passed. It returns false if nothing is
|
|
||||||
// passed. For multiple items it returns true only if all of the items exist.
|
|
||||||
func (s *Set) Has(items ...interface{}) bool {
|
|
||||||
// assume checked for empty item, which not exist
|
|
||||||
if len(items) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
has := true
|
|
||||||
for _, item := range items {
|
|
||||||
if _, has = s.m[item]; !has {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the number of items in a set.
|
|
||||||
func (s *Set) Size() int {
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
l := len(s.m)
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear removes all items from the set.
|
|
||||||
func (s *Set) Clear() {
|
|
||||||
s.l.Lock()
|
|
||||||
defer s.l.Unlock()
|
|
||||||
|
|
||||||
s.m = make(map[interface{}]struct{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEqual test whether s and t are the same in size and have the same items.
|
|
||||||
func (s *Set) IsEqual(t Interface) bool {
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
// Force locking only if given set is threadsafe.
|
|
||||||
if conv, ok := t.(*Set); ok {
|
|
||||||
conv.l.RLock()
|
|
||||||
defer conv.l.RUnlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// return false if they are no the same size
|
|
||||||
if sameSize := len(s.m) == t.Size(); !sameSize {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
equal := true
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
_, equal = s.m[item]
|
|
||||||
return equal // if false, Each() will end
|
|
||||||
})
|
|
||||||
|
|
||||||
return equal
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSubset tests whether t is a subset of s.
|
|
||||||
func (s *Set) IsSubset(t Interface) (subset bool) {
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
subset = true
|
|
||||||
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
_, subset = s.m[item]
|
|
||||||
return subset
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each traverses the items in the Set, calling the provided function for each
|
|
||||||
// set member. Traversal will continue until all items in the Set have been
|
|
||||||
// visited, or if the closure returns false.
|
|
||||||
func (s *Set) Each(f func(item interface{}) bool) {
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
for item := range s.m {
|
|
||||||
if !f(item) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a slice of all items. There is also StringSlice() and
|
|
||||||
// IntSlice() methods for returning slices of type string or int.
|
|
||||||
func (s *Set) List() []interface{} {
|
|
||||||
s.l.RLock()
|
|
||||||
defer s.l.RUnlock()
|
|
||||||
|
|
||||||
list := make([]interface{}, 0, len(s.m))
|
|
||||||
|
|
||||||
for item := range s.m {
|
|
||||||
list = append(list, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy returns a new Set with a copy of s.
|
|
||||||
func (s *Set) Copy() Interface {
|
|
||||||
return New(s.List()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge is like Union, however it modifies the current set it's applied on
|
|
||||||
// with the given t set.
|
|
||||||
func (s *Set) Merge(t Interface) {
|
|
||||||
s.l.Lock()
|
|
||||||
defer s.l.Unlock()
|
|
||||||
|
|
||||||
t.Each(func(item interface{}) bool {
|
|
||||||
s.m[item] = keyExists
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
12
vendor/vendor.json
vendored
12
vendor/vendor.json
vendored
@ -80,6 +80,12 @@
|
|||||||
"revision": "346938d642f2ec3594ed81d874461961cd0faa76",
|
"revision": "346938d642f2ec3594ed81d874461961cd0faa76",
|
||||||
"revisionTime": "2016-10-29T20:57:26Z"
|
"revisionTime": "2016-10-29T20:57:26Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "1xK7ycc1ICRInk/S9iiyB9Rpv50=",
|
||||||
|
"path": "github.com/deckarep/golang-set",
|
||||||
|
"revision": "504e848d77ea4752b3057b8fb46da0e7f746ccf3",
|
||||||
|
"revisionTime": "2018-06-03T19:32:48Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "2Fy1Y6Z3lRRX1891WF/+HT4XS2I=",
|
"checksumSHA1": "2Fy1Y6Z3lRRX1891WF/+HT4XS2I=",
|
||||||
"path": "github.com/dgrijalva/jwt-go",
|
"path": "github.com/dgrijalva/jwt-go",
|
||||||
@ -891,12 +897,6 @@
|
|||||||
"revision": "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
|
"revision": "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
|
||||||
"revisionTime": "2016-12-08T18:13:25Z"
|
"revisionTime": "2016-12-08T18:13:25Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "NGg7/qIJVUfXi7xnEyyDLocdi6Y=",
|
|
||||||
"path": "gopkg.in/fatih/set.v0",
|
|
||||||
"revision": "27c40922c40b43fe04554d8223a402af3ea333f3",
|
|
||||||
"revisionTime": "2014-12-10T08:48:24Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "DQXNV0EivoHm4q+bkdahYXrjjfE=",
|
"checksumSHA1": "DQXNV0EivoHm4q+bkdahYXrjjfE=",
|
||||||
"path": "gopkg.in/karalabe/cookiejar.v2/collections/prque",
|
"path": "gopkg.in/karalabe/cookiejar.v2/collections/prque",
|
||||||
|
@ -20,11 +20,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Peer represents a whisper protocol peer connection.
|
// Peer represents a whisper protocol peer connection.
|
||||||
@ -34,7 +34,7 @@ type Peer struct {
|
|||||||
ws p2p.MsgReadWriter
|
ws p2p.MsgReadWriter
|
||||||
trusted bool
|
trusted bool
|
||||||
|
|
||||||
known *set.Set // Messages already known by the peer to avoid wasting bandwidth
|
known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
|
|||||||
peer: remote,
|
peer: remote,
|
||||||
ws: rw,
|
ws: rw,
|
||||||
trusted: false,
|
trusted: false,
|
||||||
known: set.New(),
|
known: mapset.NewSet(),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ func (peer *Peer) mark(envelope *Envelope) {
|
|||||||
|
|
||||||
// marked checks if an envelope is already known to the remote peer.
|
// marked checks if an envelope is already known to the remote peer.
|
||||||
func (peer *Peer) marked(envelope *Envelope) bool {
|
func (peer *Peer) marked(envelope *Envelope) bool {
|
||||||
return peer.known.Has(envelope.Hash())
|
return peer.known.Contains(envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// expire iterates over all the known envelopes in the host and removes all
|
// expire iterates over all the known envelopes in the host and removes all
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
@ -34,7 +35,6 @@ import (
|
|||||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
"golang.org/x/sync/syncmap"
|
"golang.org/x/sync/syncmap"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Statistics struct {
|
type Statistics struct {
|
||||||
@ -63,7 +63,7 @@ type Whisper struct {
|
|||||||
|
|
||||||
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
||||||
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
||||||
expirations map[uint32]*set.SetNonTS // Message expiration pool
|
expirations map[uint32]mapset.Set // Message expiration pool
|
||||||
|
|
||||||
peerMu sync.RWMutex // Mutex to sync the active peer set
|
peerMu sync.RWMutex // Mutex to sync the active peer set
|
||||||
peers map[*Peer]struct{} // Set of currently active peers
|
peers map[*Peer]struct{} // Set of currently active peers
|
||||||
@ -90,7 +90,7 @@ func New(cfg *Config) *Whisper {
|
|||||||
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
||||||
symKeys: make(map[string][]byte),
|
symKeys: make(map[string][]byte),
|
||||||
envelopes: make(map[common.Hash]*Envelope),
|
envelopes: make(map[common.Hash]*Envelope),
|
||||||
expirations: make(map[uint32]*set.SetNonTS),
|
expirations: make(map[uint32]mapset.Set),
|
||||||
peers: make(map[*Peer]struct{}),
|
peers: make(map[*Peer]struct{}),
|
||||||
messageQueue: make(chan *Envelope, messageQueueLimit),
|
messageQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
@ -608,9 +608,9 @@ func (w *Whisper) add(envelope *Envelope) (bool, error) {
|
|||||||
if !alreadyCached {
|
if !alreadyCached {
|
||||||
w.envelopes[hash] = envelope
|
w.envelopes[hash] = envelope
|
||||||
if w.expirations[envelope.Expiry] == nil {
|
if w.expirations[envelope.Expiry] == nil {
|
||||||
w.expirations[envelope.Expiry] = set.NewNonTS()
|
w.expirations[envelope.Expiry] = mapset.NewThreadUnsafeSet()
|
||||||
}
|
}
|
||||||
if !w.expirations[envelope.Expiry].Has(hash) {
|
if !w.expirations[envelope.Expiry].Contains(hash) {
|
||||||
w.expirations[envelope.Expiry].Add(hash)
|
w.expirations[envelope.Expiry].Add(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
|
func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
|
||||||
@ -31,7 +31,7 @@ func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
|
|||||||
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
||||||
symKeys: make(map[string][]byte),
|
symKeys: make(map[string][]byte),
|
||||||
envelopes: make(map[common.Hash]*Envelope),
|
envelopes: make(map[common.Hash]*Envelope),
|
||||||
expirations: make(map[uint32]*set.SetNonTS),
|
expirations: make(map[uint32]mapset.Set),
|
||||||
peers: make(map[*Peer]struct{}),
|
peers: make(map[*Peer]struct{}),
|
||||||
messageQueue: make(chan *Envelope, messageQueueLimit),
|
messageQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
|
@ -22,11 +22,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Peer represents a whisper protocol peer connection.
|
// Peer represents a whisper protocol peer connection.
|
||||||
@ -41,7 +41,7 @@ type Peer struct {
|
|||||||
bloomFilter []byte
|
bloomFilter []byte
|
||||||
fullNode bool
|
fullNode bool
|
||||||
|
|
||||||
known *set.Set // Messages already known by the peer to avoid wasting bandwidth
|
known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
|
|||||||
ws: rw,
|
ws: rw,
|
||||||
trusted: false,
|
trusted: false,
|
||||||
powRequirement: 0.0,
|
powRequirement: 0.0,
|
||||||
known: set.New(),
|
known: mapset.NewSet(),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
bloomFilter: MakeFullNodeBloom(),
|
bloomFilter: MakeFullNodeBloom(),
|
||||||
fullNode: true,
|
fullNode: true,
|
||||||
@ -165,7 +165,7 @@ func (peer *Peer) mark(envelope *Envelope) {
|
|||||||
|
|
||||||
// marked checks if an envelope is already known to the remote peer.
|
// marked checks if an envelope is already known to the remote peer.
|
||||||
func (peer *Peer) marked(envelope *Envelope) bool {
|
func (peer *Peer) marked(envelope *Envelope) bool {
|
||||||
return peer.known.Has(envelope.Hash())
|
return peer.known.Contains(envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// expire iterates over all the known envelopes in the host and removes all
|
// expire iterates over all the known envelopes in the host and removes all
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
@ -35,7 +36,6 @@ import (
|
|||||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
"golang.org/x/sync/syncmap"
|
"golang.org/x/sync/syncmap"
|
||||||
set "gopkg.in/fatih/set.v0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Statistics holds several message-related counter for analytics
|
// Statistics holds several message-related counter for analytics
|
||||||
@ -69,7 +69,7 @@ type Whisper struct {
|
|||||||
|
|
||||||
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
poolMu sync.RWMutex // Mutex to sync the message and expiration pools
|
||||||
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node
|
||||||
expirations map[uint32]*set.SetNonTS // Message expiration pool
|
expirations map[uint32]mapset.Set // Message expiration pool
|
||||||
|
|
||||||
peerMu sync.RWMutex // Mutex to sync the active peer set
|
peerMu sync.RWMutex // Mutex to sync the active peer set
|
||||||
peers map[*Peer]struct{} // Set of currently active peers
|
peers map[*Peer]struct{} // Set of currently active peers
|
||||||
@ -100,7 +100,7 @@ func New(cfg *Config) *Whisper {
|
|||||||
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
privateKeys: make(map[string]*ecdsa.PrivateKey),
|
||||||
symKeys: make(map[string][]byte),
|
symKeys: make(map[string][]byte),
|
||||||
envelopes: make(map[common.Hash]*Envelope),
|
envelopes: make(map[common.Hash]*Envelope),
|
||||||
expirations: make(map[uint32]*set.SetNonTS),
|
expirations: make(map[uint32]mapset.Set),
|
||||||
peers: make(map[*Peer]struct{}),
|
peers: make(map[*Peer]struct{}),
|
||||||
messageQueue: make(chan *Envelope, messageQueueLimit),
|
messageQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
|
||||||
@ -796,9 +796,9 @@ func (whisper *Whisper) add(envelope *Envelope, isP2P bool) (bool, error) {
|
|||||||
if !alreadyCached {
|
if !alreadyCached {
|
||||||
whisper.envelopes[hash] = envelope
|
whisper.envelopes[hash] = envelope
|
||||||
if whisper.expirations[envelope.Expiry] == nil {
|
if whisper.expirations[envelope.Expiry] == nil {
|
||||||
whisper.expirations[envelope.Expiry] = set.NewNonTS()
|
whisper.expirations[envelope.Expiry] = mapset.NewThreadUnsafeSet()
|
||||||
}
|
}
|
||||||
if !whisper.expirations[envelope.Expiry].Has(hash) {
|
if !whisper.expirations[envelope.Expiry].Contains(hash) {
|
||||||
whisper.expirations[envelope.Expiry].Add(hash)
|
whisper.expirations[envelope.Expiry].Add(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user