Consume ring buffer for networks added on-the-fly
This commit is contained in:
parent
293a0e8e20
commit
21241c2009
106
downstream.go
106
downstream.go
@ -702,58 +702,70 @@ func (dc *downstreamConn) register() error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
dc.forEachNetwork(func(net *network) {
|
dc.forEachNetwork(func(net *network) {
|
||||||
historyName := dc.rawUsername
|
// TODO: need to take dc.network into account when deciding whether or
|
||||||
|
// not to load history
|
||||||
// TODO: need to take dc.network into account here
|
dc.runNetwork(net, firstDownstream)
|
||||||
var seqPtr *uint64
|
|
||||||
if firstDownstream {
|
|
||||||
net.lock.Lock()
|
|
||||||
seq, ok := net.history[historyName]
|
|
||||||
net.lock.Unlock()
|
|
||||||
if ok {
|
|
||||||
seqPtr = &seq
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: we need to create a consumer when adding networks on-the-fly
|
|
||||||
consumer, ch := net.ring.NewConsumer(seqPtr)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
var closed bool
|
|
||||||
select {
|
|
||||||
case <-ch:
|
|
||||||
uc := net.upstream()
|
|
||||||
if uc == nil {
|
|
||||||
dc.logger.Printf("ignoring messages for upstream %q: upstream is disconnected", net.Addr)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dc.ringMessages <- ringMessage{consumer, uc}
|
|
||||||
case <-dc.closed:
|
|
||||||
closed = true
|
|
||||||
}
|
|
||||||
if closed {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seq := consumer.Close()
|
|
||||||
|
|
||||||
// TODO: need to take dc.network into account here
|
|
||||||
dc.user.lock.Lock()
|
|
||||||
lastDownstream := len(dc.user.downstreamConns) == 0
|
|
||||||
dc.user.lock.Unlock()
|
|
||||||
|
|
||||||
if lastDownstream {
|
|
||||||
net.lock.Lock()
|
|
||||||
net.history[historyName] = seq
|
|
||||||
net.lock.Unlock()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runNetwork starts listening for messages coming from the network's ring
|
||||||
|
// buffer.
|
||||||
|
//
|
||||||
|
// It panics if the network is not suitable for the downstream connection.
|
||||||
|
func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
|
||||||
|
if dc.network != nil && net != dc.network {
|
||||||
|
panic("network not suitable for downstream connection")
|
||||||
|
}
|
||||||
|
|
||||||
|
historyName := dc.rawUsername
|
||||||
|
|
||||||
|
var seqPtr *uint64
|
||||||
|
if loadHistory {
|
||||||
|
net.lock.Lock()
|
||||||
|
seq, ok := net.history[historyName]
|
||||||
|
net.lock.Unlock()
|
||||||
|
if ok {
|
||||||
|
seqPtr = &seq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
consumer, ch := net.ring.NewConsumer(seqPtr)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
var closed bool
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
uc := net.upstream()
|
||||||
|
if uc == nil {
|
||||||
|
dc.logger.Printf("ignoring messages for upstream %q: upstream is disconnected", net.Addr)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dc.ringMessages <- ringMessage{consumer, uc}
|
||||||
|
case <-dc.closed:
|
||||||
|
closed = true
|
||||||
|
}
|
||||||
|
if closed {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seq := consumer.Close()
|
||||||
|
|
||||||
|
// TODO: need to take dc.network into account here
|
||||||
|
dc.user.lock.Lock()
|
||||||
|
lastDownstream := len(dc.user.downstreamConns) == 0
|
||||||
|
dc.user.lock.Unlock()
|
||||||
|
|
||||||
|
if lastDownstream {
|
||||||
|
net.lock.Lock()
|
||||||
|
net.history[historyName] = seq
|
||||||
|
net.lock.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
func (dc *downstreamConn) runUntilRegistered() error {
|
func (dc *downstreamConn) runUntilRegistered() error {
|
||||||
for !dc.registered {
|
for !dc.registered {
|
||||||
msg, err := dc.irc.ReadMessage()
|
msg, err := dc.irc.ReadMessage()
|
||||||
|
12
user.go
12
user.go
@ -198,14 +198,26 @@ func (u *user) removeDownstream(dc *downstreamConn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *user) createNetwork(net *Network) (*network, error) {
|
func (u *user) createNetwork(net *Network) (*network, error) {
|
||||||
|
if net.ID != 0 {
|
||||||
|
panic("tried creating an already-existing network")
|
||||||
|
}
|
||||||
|
|
||||||
network := newNetwork(u, net)
|
network := newNetwork(u, net)
|
||||||
err := u.srv.db.StoreNetwork(u.Username, &network.Network)
|
err := u.srv.db.StoreNetwork(u.Username, &network.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.forEachDownstream(func(dc *downstreamConn) {
|
||||||
|
if dc.network == nil {
|
||||||
|
dc.runNetwork(network, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
u.lock.Lock()
|
u.lock.Lock()
|
||||||
u.networks = append(u.networks, network)
|
u.networks = append(u.networks, network)
|
||||||
u.lock.Unlock()
|
u.lock.Unlock()
|
||||||
|
|
||||||
go network.run()
|
go network.run()
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user