1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package service
5
6import keybase1 "github.com/keybase/client/go/protocol/keybase1"
7
8type logEntry struct {
9	level  keybase1.LogLevel
10	format string
11	args   []interface{}
12}
13
14type extLogger interface {
15	Log(e *logEntry)
16	SetHandleID(id int)
17	HandleID() int
18	Shutdown()
19}
20
21type logFwd struct {
22	addCh    chan extLogger
23	removeCh chan extLogger
24	logCh    chan *logEntry
25	doneCh   chan bool
26
27	loggers map[int]extLogger
28	idSeq   int
29}
30
31func newLogFwd() *logFwd {
32	f := &logFwd{
33		addCh:    make(chan extLogger),
34		removeCh: make(chan extLogger),
35		logCh:    make(chan *logEntry, 10000),
36		doneCh:   make(chan bool),
37		loggers:  make(map[int]extLogger),
38	}
39
40	go f.process()
41
42	return f
43}
44
45func (f *logFwd) Add(x extLogger) {
46	f.addCh <- x
47}
48
49func (f *logFwd) Remove(x extLogger) {
50	f.removeCh <- x
51}
52
53func (f *logFwd) Log(level keybase1.LogLevel, format string, args []interface{}) {
54	f.logCh <- &logEntry{level: level, format: format, args: args}
55}
56
57func (f *logFwd) Shutdown() {
58	f.doneCh <- true
59}
60
61func (f *logFwd) process() {
62	for {
63		select {
64		case x := <-f.addCh:
65			f.loggers[f.idSeq] = x
66			x.SetHandleID(f.idSeq)
67			f.idSeq++
68		case x := <-f.removeCh:
69			delete(f.loggers, x.HandleID())
70			x.Shutdown()
71		case e := <-f.logCh:
72			for _, x := range f.loggers {
73				x.Log(e)
74			}
75		case <-f.doneCh:
76			for _, x := range f.loggers {
77				x.Shutdown()
78			}
79			return
80		}
81	}
82}
83