本文整理汇总了Golang中minilog.WillLog函数的典型用法代码示例。如果您正苦于以下问题:Golang WillLog函数的具体用法?Golang WillLog怎么用?Golang WillLog使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了WillLog函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: updateRoute
// find and record the next hop route for c.
// Additionally, all hops along this route are also the shortest path, so
// record those as well to save on effort.
func (n *Node) updateRoute(c string) {
if len(n.effectiveNetwork) == 0 {
return
}
if log.WillLog(log.DEBUG) {
log.Debug("updating route for %v", c)
}
routes := make(map[string]string) // a key node has a value of the previous hop, the key exists if it's been visited
routes[n.name] = n.name // the route to ourself is pretty easy to calculate
// dijkstra's algorithm is well suited in go - we can use a buffered
// channel of nodes to order our search. We start by putting ourselves
// in the queue (channel) and follow all nodes connected to it. If we
// haven't visited that node before, it goes in the queue.
q := make(chan string, len(n.effectiveNetwork))
q <- n.name
for len(q) != 0 {
v := <-q
if log.WillLog(log.DEBUG) {
log.Debug("visiting %v", v)
}
for _, a := range n.effectiveNetwork[v] {
if _, ok := routes[a]; !ok {
q <- a
if log.WillLog(log.DEBUG) {
log.Debug("previous hop for %v is %v", a, v)
}
routes[a] = v // this is the route to node a from v
}
}
if v == c {
break
}
}
for k, v := range routes {
curr := v
prev := k
r := k
if curr == n.name {
r += "<-" + routes[curr]
}
for curr != n.name {
prev = curr
curr = routes[curr]
r += "<-" + routes[curr]
}
if log.WillLog(log.DEBUG) {
log.Debug("full route for %v is %v", k, r)
}
n.routes[k] = prev
}
}
示例2: Send
// Send a message according to the parameters set in the message.
// Users will generally use the Set and Broadcast functions instead of Send.
// The returned error is always nil if the message type is broadcast.
// If an error is encountered, Send returns immediately.
func (n *Node) Send(m *Message) ([]string, error) {
if log.WillLog(log.DEBUG) {
log.Debug("Send: %v", m)
}
// force updating the network if needed on Send()
n.checkUpdateNetwork()
routeSlices, err := n.getRoutes(m)
if err != nil {
return nil, err
}
if log.WillLog(log.DEBUG) {
log.Debug("routeSlices: %v", routeSlices)
}
errChan := make(chan error)
for k, v := range routeSlices {
go func(client string, recipients []string) {
mOne := &Message{
Recipients: recipients,
Source: m.Source,
CurrentRoute: m.CurrentRoute,
Command: m.Command,
Body: m.Body,
}
err := n.clientSend(client, mOne)
if err != nil {
errChan <- err
} else {
errChan <- nil
}
}(k, v)
}
// wait on all of the client sends to complete
var ret string
for i := 0; i < len(routeSlices); i++ {
r := <-errChan
if r != nil {
ret += r.Error() + "\n"
}
}
// Rebuild the recipients from the routeSlices so that the caller can know
// which recipients were actually valid.
recipients := []string{}
for _, r := range routeSlices {
recipients = append(recipients, r...)
}
if ret == "" {
return recipients, nil
}
return recipients, errors.New(ret)
}
示例3: generateEffectiveNetwork
// generateEffectiveNetwork returns the subset of the current known topology that contains
// pairs of known connections. That is, if node A says it's connected to node B
// but node B does not say it's connected to node A, then that connection will
// not be listed in the effective mesh list.
// generateEffectiveNetwork expects to be called with meshLock obtained.
func (n *Node) generateEffectiveNetwork() {
log.Debugln("generateEffectiveNetwork")
for {
emesh := make(mesh)
for k, v := range n.network {
effectiveNetworkLoop:
for _, i := range v { // for each connection i to node k, see if i also reports being connected to k
for _, j := range emesh[i] { // do we already have this connection noted? if so, move on. This should happen zero or one times for each node.
if j == k {
continue effectiveNetworkLoop
}
}
for _, j := range n.network[i] { // go through all of node i's connections looking for k
if j == k {
if log.WillLog(log.DEBUG) {
log.Debug("found pair %v <-> %v", k, i)
}
// note the connection in the adjacency list for both i and k
emesh[k] = append(emesh[k], i)
emesh[i] = append(emesh[i], k)
break
}
}
}
}
n.effectiveNetwork = emesh
// now generate routes to each of the nodes from us based on the effectiveNetwork
n.routes = make(map[string]string)
// attempt to learn routes to each node from this node,
// assuming that all nodes in the effective network are
// routable. It's possible that the effective network
// represents partitioned meshes, so if we cannot find a route
// to a node, remove it from the known network and start this
// entire process over.
stable := true
for h, _ := range n.effectiveNetwork {
if _, ok := n.routes[h]; !ok {
n.updateRoute(h)
if _, ok := n.routes[h]; !ok {
log.Debug("removing unroutable node %v", h)
delete(n.network, h)
stable = false
}
}
}
if stable {
break
}
}
if log.WillLog(log.DEBUG) {
log.Debug("new effectiveNetwork: %v", n.effectiveNetwork)
}
}
示例4: Xfer
// Transfer a single filepart to a temporary transfer directory.
func (iom *IOMeshage) Xfer(filename string, part int64, from string) error {
TID := genTID()
c := make(chan *IOMMessage)
err := iom.registerTID(TID, c)
defer iom.unregisterTID(TID)
if err != nil {
// a collision in int64, we should tell someone about this
log.Fatalln(err)
}
m := &IOMMessage{
From: iom.node.Name(),
Type: TYPE_XFER,
Filename: filename,
TID: TID,
Part: part,
}
_, err = iom.node.Set([]string{from}, m)
if err != nil {
return err
}
// wait for a response, or a timeout
select {
case resp := <-c:
if log.WillLog(log.DEBUG) {
log.Debugln("got part: ", resp.Part)
}
if resp.ACK {
if log.WillLog(log.DEBUG) {
log.Debugln("got part from: ", resp.From)
}
// write the part out to disk
iom.transferLock.RLock()
defer iom.transferLock.RUnlock()
if t, ok := iom.transfers[filename]; ok {
outfile := fmt.Sprintf("%v/%v.part_%v", t.Dir, filepath.Base(filename), part)
err := ioutil.WriteFile(outfile, resp.Data, 0664)
if err != nil {
return err
}
} else {
return fmt.Errorf("no transfer temporary directory to write to!")
}
} else {
return fmt.Errorf("received NACK from xfer node")
}
case <-time.After(timeout):
return fmt.Errorf("timeout")
}
return nil
}
示例5: handleMSA
func (n *Node) handleMSA(m *Message) {
log.Debug("handleMSA: %v", m)
n.meshLock.Lock()
defer n.meshLock.Unlock()
if len(n.network[m.Source]) == len(m.Body.([]string)) {
diff := false
for i, v := range n.network[m.Source] {
if m.Body.([]string)[i] != v {
diff = true
break
}
}
if !diff {
log.Debugln("MSA discarded, client data hasn't changed")
return
}
}
n.network[m.Source] = m.Body.([]string)
if log.WillLog(log.DEBUG) {
log.Debug("new network is: %v", n.network)
}
n.updateNetwork = true
}
示例6: clientSend
func (n *Node) clientSend(host string, m *Message) error {
if log.WillLog(log.DEBUG) {
log.Debug("clientSend %s: %v", host, m)
}
if c, ok := n.clients[host]; ok {
c.lock.Lock()
defer c.lock.Unlock()
err := c.enc.Encode(m)
if err != nil {
c.conn.Close()
return err
}
// wait for a response
for {
select {
case ID := <-c.ack:
if ID == m.ID {
return nil
}
case <-time.After(n.timeout):
c.conn.Close()
return errors.New("timeout")
}
}
}
return fmt.Errorf("no such client %s", host)
}
示例7: handleInfo
// Handle incoming "get file info" messages by looking up if we have the file
// and responding with the number of parts or a NACK. Also process directories
// and globs, populating the Glob field of the IOMMessage if needed.
func (iom *IOMeshage) handleInfo(m *IOMMessage) {
// do we have this file, rooted at iom.base?
resp := IOMMessage{
From: iom.node.Name(),
Type: TYPE_RESPONSE,
Filename: m.Filename,
TID: m.TID,
}
glob, parts, err := iom.fileInfo(filepath.Join(iom.base, m.Filename))
if err != nil {
resp.ACK = false
} else if len(glob) == 1 && glob[0] == m.Filename {
resp.ACK = true
resp.Part = parts
fi, err := os.Stat(filepath.Join(iom.base, m.Filename))
if err != nil {
resp.ACK = false
} else {
resp.Perm = fi.Mode() & os.ModePerm
}
if log.WillLog(log.DEBUG) {
log.Debugln("handleInfo found file with parts: ", resp.Part)
}
} else {
// populate Glob
resp.ACK = true
resp.Glob = glob
}
_, err = iom.node.Set([]string{m.From}, resp)
if err != nil {
log.Errorln("handleInfo: sending message: ", err)
}
}
示例8: fileInfo
// Get file info and return the number of parts in the file. If the filename is
// a directory or glob, return the list of files the directory/glob contains.
func (iom *IOMeshage) fileInfo(filename string) ([]string, int64, error) {
glob, err := filepath.Glob(filename)
if err != nil {
return nil, 0, err
}
if len(glob) > 1 {
// globs are recursive, figure out any directories
var globsRet []string
for _, v := range glob {
rGlob, _, err := iom.fileInfo(v)
if err != nil {
return nil, 0, err
}
globsRet = append(globsRet, rGlob...)
}
return globsRet, 0, nil
}
f, err := os.Open(filename)
if err != nil {
return nil, 0, err
}
defer f.Close()
// is this a directory
fi, err := f.Stat()
if err != nil {
if log.WillLog(log.DEBUG) {
log.Debugln("fileInfo error stat: ", err)
}
return nil, 0, err
}
if fi.IsDir() {
// walk the directory and populate glob
glob = []string{}
err := filepath.Walk(filename, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
rel, err := filepath.Rel(iom.base, path)
if err != nil {
return err
}
glob = append(glob, rel)
return nil
})
if err != nil {
return nil, 0, err
}
return glob, 0, nil
}
// we do have the file, calculate the number of parts
parts := (fi.Size() + PART_SIZE - 1) / PART_SIZE // integer divide with ceiling instead of floor
rel, err := filepath.Rel(iom.base, filename)
return []string{rel}, parts, nil
}
示例9: flood
func (n *Node) flood(m *Message) {
if log.WillLog(log.DEBUG) {
log.Debug("flood: %v", m)
}
n.clientLock.Lock()
defer n.clientLock.Unlock()
floodLoop:
for k, _ := range n.clients {
for _, j := range m.CurrentRoute {
if k == j {
continue floodLoop
}
}
go func(j string, m *Message) {
err := n.clientSend(j, m)
if err != nil {
// is j still a client?
if n.hasClient(j) {
log.Error("flood to client %v: %v", j, err)
}
}
}(k, m)
}
}
示例10: MSA
// MSA issues a Meshage State Annoucement, which contains a list of all the nodes connected to the broadcaster
func (n *Node) MSA() {
log.Debugln("MSA")
// rate limit MSA spam to once per MSA timeout / 2
n.msaLock.Lock()
defer n.msaLock.Unlock()
if time.Now().Sub(n.lastMSA) < (n.msaTimeout / 2) {
return
}
n.lastMSA = time.Now()
n.clientLock.Lock()
var clients []string
for k, _ := range n.clients {
clients = append(clients, k)
}
n.clientLock.Unlock()
sort.Strings(clients)
n.meshLock.Lock()
diff := false
if len(n.network[n.name]) != len(clients) {
diff = true
} else {
for i, v := range n.network[n.name] {
if clients[i] != v {
diff = true
break
}
}
}
if diff {
log.Debugln("client list changed, recalculating topology")
n.network[n.name] = clients
n.updateNetwork = true
}
n.meshLock.Unlock()
if log.WillLog(log.DEBUG) {
log.Debug("client list: %v", clients)
}
if len(clients) == 0 {
log.Debugln("not issuing MSA, no connected clients")
return
}
m := &Message{
Source: n.name,
CurrentRoute: []string{n.name},
ID: n.sequence(),
Command: MSA,
Body: clients,
}
n.flood(m)
}
示例11: clientHandler
// clientHandler is called as a goroutine after a successful handshake. It
// begins by issuing an MSA. When the receiver exits, another MSA is issued
// without the client.
func (n *Node) clientHandler(host string) {
log.Debug("clientHandler: %v", host)
c, err := n.getClient(host)
if err != nil {
log.Error("client %v vanished -- %v", host, err)
return
}
n.MSA()
for {
var m Message
c.conn.SetReadDeadline(time.Now().Add(deadlineMultiplier * n.msaTimeout))
err := c.dec.Decode(&m)
if err != nil {
if err != io.EOF && !strings.Contains(err.Error(), "connection reset by peer") {
log.Error("client %v decode: %v", host, err)
}
break
}
if log.WillLog(log.DEBUG) {
log.Debug("decoded message: %v: %v", c.name, &m)
}
if m.Command == ACK {
c.ack <- m.ID
} else {
// send an ack
a := Message{
Command: ACK,
ID: m.ID,
}
c.conn.SetWriteDeadline(time.Now().Add(deadlineMultiplier * n.msaTimeout))
err := c.enc.Encode(a)
if err != nil {
if err != io.EOF {
log.Error("client %v encode ACK: %v", host, err)
}
break
}
n.messagePump <- &m
}
}
log.Info("client %v disconnected", host)
// client has disconnected
c.conn.Close()
n.clientLock.Lock()
delete(n.clients, c.name)
n.clientLock.Unlock()
go n.checkDegree()
n.MSA()
}
示例12: handleResponse
// Handle incoming responses (ACK, file transfer, etc.). It's possible for an
// incoming response to be invalid, such as when a message times out and the
// receiver is no longer expecting the message to arrive. If so, drop the
// message. Responses are sent along registered channels, which are closed when
// the receiver gives up. If we try to send on a closed channel, recover and
// move on.
func (iom *IOMeshage) handleResponse(m *IOMMessage) {
if c, ok := iom.TIDs[m.TID]; ok {
defer func() {
recover()
if log.WillLog(log.DEBUG) {
log.Debugln("send on closed channel recovered")
}
}()
c <- m
} else {
log.Errorln("dropping message for invalid TID: ", m.TID)
}
}
示例13: messageHandler
// messageHandler accepts messages from all connected clients and forwards them to the
// appropriate handlers, and to the receiver channel should the message be intended for this
// node.
func (n *Node) messageHandler() {
log.Debugln("messageHandler")
for {
m := <-n.messagePump
if log.WillLog(log.DEBUG) {
log.Debug("messageHandler: %v", m)
}
m.CurrentRoute = append(m.CurrentRoute, n.name)
switch m.Command {
case MSA:
n.sequenceLock.Lock()
if m.ID == 1 && n.sequences[m.Source] > LOLLIPOP_LENGTH {
n.sequences[m.Source] = 0
}
if m.ID > n.sequences[m.Source] {
n.sequences[m.Source] = m.ID
go n.handleMSA(m)
go n.flood(m)
} else {
log.Debug("dropping broadcast: %v:%v", m.Source, m.ID)
}
n.sequenceLock.Unlock()
case MESSAGE:
var newRecipients []string
runLocal := false
for _, i := range m.Recipients {
if i == n.name {
runLocal = true
} else {
newRecipients = append(newRecipients, i)
}
}
m.Recipients = newRecipients
go n.Send(m)
if runLocal {
go n.handleMessage(m)
} else {
if n.Snoop != nil {
go n.Snoop(m)
}
}
default:
log.Errorln("invalid message command: ", m.Command)
}
}
}
示例14: handleResponse
// Handle incoming responses (ACK, file transfer, etc.). It's possible for an
// incoming response to be invalid, such as when a message times out and the
// receiver is no longer expecting the message to arrive. If so, drop the
// message. Responses are sent along registered channels, which are closed when
// the receiver gives up. If we try to send on a closed channel, recover and
// move on.
func (iom *IOMeshage) handleResponse(m *IOMMessage) {
iom.tidLock.Lock()
c, ok := iom.TIDs[m.TID]
iom.tidLock.Unlock()
if !ok {
log.Errorln("dropping message for invalid TID: ", m.TID)
return
}
defer func() {
recover()
if log.WillLog(log.DEBUG) {
log.Debugln("send on closed channel recovered")
}
}()
c <- m
}
示例15: handleMessages
// Message pump for incoming iomeshage messages.
func (iom *IOMeshage) handleMessages() {
for {
message := (<-iom.Messages).Body.(IOMMessage)
m := &message
if log.WillLog(log.DEBUG) {
log.Debug("got iomessage from %v, type %v", m.From, m.Type)
}
switch m.Type {
case TYPE_INFO:
go iom.handleInfo(m)
case TYPE_WHOHAS:
go iom.handleWhohas(m)
case TYPE_XFER:
go iom.handleXfer(m)
case TYPE_RESPONSE:
go iom.handleResponse(m)
default:
log.Errorln("iomeshage: received invalid message type: ", m.Type)
}
}
}