Merge lp:~chipaca/ubuntu-push/actual-client-v0 into lp:ubuntu-push

Proposed by John Lenton
Status: Rejected
Rejected by: John Lenton
Proposed branch: lp:~chipaca/ubuntu-push/actual-client-v0
Merge into: lp:ubuntu-push
Prerequisite: lp:~chipaca/ubuntu-push/client-v0
Diff against target: 528 lines (+199/-43)
7 files modified
bus/connectivity/connectivity.go (+7/-7)
bus/connectivity/connectivity_test.go (+6/-6)
client.json (+9/-0)
client/client.go (+141/-0)
client/session/session.go (+2/-2)
client/session/session_test.go (+22/-22)
util/redialer.go (+12/-6)
To merge this branch: bzr merge lp:~chipaca/ubuntu-push/actual-client-v0
Reviewer Review Type Date Requested Status
Ubuntu Push Hackers Pending
Review via email: mp+203236@code.launchpad.net

Commit message

v0 of the actual client. Not covered by tests yet.

Description of the change

v0 of the actual client. Not covered by tests yet.

To post a comment you must log in.
28. By John Lenton

moved client config to etc

29. By John Lenton

merged pipeline; conflict in the redialer fixed

30. By John Lenton

merged trunk, resolved conflict in redialer

Revision history for this message
Samuele Pedroni (pedronis) wrote :

I think main is testable if it gets split in some parts

Unmerged revisions

30. By John Lenton

merged trunk, resolved conflict in redialer

29. By John Lenton

merged pipeline; conflict in the redialer fixed

28. By John Lenton

moved client config to etc

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bus/connectivity/connectivity.go'
--- bus/connectivity/connectivity.go 2014-01-23 14:33:08 +0000
+++ bus/connectivity/connectivity.go 2014-01-27 18:11:05 +0000
@@ -34,21 +34,21 @@
3434
35// the configuration for ConnectedState, with the idea that you'd populate it35// the configuration for ConnectedState, with the idea that you'd populate it
36// from a config file.36// from a config file.
37type Config struct {37type ConnectivityConfig struct {
38 // how long to wait after a state change to make sure it's "stable"38 // how long to wait after a state change to make sure it's "stable"
39 // before acting on it39 // before acting on it
40 StabilizingTimeout config.ConfigTimeDuration40 StabilizingTimeout config.ConfigTimeDuration `json:"stabilizing_timeout"`
41 // How long to wait between online connectivity checks.41 // How long to wait between online connectivity checks.
42 RecheckTimeout config.ConfigTimeDuration42 RecheckTimeout config.ConfigTimeDuration `json:"recheck_timeout"`
43 // The URL against which to do the connectivity check.43 // The URL against which to do the connectivity check.
44 ConnectivityCheckURL string44 ConnectivityCheckURL string `json:"connectivity_check_url"`
45 // The expected MD5 of the content at the ConnectivityCheckURL45 // The expected MD5 of the content at the ConnectivityCheckURL
46 ConnectivityCheckMD5 string46 ConnectivityCheckMD5 string `json:"connectivity_check_md5"`
47}47}
4848
49type connectedState struct {49type connectedState struct {
50 networkStateCh <-chan networkmanager.State50 networkStateCh <-chan networkmanager.State
51 config Config51 config ConnectivityConfig
52 log logger.Logger52 log logger.Logger
53 endp bus.Endpoint53 endp bus.Endpoint
54 connAttempts uint3254 connAttempts uint32
@@ -140,7 +140,7 @@
140//140//
141// The endpoint need not be dialed; connectivity will Dial() and Close()141// The endpoint need not be dialed; connectivity will Dial() and Close()
142// it as it sees fit.142// it as it sees fit.
143func ConnectedState(endp bus.Endpoint, config Config, log logger.Logger, out chan<- bool) {143func ConnectedState(endp bus.Endpoint, config ConnectivityConfig, log logger.Logger, out chan<- bool) {
144 wg := NewWebchecker(config.ConnectivityCheckURL, config.ConnectivityCheckMD5, log)144 wg := NewWebchecker(config.ConnectivityCheckURL, config.ConnectivityCheckMD5, log)
145 cs := &connectedState{145 cs := &connectedState{
146 config: config,146 config: config,
147147
=== modified file 'bus/connectivity/connectivity_test.go'
--- bus/connectivity/connectivity_test.go 2014-01-24 14:12:22 +0000
+++ bus/connectivity/connectivity_test.go 2014-01-27 18:11:05 +0000
@@ -58,7 +58,7 @@
58// when given a working config and bus, Start() will work58// when given a working config and bus, Start() will work
59func (s *ConnSuite) TestStartWorks(c *C) {59func (s *ConnSuite) TestStartWorks(c *C) {
60 endp := testingbus.NewTestingEndpoint(condition.Work(true), condition.Work(true), uint32(networkmanager.Connecting))60 endp := testingbus.NewTestingEndpoint(condition.Work(true), condition.Work(true), uint32(networkmanager.Connecting))
61 cs := connectedState{config: Config{}, log: nullog, endp: endp}61 cs := connectedState{config: ConnectivityConfig{}, log: nullog, endp: endp}
6262
63 c.Check(cs.start(), Equals, networkmanager.Connecting)63 c.Check(cs.start(), Equals, networkmanager.Connecting)
64}64}
@@ -66,7 +66,7 @@
66// if the bus fails a couple of times, we're still OK66// if the bus fails a couple of times, we're still OK
67func (s *ConnSuite) TestStartRetriesConnect(c *C) {67func (s *ConnSuite) TestStartRetriesConnect(c *C) {
68 endp := testingbus.NewTestingEndpoint(condition.Fail2Work(2), condition.Work(true), uint32(networkmanager.Connecting))68 endp := testingbus.NewTestingEndpoint(condition.Fail2Work(2), condition.Work(true), uint32(networkmanager.Connecting))
69 cs := connectedState{config: Config{}, log: nullog, endp: endp}69 cs := connectedState{config: ConnectivityConfig{}, log: nullog, endp: endp}
7070
71 c.Check(cs.start(), Equals, networkmanager.Connecting)71 c.Check(cs.start(), Equals, networkmanager.Connecting)
72 c.Check(cs.connAttempts, Equals, uint32(3)) // 1 more than the Fail2Work72 c.Check(cs.connAttempts, Equals, uint32(3)) // 1 more than the Fail2Work
@@ -75,7 +75,7 @@
75// when the calls to NetworkManager fail for a bit, we're still OK75// when the calls to NetworkManager fail for a bit, we're still OK
76func (s *ConnSuite) TestStartRetriesCall(c *C) {76func (s *ConnSuite) TestStartRetriesCall(c *C) {
77 endp := testingbus.NewTestingEndpoint(condition.Work(true), condition.Fail2Work(5), uint32(networkmanager.Connecting))77 endp := testingbus.NewTestingEndpoint(condition.Work(true), condition.Fail2Work(5), uint32(networkmanager.Connecting))
78 cs := connectedState{config: Config{}, log: nullog, endp: endp}78 cs := connectedState{config: ConnectivityConfig{}, log: nullog, endp: endp}
7979
80 c.Check(cs.start(), Equals, networkmanager.Connecting)80 c.Check(cs.start(), Equals, networkmanager.Connecting)
8181
@@ -93,7 +93,7 @@
93 endp := testingbus.NewTestingEndpoint(condition.Work(true), nmcond,93 endp := testingbus.NewTestingEndpoint(condition.Work(true), nmcond,
94 uint32(networkmanager.Connecting),94 uint32(networkmanager.Connecting),
95 uint32(networkmanager.ConnectedGlobal))95 uint32(networkmanager.ConnectedGlobal))
96 cs := connectedState{config: Config{}, log: nullog, endp: endp}96 cs := connectedState{config: ConnectivityConfig{}, log: nullog, endp: endp}
9797
98 c.Check(cs.start(), Equals, networkmanager.Connecting)98 c.Check(cs.start(), Equals, networkmanager.Connecting)
99 c.Check(cs.connAttempts, Equals, uint32(2))99 c.Check(cs.connAttempts, Equals, uint32(2))
@@ -109,7 +109,7 @@
109 var webget_p condition.Interface = condition.Work(true)109 var webget_p condition.Interface = condition.Work(true)
110 recheck_timeout := 50 * time.Millisecond110 recheck_timeout := 50 * time.Millisecond
111111
112 cfg := Config{112 cfg := ConnectivityConfig{
113 RecheckTimeout: config.ConfigTimeDuration{recheck_timeout},113 RecheckTimeout: config.ConfigTimeDuration{recheck_timeout},
114 }114 }
115 ch := make(chan networkmanager.State, 10)115 ch := make(chan networkmanager.State, 10)
@@ -184,7 +184,7 @@
184 ts := httptest.NewServer(mkHandler(staticText))184 ts := httptest.NewServer(mkHandler(staticText))
185 defer ts.Close()185 defer ts.Close()
186186
187 cfg := Config{187 cfg := ConnectivityConfig{
188 ConnectivityCheckURL: ts.URL,188 ConnectivityCheckURL: ts.URL,
189 ConnectivityCheckMD5: staticHash,189 ConnectivityCheckMD5: staticHash,
190 RecheckTimeout: config.ConfigTimeDuration{time.Second},190 RecheckTimeout: config.ConfigTimeDuration{time.Second},
191191
=== added file 'client.json'
--- client.json 1970-01-01 00:00:00 +0000
+++ client.json 2014-01-27 18:11:05 +0000
@@ -0,0 +1,9 @@
1{
2 "exchange_timeout": "30s",
3 "addr": ":9090",
4 "cert_pem_file": "server/acceptance/config/testing.cert",
5 "stabilizing_timeout": "2s",
6 "recheck_timeout": "10m",
7 "connectivity_check_url": "http://start.ubuntu.com/connectivity-check.html",
8 "connectivity_check_md5": "4589f42e1546aa47ca181e5d949d310b"
9}
010
=== added file 'client/client.go'
--- client/client.go 1970-01-01 00:00:00 +0000
+++ client/client.go 2014-01-27 18:11:05 +0000
@@ -0,0 +1,141 @@
1package main
2
3import (
4 "launchpad.net/go-dbus/v1"
5 "launchpad.net/ubuntu-push/bus"
6 "launchpad.net/ubuntu-push/bus/connectivity"
7 "launchpad.net/ubuntu-push/bus/networkmanager"
8 "launchpad.net/ubuntu-push/bus/notifications"
9 "launchpad.net/ubuntu-push/bus/urldispatcher"
10 "launchpad.net/ubuntu-push/client/session"
11 "launchpad.net/ubuntu-push/config"
12 "launchpad.net/ubuntu-push/logger"
13 "launchpad.net/ubuntu-push/util"
14 "launchpad.net/ubuntu-push/whoopsie/identifier"
15 "os"
16)
17
18type configuration struct {
19 connectivity.ConnectivityConfig
20 session.ClientConfig
21}
22
23const (
24 configFName string = "/etc/ubuntu-push/client.json"
25)
26
27func notify_update(nots *notifications.RawNotifications, log logger.Logger) {
28 action_id := "my_action_id"
29 a := []string{action_id, "Go get it!"} // action value not visible on the phone
30 h := map[string]*dbus.Variant{"x-canonical-switch-to-application": &dbus.Variant{true}}
31 not_id, err := nots.Notify(
32 "ubuntu-push-client", // app name
33 uint32(0), // id
34 "update_manager_icon", // icon
35 "There's an updated system image!", // summary
36 "You've got to get it! Now! Run!", // body
37 a, // actions
38 h, // hints
39 int32(10*1000), // timeout
40 )
41 if err != nil {
42 log.Fatalf("%s", err)
43 }
44 log.Debugf("Got notification id %d\n", not_id)
45}
46
47func main() {
48 log := logger.NewSimpleLogger(os.Stderr, "debug")
49 f, err := os.Open(configFName)
50 if err != nil {
51 log.Fatalf("reading config: %v", err)
52 }
53 cfg := &configuration{}
54 err = config.ReadConfig(f, cfg)
55 if err != nil {
56 log.Fatalf("reading config: %v", err)
57 }
58 whopId := identifier.New()
59 err = whopId.Generate()
60 if err != nil {
61 log.Fatalf("Generating device id: %v", err)
62 }
63 deviceId := whopId.String()
64 log.Debugf("Connecting as device id %s", deviceId)
65 session, err := session.NewSession(cfg.ClientConfig, log, deviceId)
66 if err != nil {
67 log.Fatalf("%s", err)
68 }
69 // ^^ up to this line, things that never change
70 var is_connected, ok bool
71 // vv from this line, things that never stay the same
72 for {
73 log.Debugf("Here we go!")
74 is_connected = false
75 connCh := make(chan bool)
76 iniCh := make(chan uint32)
77
78 notEndp := bus.SessionBus.Endpoint(notifications.BusAddress, log)
79 urlEndp := bus.SessionBus.Endpoint(urldispatcher.BusAddress, log)
80
81 go func() { iniCh <- util.AutoRetry(session.Reset) }()
82 go func() { iniCh <- util.AutoRedial(notEndp) }()
83 go func() { iniCh <- util.AutoRedial(urlEndp) }()
84 go connectivity.ConnectedState(bus.SystemBus.Endpoint(networkmanager.BusAddress, log), cfg.ConnectivityConfig, log, connCh)
85
86 <-iniCh
87 <-iniCh
88 <-iniCh
89 nots := notifications.Raw(notEndp, log)
90 urld := urldispatcher.New(urlEndp, log)
91
92 actnCh, err := nots.WatchActions()
93 if err != nil {
94 log.Errorf("%s", err)
95 continue
96 }
97
98 InnerLoop:
99 for {
100 select {
101 case is_connected, ok = <-connCh:
102 // handle connectivty changes
103 // disconnect session if offline, reconnect if online
104 if !ok {
105 log.Errorf("connectivity checker crashed? restarting everything")
106 break InnerLoop
107 }
108 // fallthrough
109 // oh, silly ol' go doesn't like that.
110 if is_connected {
111 err = session.Reset()
112 if err != nil {
113 break InnerLoop
114 }
115 }
116 case <-session.ErrCh:
117 // handle session errors
118 // restart if online, otherwise ignore
119 if is_connected {
120 err = session.Reset()
121 if err != nil {
122 break InnerLoop
123 }
124 }
125 case <-session.MsgCh:
126 // handle push notifications
127 // pop up client notification
128 // what to do does not depend on the rest
129 // (... for now)
130 log.Debugf("got a notification! let's pop it up.")
131 notify_update(nots, log)
132 case <-actnCh:
133 // handle action clicks
134 // launch system updates
135 // what to do does not depend on the rest
136 // (... for now)
137 urld.DispatchURL("settings:///system/system-update")
138 }
139 }
140 }
141}
0142
=== modified file 'client/session/session.go'
--- client/session/session.go 2014-01-27 18:11:05 +0000
+++ client/session/session.go 2014-01-27 18:11:05 +0000
@@ -50,7 +50,7 @@
5050
51var _ LevelMap = &mapLevelMap{}51var _ LevelMap = &mapLevelMap{}
5252
53type Config struct {53type ClientConfig struct {
54 // session configuration54 // session configuration
55 ExchangeTimeout config.ConfigTimeDuration `json:"exchange_timeout"`55 ExchangeTimeout config.ConfigTimeDuration `json:"exchange_timeout"`
56 // server connection config56 // server connection config
@@ -75,7 +75,7 @@
75 MsgCh chan *Notification75 MsgCh chan *Notification
76}76}
7777
78func NewSession(config Config, log logger.Logger, deviceId string) (*ClientSession, error) {78func NewSession(config ClientConfig, log logger.Logger, deviceId string) (*ClientSession, error) {
79 sess := &ClientSession{79 sess := &ClientSession{
80 ExchangeTimeout: config.ExchangeTimeout.TimeDuration(),80 ExchangeTimeout: config.ExchangeTimeout.TimeDuration(),
81 ServerAddr: config.Addr.HostPort(),81 ServerAddr: config.Addr.HostPort(),
8282
=== modified file 'client/session/session_test.go'
--- client/session/session_test.go 2014-01-27 18:11:05 +0000
+++ client/session/session_test.go 2014-01-27 18:11:05 +0000
@@ -49,7 +49,7 @@
49****************************************************************/49****************************************************************/
5050
51func (cs *clientSessionSuite) TestNewSessionPlainWorks(c *C) {51func (cs *clientSessionSuite) TestNewSessionPlainWorks(c *C) {
52 cfg := Config{}52 cfg := ClientConfig{}
53 sess, err := NewSession(cfg, nullog, "wah")53 sess, err := NewSession(cfg, nullog, "wah")
54 c.Check(sess, NotNil)54 c.Check(sess, NotNil)
55 c.Check(err, IsNil)55 c.Check(err, IsNil)
@@ -58,7 +58,7 @@
58var certfile string = helpers.SourceRelative("../../server/acceptance/config/testing.cert")58var certfile string = helpers.SourceRelative("../../server/acceptance/config/testing.cert")
5959
60func (cs *clientSessionSuite) TestNewSessionPEMWorks(c *C) {60func (cs *clientSessionSuite) TestNewSessionPEMWorks(c *C) {
61 cfg := Config{CertPEMFile: certfile}61 cfg := ClientConfig{CertPEMFile: certfile}
62 sess, err := NewSession(cfg, nullog, "wah")62 sess, err := NewSession(cfg, nullog, "wah")
63 c.Check(sess, NotNil)63 c.Check(sess, NotNil)
64 c.Assert(err, IsNil)64 c.Assert(err, IsNil)
@@ -66,14 +66,14 @@
66}66}
6767
68func (cs *clientSessionSuite) TestNewSessionBadPEMFilePathFails(c *C) {68func (cs *clientSessionSuite) TestNewSessionBadPEMFilePathFails(c *C) {
69 cfg := Config{CertPEMFile: "/no/such/path"}69 cfg := ClientConfig{CertPEMFile: "/no/such/path"}
70 sess, err := NewSession(cfg, nullog, "wah")70 sess, err := NewSession(cfg, nullog, "wah")
71 c.Check(sess, IsNil)71 c.Check(sess, IsNil)
72 c.Check(err, NotNil)72 c.Check(err, NotNil)
73}73}
7474
75func (cs *clientSessionSuite) TestNewSessionBadPEMFileContentFails(c *C) {75func (cs *clientSessionSuite) TestNewSessionBadPEMFileContentFails(c *C) {
76 cfg := Config{CertPEMFile: "/etc/passwd"}76 cfg := ClientConfig{CertPEMFile: "/etc/passwd"}
77 sess, err := NewSession(cfg, nullog, "wah")77 sess, err := NewSession(cfg, nullog, "wah")
78 c.Check(sess, IsNil)78 c.Check(sess, IsNil)
79 c.Check(err, NotNil)79 c.Check(err, NotNil)
@@ -214,7 +214,7 @@
214 ****************************************************************/214 ****************************************************************/
215215
216func (cs *clientSessionSuite) TestRunFailsIfNilConnection(c *C) {216func (cs *clientSessionSuite) TestRunFailsIfNilConnection(c *C) {
217 sess, err := NewSession(Config{}, debuglog, "wah")217 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
218 c.Assert(err, IsNil)218 c.Assert(err, IsNil)
219 // not connected!219 // not connected!
220 err = sess.run()220 err = sess.run()
@@ -223,7 +223,7 @@
223}223}
224224
225func (cs *clientSessionSuite) TestRunFailsIfNilProtocolator(c *C) {225func (cs *clientSessionSuite) TestRunFailsIfNilProtocolator(c *C) {
226 sess, err := NewSession(Config{}, debuglog, "wah")226 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
227 c.Assert(err, IsNil)227 c.Assert(err, IsNil)
228 sess.Connection = &testConn{Name: testname()} // ok, have a constructor228 sess.Connection = &testConn{Name: testname()} // ok, have a constructor
229 sess.Protocolator = nil // but no protocol, seeficare.229 sess.Protocolator = nil // but no protocol, seeficare.
@@ -233,7 +233,7 @@
233}233}
234234
235func (cs *clientSessionSuite) TestRunFailsIfSetDeadlineFails(c *C) {235func (cs *clientSessionSuite) TestRunFailsIfSetDeadlineFails(c *C) {
236 sess, err := NewSession(Config{}, debuglog, "wah")236 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
237 c.Assert(err, IsNil)237 c.Assert(err, IsNil)
238 sess.Connection = &testConn{Name: testname(),238 sess.Connection = &testConn{Name: testname(),
239 DeadlineCondition: condition.Work(false)} // setdeadline will fail239 DeadlineCondition: condition.Work(false)} // setdeadline will fail
@@ -243,7 +243,7 @@
243}243}
244244
245func (cs *clientSessionSuite) TestRunFailsIfWriteFails(c *C) {245func (cs *clientSessionSuite) TestRunFailsIfWriteFails(c *C) {
246 sess, err := NewSession(Config{}, debuglog, "wah")246 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
247 c.Assert(err, IsNil)247 c.Assert(err, IsNil)
248 sess.Connection = &testConn{Name: testname(),248 sess.Connection = &testConn{Name: testname(),
249 WriteCondition: condition.Work(false)} // write will fail249 WriteCondition: condition.Work(false)} // write will fail
@@ -253,7 +253,7 @@
253}253}
254254
255func (cs *clientSessionSuite) TestRunConnectMessageFails(c *C) {255func (cs *clientSessionSuite) TestRunConnectMessageFails(c *C) {
256 sess, err := NewSession(Config{}, debuglog, "wah")256 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
257 c.Assert(err, IsNil)257 c.Assert(err, IsNil)
258 sess.Connection = &testConn{Name: testname()}258 sess.Connection = &testConn{Name: testname()}
259 errCh := make(chan error, 1)259 errCh := make(chan error, 1)
@@ -278,7 +278,7 @@
278}278}
279279
280func (cs *clientSessionSuite) TestRunConnackReadError(c *C) {280func (cs *clientSessionSuite) TestRunConnackReadError(c *C) {
281 sess, err := NewSession(Config{}, debuglog, "wah")281 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
282 c.Assert(err, IsNil)282 c.Assert(err, IsNil)
283 sess.Connection = &testConn{Name: testname()}283 sess.Connection = &testConn{Name: testname()}
284 errCh := make(chan error, 1)284 errCh := make(chan error, 1)
@@ -300,7 +300,7 @@
300}300}
301301
302func (cs *clientSessionSuite) TestRunBadConnack(c *C) {302func (cs *clientSessionSuite) TestRunBadConnack(c *C) {
303 sess, err := NewSession(Config{}, debuglog, "wah")303 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
304 c.Assert(err, IsNil)304 c.Assert(err, IsNil)
305 sess.Connection = &testConn{Name: testname()}305 sess.Connection = &testConn{Name: testname()}
306 errCh := make(chan error, 1)306 errCh := make(chan error, 1)
@@ -322,7 +322,7 @@
322}322}
323323
324func (cs *clientSessionSuite) TestRunMainloopReadError(c *C) {324func (cs *clientSessionSuite) TestRunMainloopReadError(c *C) {
325 sess, err := NewSession(Config{}, debuglog, "wah")325 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
326 c.Assert(err, IsNil)326 c.Assert(err, IsNil)
327 sess.Connection = &testConn{Name: testname()}327 sess.Connection = &testConn{Name: testname()}
328 errCh := make(chan error, 1)328 errCh := make(chan error, 1)
@@ -349,7 +349,7 @@
349}349}
350350
351func (cs *clientSessionSuite) TestRunPongWriteError(c *C) {351func (cs *clientSessionSuite) TestRunPongWriteError(c *C) {
352 sess, err := NewSession(Config{}, debuglog, "wah")352 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
353 c.Assert(err, IsNil)353 c.Assert(err, IsNil)
354 sess.Connection = &testConn{Name: testname()}354 sess.Connection = &testConn{Name: testname()}
355 errCh := make(chan error, 1)355 errCh := make(chan error, 1)
@@ -378,7 +378,7 @@
378}378}
379379
380func (cs *clientSessionSuite) TestRunPingPong(c *C) {380func (cs *clientSessionSuite) TestRunPingPong(c *C) {
381 sess, err := NewSession(Config{}, debuglog, "wah")381 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
382 c.Assert(err, IsNil)382 c.Assert(err, IsNil)
383 sess.Connection = &testConn{Name: testname()}383 sess.Connection = &testConn{Name: testname()}
384 errCh := make(chan error, 1)384 errCh := make(chan error, 1)
@@ -406,7 +406,7 @@
406}406}
407407
408func (cs *clientSessionSuite) TestRunBadAckWrite(c *C) {408func (cs *clientSessionSuite) TestRunBadAckWrite(c *C) {
409 sess, err := NewSession(Config{}, debuglog, "wah")409 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
410 c.Assert(err, IsNil)410 c.Assert(err, IsNil)
411 sess.Connection = &testConn{Name: testname()}411 sess.Connection = &testConn{Name: testname()}
412 errCh := make(chan error, 1)412 errCh := make(chan error, 1)
@@ -444,7 +444,7 @@
444}444}
445445
446func (cs *clientSessionSuite) TestRunBroadcastWrongChannel(c *C) {446func (cs *clientSessionSuite) TestRunBroadcastWrongChannel(c *C) {
447 sess, err := NewSession(Config{}, debuglog, "wah")447 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
448 c.Assert(err, IsNil)448 c.Assert(err, IsNil)
449 sess.Connection = &testConn{Name: testname()}449 sess.Connection = &testConn{Name: testname()}
450 errCh := make(chan error, 1)450 errCh := make(chan error, 1)
@@ -482,7 +482,7 @@
482}482}
483483
484func (cs *clientSessionSuite) TestRunBroadcastRightChannel(c *C) {484func (cs *clientSessionSuite) TestRunBroadcastRightChannel(c *C) {
485 sess, err := NewSession(Config{}, debuglog, "wah")485 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
486 c.Assert(err, IsNil)486 c.Assert(err, IsNil)
487 sess.Connection = &testConn{Name: testname()}487 sess.Connection = &testConn{Name: testname()}
488 sess.ErrCh = make(chan error, 1)488 sess.ErrCh = make(chan error, 1)
@@ -528,7 +528,7 @@
528 */528 */
529529
530func (cs *clientSessionSuite) TestDialFailsWithNoAddress(c *C) {530func (cs *clientSessionSuite) TestDialFailsWithNoAddress(c *C) {
531 sess, err := NewSession(Config{}, debuglog, "wah")531 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
532 c.Assert(err, IsNil)532 c.Assert(err, IsNil)
533 err = sess.Dial()533 err = sess.Dial()
534 c.Assert(err, NotNil)534 c.Assert(err, NotNil)
@@ -539,7 +539,7 @@
539 lp, err := net.Listen("tcp", ":0")539 lp, err := net.Listen("tcp", ":0")
540 c.Assert(err, IsNil)540 c.Assert(err, IsNil)
541 defer lp.Close()541 defer lp.Close()
542 sess, err := NewSession(Config{}, debuglog, "wah")542 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
543 c.Assert(err, IsNil)543 c.Assert(err, IsNil)
544 sess.ServerAddr = lp.Addr().String()544 sess.ServerAddr = lp.Addr().String()
545 err = sess.Dial()545 err = sess.Dial()
@@ -548,7 +548,7 @@
548}548}
549549
550func (cs *clientSessionSuite) TestResetFailsWithoutProtocolator(c *C) {550func (cs *clientSessionSuite) TestResetFailsWithoutProtocolator(c *C) {
551 sess, _ := NewSession(Config{}, debuglog, "wah")551 sess, _ := NewSession(ClientConfig{}, debuglog, "wah")
552 sess.Protocolator = nil552 sess.Protocolator = nil
553 err := sess.Reset()553 err := sess.Reset()
554 c.Assert(err, NotNil)554 c.Assert(err, NotNil)
@@ -556,7 +556,7 @@
556}556}
557557
558func (cs *clientSessionSuite) TestResetFailsWithNoAddress(c *C) {558func (cs *clientSessionSuite) TestResetFailsWithNoAddress(c *C) {
559 sess, err := NewSession(Config{}, debuglog, "wah")559 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
560 c.Assert(err, IsNil)560 c.Assert(err, IsNil)
561 err = sess.Reset()561 err = sess.Reset()
562 c.Assert(err, NotNil)562 c.Assert(err, NotNil)
@@ -571,7 +571,7 @@
571 c.Assert(err, IsNil)571 c.Assert(err, IsNil)
572 defer lp.Close()572 defer lp.Close()
573573
574 sess, err := NewSession(Config{}, debuglog, "wah")574 sess, err := NewSession(ClientConfig{}, debuglog, "wah")
575 c.Assert(err, IsNil)575 c.Assert(err, IsNil)
576 sess.ServerAddr = lp.Addr().String()576 sess.ServerAddr = lp.Addr().String()
577 sess.Connection = &testConn{Name: testname()}577 sess.Connection = &testConn{Name: testname()}
578578
=== modified file 'util/redialer.go'
--- util/redialer.go 2014-01-27 13:02:26 +0000
+++ util/redialer.go 2014-01-27 18:11:05 +0000
@@ -49,15 +49,14 @@
49 return time.Duration(rand.Int63n(2*n+1) - n)49 return time.Duration(rand.Int63n(2*n+1) - n)
50}50}
5151
52// AutoRedialer takes a Dialer and retries its Dial() method until it52// AutoRetry keeps on calling f() until it stops returning an error.
53// stops returning an error. It does exponential (optionally53// It does exponential backoff, adding jitter at each step back.
54// jitter'ed) backoff.54func AutoRetry(f func() error, jitter func(time.Duration) time.Duration) uint32 {
55func AutoRedial(dialer Dialer) uint32 {
56 var timeout time.Duration55 var timeout time.Duration
57 var dialAttempts uint32 = 0 // unsigned so it can wrap safely ...56 var dialAttempts uint32 = 0 // unsigned so it can wrap safely ...
58 var numTimeouts uint32 = uint32(len(Timeouts))57 var numTimeouts uint32 = uint32(len(Timeouts))
59 for {58 for {
60 if dialer.Dial() == nil {59 if f() == nil {
61 return dialAttempts + 160 return dialAttempts + 1
62 }61 }
63 if dialAttempts < numTimeouts {62 if dialAttempts < numTimeouts {
@@ -65,7 +64,7 @@
65 } else {64 } else {
66 timeout = Timeouts[numTimeouts-1]65 timeout = Timeouts[numTimeouts-1]
67 }66 }
68 timeout += dialer.Jitter(timeout)67 timeout += jitter(timeout)
69 dialAttempts++68 dialAttempts++
70 select {69 select {
71 case <-quitRedialing:70 case <-quitRedialing:
@@ -75,6 +74,13 @@
75 }74 }
76}75}
7776
77// AutoRedialer takes a Dialer and retries its Dial() method until it
78// stops returning an error. It does exponential (optionally
79// jitter'ed) backoff.
80func AutoRedial(dialer Dialer) uint32 {
81 return AutoRetry(dialer.Dial, dialer.Jitter)
82}
83
78func init() {84func init() {
79 ps := []int{1, 2, 5, 11, 19, 37, 67, 113, 191} // 3 pₙ₊₁ ≥ 5 pₙ85 ps := []int{1, 2, 5, 11, 19, 37, 67, 113, 191} // 3 pₙ₊₁ ≥ 5 pₙ
80 Timeouts = make([]time.Duration, len(ps))86 Timeouts = make([]time.Duration, len(ps))

Subscribers

People subscribed via source and target branches