Merge lp:~rogpeppe/gozk/better-error-messages into lp:gozk/zookeeper

Proposed by Roger Peppe
Status: Merged
Merged at revision: 33
Proposed branch: lp:~rogpeppe/gozk/better-error-messages
Merge into: lp:gozk/zookeeper
Diff against target: 638 lines (+162/-91)
4 files modified
close_test.go (+1/-1)
retry_test.go (+3/-3)
zk.go (+104/-72)
zk_test.go (+54/-15)
To merge this branch: bzr merge lp:~rogpeppe/gozk/better-error-messages
Reviewer Review Type Date Requested Status
The Go Language Gophers Pending
Review via email: mp+97613@code.launchpad.net

Description of the change

zookeeper: make error messages more informative.

https://codereview.appspot.com/5835045/

To post a comment you must log in.
Revision history for this message
Roger Peppe (rogpeppe) wrote :

Reviewers: mp+97613_code.launchpad.net,

Message:
Please take a look.

Description:

https://code.launchpad.net/~rogpeppe/gozk/better-error-messages/+merge/97613

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/5835045/

Affected files:
   A [revision details]
   M close_test.go
   M retry_test.go
   M zk.go
   M zk_test.go

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Very nice. Just a few ideas.

https://codereview.appspot.com/5835045/diff/2001/zk.go
File zk.go (right):

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode120
zk.go:120: // HasErrorCode returns whether the error has the given
It's nice to have this. I was a bit concerned it might be boring to deal
with it.

Can we please call the function as IsError? For example:

   if zookeeper.IsError(err, zookeeper.ZNONODE) { ... }

Also, for the comment, I suggest something like this:

// IsError returns whether err is an *Error with the given
// error code.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode457
zk.go:457: func errClosing(op string) error {
Can we please call this closingError and put it next to zkError? They're
pretty related.

Also, closingError should take a path, as many of the places it's used
have it in context.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode584
zk.go:584: return nil, nil, nil, errClosing("childrenW")
The upper/lower casing is inconsistent. We have "ACL", "addauth",
"setACL", and "childrenW". I suggest we lowercase them all completely.
This is an error message, and more of a hint than something that has to
reflect the method name used exactly.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode925
zk.go:925: if err != nil && !HasErrorCode(err, ZNONODE) {
err != nil isn't necessary here.

https://codereview.appspot.com/5835045/diff/2001/zk_test.go
File zk_test.go (right):

https://codereview.appspot.com/5835045/diff/2001/zk_test.go#newcode1
zk_test.go:1: package zookeeper_test
The Error.Error method has a few different possibilities now as far as
building the error message goes. Would you mind to add a test case for
those? We don't want to find out that we broke that logic at some point
in actual usage.

https://codereview.appspot.com/5835045/diff/2001/zk_test.go#newcode161
zk_test.go:161: c.Assert(err, ErrorMatches, `zookeeper: get
"/non-existent": no node`)
Nice!

https://codereview.appspot.com/5835045/

Revision history for this message
Roger Peppe (rogpeppe) wrote :
39. By Roger Peppe

changes for review

40. By Roger Peppe

go fmt

Revision history for this message
Roger Peppe (rogpeppe) wrote :

https://codereview.appspot.com/5835045/diff/2001/zk.go
File zk.go (right):

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode120
zk.go:120: // HasErrorCode returns whether the error has the given
On 2012/03/15 14:31:38, niemeyer wrote:
> It's nice to have this. I was a bit concerned it might be boring to
deal with
> it.

> Can we please call the function as IsError? For example:

> if zookeeper.IsError(err, zookeeper.ZNONODE) { ... }

> Also, for the comment, I suggest something like this:

> // IsError returns whether err is an *Error with the given
> // error code.

yeah, that's nicer. done.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode457
zk.go:457: func errClosing(op string) error {
On 2012/03/15 14:31:38, niemeyer wrote:
> Can we please call this closingError and put it next to zkError?
They're pretty
> related.

> Also, closingError should take a path, as many of the places it's used
have it
> in context.

Done.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode584
zk.go:584: return nil, nil, nil, errClosing("childrenW")
On 2012/03/15 14:31:38, niemeyer wrote:
> The upper/lower casing is inconsistent. We have "ACL", "addauth",
"setACL", and
> "childrenW". I suggest we lowercase them all completely. This is an
error
> message, and more of a hint than something that has to reflect the
method name
> used exactly.

yeah, i wondered about that. done.

https://codereview.appspot.com/5835045/diff/2001/zk.go#newcode925
zk.go:925: if err != nil && !HasErrorCode(err, ZNONODE) {
On 2012/03/15 14:31:38, niemeyer wrote:
> err != nil isn't necessary here.

it is necessary, i think, otherwise we'll return when err is nil.

https://codereview.appspot.com/5835045/diff/2001/zk_test.go
File zk_test.go (right):

https://codereview.appspot.com/5835045/diff/2001/zk_test.go#newcode1
zk_test.go:1: package zookeeper_test
On 2012/03/15 14:31:38, niemeyer wrote:
> The Error.Error method has a few different possibilities now as far as
building
> the error message goes. Would you mind to add a test case for those?
We don't
> want to find out that we broke that logic at some point in actual
usage.

Done.

https://codereview.appspot.com/5835045/

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :
Revision history for this message
Roger Peppe (rogpeppe) wrote :

*** Submitted:

zookeeper: make error messages more informative.

R=niemeyer
CC=
https://codereview.appspot.com/5835045

https://codereview.appspot.com/5835045/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'close_test.go'
--- close_test.go 2012-02-28 09:13:50 +0000
+++ close_test.go 2012-03-15 15:14:18 +0000
@@ -130,7 +130,7 @@
130 }130 }
131 p.close()131 p.close()
132 err = f(conn, "/closetest")132 err = f(conn, "/closetest")
133 c.Check(err, Equals, zk.ZCLOSING)133 c.Check(zk.IsError(err, zk.ZCLOSING), Equals, true, Commentf("%v", err))
134 }134 }
135}135}
136136
137137
=== modified file 'retry_test.go'
--- retry_test.go 2012-02-27 17:15:50 +0000
+++ retry_test.go 2012-03-15 15:14:18 +0000
@@ -209,7 +209,7 @@
209 return "", nil209 return "", nil
210 })210 })
211 c.Assert(err, NotNil)211 c.Assert(err, NotNil)
212 c.Assert(err, Equals, zk.ZNOAUTH)212 c.Check(zk.IsError(err, zk.ZNOAUTH), Equals, true, Commentf("%v", err))
213213
214 stat, err := conn.Exists("/test")214 stat, err := conn.Exists("/test")
215 c.Assert(err, IsNil)215 c.Assert(err, IsNil)
@@ -232,7 +232,7 @@
232 called = true232 called = true
233 return "", nil233 return "", nil
234 })234 })
235 c.Assert(err, Equals, zk.ZNOAUTH)235 c.Check(zk.IsError(err, zk.ZNOAUTH), Equals, true, Commentf("%v", err))
236236
237 stat, err := conn.Exists("/test")237 stat, err := conn.Exists("/test")
238 c.Assert(err, IsNil)238 c.Assert(err, IsNil)
@@ -256,7 +256,7 @@
256 return "", nil256 return "", nil
257 })257 })
258 c.Assert(err, NotNil)258 c.Assert(err, NotNil)
259 c.Assert(err, Equals, zk.ZNOAUTH)259 c.Check(zk.IsError(err, zk.ZNOAUTH), Equals, true, Commentf("%v", err))
260260
261 stat, err := conn.Exists("/test/sub")261 stat, err := conn.Exists("/test/sub")
262 c.Assert(err, IsNil)262 c.Assert(err, IsNil)
263263
=== modified file 'zk.go'
--- zk.go 2012-02-27 17:15:50 +0000
+++ zk.go 2012-03-15 15:14:18 +0000
@@ -98,57 +98,89 @@
98}98}
9999
100// Error represents a ZooKeeper error.100// Error represents a ZooKeeper error.
101type Error int101type Error struct {
102 Op string
103 Code ErrorCode
104 // SystemError holds an error if Code is ZSYSTEMERROR.
105 SystemError error
106 Path string
107}
108
109func (e *Error) Error() string {
110 s := e.Code.String()
111 if e.Code == ZSYSTEMERROR && e.SystemError != nil {
112 s = e.SystemError.Error()
113 }
114 if e.Path == "" {
115 return fmt.Sprintf("zookeeper: %s: %v", e.Op, s)
116 }
117 return fmt.Sprintf("zookeeper: %s %q: %v", e.Op, e.Path, s)
118}
119
120// IsError returns whether the error is a *Error
121// with the given error code.
122func IsError(err error, code ErrorCode) bool {
123 if err, _ := err.(*Error); err != nil {
124 return err.Code == code
125 }
126 return false
127}
128
129// ErrorCode represents a kind of ZooKeeper error.
130type ErrorCode int
102131
103const (132const (
104 ZOK Error = C.ZOK133 ZOK ErrorCode = C.ZOK
105 ZSYSTEMERROR Error = C.ZSYSTEMERROR134 ZSYSTEMERROR ErrorCode = C.ZSYSTEMERROR
106 ZRUNTIMEINCONSISTENCY Error = C.ZRUNTIMEINCONSISTENCY135 ZRUNTIMEINCONSISTENCY ErrorCode = C.ZRUNTIMEINCONSISTENCY
107 ZDATAINCONSISTENCY Error = C.ZDATAINCONSISTENCY136 ZDATAINCONSISTENCY ErrorCode = C.ZDATAINCONSISTENCY
108 ZCONNECTIONLOSS Error = C.ZCONNECTIONLOSS137 ZCONNECTIONLOSS ErrorCode = C.ZCONNECTIONLOSS
109 ZMARSHALLINGERROR Error = C.ZMARSHALLINGERROR138 ZMARSHALLINGERROR ErrorCode = C.ZMARSHALLINGERROR
110 ZUNIMPLEMENTED Error = C.ZUNIMPLEMENTED139 ZUNIMPLEMENTED ErrorCode = C.ZUNIMPLEMENTED
111 ZOPERATIONTIMEOUT Error = C.ZOPERATIONTIMEOUT140 ZOPERATIONTIMEOUT ErrorCode = C.ZOPERATIONTIMEOUT
112 ZBADARGUMENTS Error = C.ZBADARGUMENTS141 ZBADARGUMENTS ErrorCode = C.ZBADARGUMENTS
113 ZINVALIDSTATE Error = C.ZINVALIDSTATE142 ZINVALIDSTATE ErrorCode = C.ZINVALIDSTATE
114 ZAPIERROR Error = C.ZAPIERROR143 ZAPIERROR ErrorCode = C.ZAPIERROR
115 ZNONODE Error = C.ZNONODE144 ZNONODE ErrorCode = C.ZNONODE
116 ZNOAUTH Error = C.ZNOAUTH145 ZNOAUTH ErrorCode = C.ZNOAUTH
117 ZBADVERSION Error = C.ZBADVERSION146 ZBADVERSION ErrorCode = C.ZBADVERSION
118 ZNOCHILDRENFOREPHEMERALS Error = C.ZNOCHILDRENFOREPHEMERALS147 ZNOCHILDRENFOREPHEMERALS ErrorCode = C.ZNOCHILDRENFOREPHEMERALS
119 ZNODEEXISTS Error = C.ZNODEEXISTS148 ZNODEEXISTS ErrorCode = C.ZNODEEXISTS
120 ZNOTEMPTY Error = C.ZNOTEMPTY149 ZNOTEMPTY ErrorCode = C.ZNOTEMPTY
121 ZSESSIONEXPIRED Error = C.ZSESSIONEXPIRED150 ZSESSIONEXPIRED ErrorCode = C.ZSESSIONEXPIRED
122 ZINVALIDCALLBACK Error = C.ZINVALIDCALLBACK151 ZINVALIDCALLBACK ErrorCode = C.ZINVALIDCALLBACK
123 ZINVALIDACL Error = C.ZINVALIDACL152 ZINVALIDACL ErrorCode = C.ZINVALIDACL
124 ZAUTHFAILED Error = C.ZAUTHFAILED153 ZAUTHFAILED ErrorCode = C.ZAUTHFAILED
125 ZCLOSING Error = C.ZCLOSING154 ZCLOSING ErrorCode = C.ZCLOSING
126 ZNOTHING Error = C.ZNOTHING155 ZNOTHING ErrorCode = C.ZNOTHING
127 ZSESSIONMOVED Error = C.ZSESSIONMOVED156 ZSESSIONMOVED ErrorCode = C.ZSESSIONMOVED
128)157)
129158
130func (error Error) Error() string {159func (code ErrorCode) String() string {
131 return C.GoString(C.zerror(C.int(error))) // Static, no need to free it.160 return C.GoString(C.zerror(C.int(code))) // Static, no need to free it.
132}161}
133162
134// zkError creates an appropriate error return from163// zkError creates an appropriate error return from
135// a ZooKeeper status and the errno return from a C API164// a ZooKeeper status and the errno return from a C API
136// call.165// call.
137func zkError(rc C.int, cerr error) error {166func zkError(rc C.int, cerr error, op, path string) error {
138 code := Error(rc)167 code := ErrorCode(rc)
139 switch code {168 if code == ZOK {
140 case ZOK:
141 return nil169 return nil
170 }
171 err := &Error{
172 Op: op,
173 Code: code,
174 Path: path,
175 }
176 if code == ZSYSTEMERROR {
177 err.SystemError = cerr
178 }
179 return err
180}
142181
143 case ZSYSTEMERROR:182func closingError(op, path string) error {
144 // If a ZooKeeper call returns ZSYSTEMERROR, then183 return zkError(C.int(ZCLOSING), nil, op, path)
145 // errno becomes significant. If errno has not been
146 // set, then we will return ZSYSTEMERROR nonetheless.
147 if cerr != nil {
148 return cerr
149 }
150 }
151 return code
152}184}
153185
154// Constants for SetLogLevel.186// Constants for SetLogLevel.
@@ -419,7 +451,7 @@
419 C.free(unsafe.Pointer(cservers))451 C.free(unsafe.Pointer(cservers))
420 if handle == nil {452 if handle == nil {
421 conn.closeAllWatches()453 conn.closeAllWatches()
422 return nil, nil, zkError(C.int(ZSYSTEMERROR), cerr)454 return nil, nil, zkError(C.int(ZSYSTEMERROR), cerr, "dial", "")
423 }455 }
424 conn.handle = handle456 conn.handle = handle
425 runWatchLoop()457 runWatchLoop()
@@ -444,7 +476,7 @@
444 if conn.handle == nil {476 if conn.handle == nil {
445 // ZooKeeper may hang indefinitely if a handler is closed twice,477 // ZooKeeper may hang indefinitely if a handler is closed twice,
446 // so we get in the way and prevent it from happening.478 // so we get in the way and prevent it from happening.
447 return ZCLOSING479 return closingError("close", "")
448 }480 }
449 rc, cerr := C.zookeeper_close(conn.handle)481 rc, cerr := C.zookeeper_close(conn.handle)
450482
@@ -454,7 +486,7 @@
454 // At this point, nothing else should need conn.handle.486 // At this point, nothing else should need conn.handle.
455 conn.handle = nil487 conn.handle = nil
456488
457 return zkError(rc, cerr)489 return zkError(rc, cerr, "close", "")
458}490}
459491
460// Get returns the data and status from an existing node. err will be nil,492// Get returns the data and status from an existing node. err will be nil,
@@ -464,7 +496,7 @@
464 conn.mutex.RLock()496 conn.mutex.RLock()
465 defer conn.mutex.RUnlock()497 defer conn.mutex.RUnlock()
466 if conn.handle == nil {498 if conn.handle == nil {
467 return "", nil, ZCLOSING499 return "", nil, closingError("get", path)
468 }500 }
469501
470 cpath := C.CString(path)502 cpath := C.CString(path)
@@ -476,7 +508,7 @@
476 var cstat Stat508 var cstat Stat
477 rc, cerr := C.zoo_wget(conn.handle, cpath, nil, nil, cbuffer, &cbufferLen, &cstat.c)509 rc, cerr := C.zoo_wget(conn.handle, cpath, nil, nil, cbuffer, &cbufferLen, &cstat.c)
478 if rc != C.ZOK {510 if rc != C.ZOK {
479 return "", nil, zkError(rc, cerr)511 return "", nil, zkError(rc, cerr, "get", path)
480 }512 }
481513
482 result := C.GoStringN(cbuffer, cbufferLen)514 result := C.GoStringN(cbuffer, cbufferLen)
@@ -491,7 +523,7 @@
491 conn.mutex.RLock()523 conn.mutex.RLock()
492 defer conn.mutex.RUnlock()524 defer conn.mutex.RUnlock()
493 if conn.handle == nil {525 if conn.handle == nil {
494 return "", nil, nil, ZCLOSING526 return "", nil, nil, closingError("getw", path)
495 }527 }
496528
497 cpath := C.CString(path)529 cpath := C.CString(path)
@@ -506,7 +538,7 @@
506 rc, cerr := C.zoo_wget(conn.handle, cpath, C.watch_handler, unsafe.Pointer(watchId), cbuffer, &cbufferLen, &cstat.c)538 rc, cerr := C.zoo_wget(conn.handle, cpath, C.watch_handler, unsafe.Pointer(watchId), cbuffer, &cbufferLen, &cstat.c)
507 if rc != C.ZOK {539 if rc != C.ZOK {
508 conn.forgetWatch(watchId)540 conn.forgetWatch(watchId)
509 return "", nil, nil, zkError(rc, cerr)541 return "", nil, nil, zkError(rc, cerr, "getw", path)
510 }542 }
511543
512 result := C.GoStringN(cbuffer, cbufferLen)544 result := C.GoStringN(cbuffer, cbufferLen)
@@ -519,7 +551,7 @@
519 conn.mutex.RLock()551 conn.mutex.RLock()
520 defer conn.mutex.RUnlock()552 defer conn.mutex.RUnlock()
521 if conn.handle == nil {553 if conn.handle == nil {
522 return nil, nil, ZCLOSING554 return nil, nil, closingError("children", path)
523 }555 }
524556
525 cpath := C.CString(path)557 cpath := C.CString(path)
@@ -536,7 +568,7 @@
536 if rc == C.ZOK {568 if rc == C.ZOK {
537 stat = &cstat569 stat = &cstat
538 } else {570 } else {
539 err = zkError(rc, cerr)571 err = zkError(rc, cerr, "children", path)
540 }572 }
541 return573 return
542}574}
@@ -549,7 +581,7 @@
549 conn.mutex.RLock()581 conn.mutex.RLock()
550 defer conn.mutex.RUnlock()582 defer conn.mutex.RUnlock()
551 if conn.handle == nil {583 if conn.handle == nil {
552 return nil, nil, nil, ZCLOSING584 return nil, nil, nil, closingError("childrenw", path)
553 }585 }
554586
555 cpath := C.CString(path)587 cpath := C.CString(path)
@@ -570,7 +602,7 @@
570 watch = watchChannel602 watch = watchChannel
571 } else {603 } else {
572 conn.forgetWatch(watchId)604 conn.forgetWatch(watchId)
573 err = zkError(rc, cerr)605 err = zkError(rc, cerr, "childrenw", path)
574 }606 }
575 return607 return
576}608}
@@ -595,7 +627,7 @@
595 conn.mutex.RLock()627 conn.mutex.RLock()
596 defer conn.mutex.RUnlock()628 defer conn.mutex.RUnlock()
597 if conn.handle == nil {629 if conn.handle == nil {
598 return nil, ZCLOSING630 return nil, closingError("exists", path)
599 }631 }
600632
601 cpath := C.CString(path)633 cpath := C.CString(path)
@@ -610,7 +642,7 @@
610 if rc == C.ZOK {642 if rc == C.ZOK {
611 stat = &cstat643 stat = &cstat
612 } else if rc != C.ZNONODE {644 } else if rc != C.ZNONODE {
613 err = zkError(rc, cerr)645 err = zkError(rc, cerr, "exists", path)
614 }646 }
615 return647 return
616}648}
@@ -624,7 +656,7 @@
624 conn.mutex.RLock()656 conn.mutex.RLock()
625 defer conn.mutex.RUnlock()657 defer conn.mutex.RUnlock()
626 if conn.handle == nil {658 if conn.handle == nil {
627 return nil, nil, ZCLOSING659 return nil, nil, closingError("existsw", path)
628 }660 }
629661
630 cpath := C.CString(path)662 cpath := C.CString(path)
@@ -638,7 +670,7 @@
638 // We diverge a bit from the usual here: a ZNONODE is not an error670 // We diverge a bit from the usual here: a ZNONODE is not an error
639 // for an exists call, otherwise every Exists call would have to check671 // for an exists call, otherwise every Exists call would have to check
640 // for err != nil and err.Code() != ZNONODE.672 // for err != nil and err.Code() != ZNONODE.
641 switch Error(rc) {673 switch ErrorCode(rc) {
642 case ZOK:674 case ZOK:
643 stat = &cstat675 stat = &cstat
644 watch = watchChannel676 watch = watchChannel
@@ -646,7 +678,7 @@
646 watch = watchChannel678 watch = watchChannel
647 default:679 default:
648 conn.forgetWatch(watchId)680 conn.forgetWatch(watchId)
649 err = zkError(rc, cerr)681 err = zkError(rc, cerr, "existsw", path)
650 }682 }
651 return683 return
652}684}
@@ -664,7 +696,7 @@
664 conn.mutex.RLock()696 conn.mutex.RLock()
665 defer conn.mutex.RUnlock()697 defer conn.mutex.RUnlock()
666 if conn.handle == nil {698 if conn.handle == nil {
667 return "", ZCLOSING699 return "", closingError("close", path)
668 }700 }
669701
670 cpath := C.CString(path)702 cpath := C.CString(path)
@@ -684,7 +716,7 @@
684 if rc == C.ZOK {716 if rc == C.ZOK {
685 pathCreated = C.GoString(cpathCreated)717 pathCreated = C.GoString(cpathCreated)
686 } else {718 } else {
687 err = zkError(rc, cerr)719 err = zkError(rc, cerr, "create", path)
688 }720 }
689 return721 return
690}722}
@@ -701,7 +733,7 @@
701 conn.mutex.RLock()733 conn.mutex.RLock()
702 defer conn.mutex.RUnlock()734 defer conn.mutex.RUnlock()
703 if conn.handle == nil {735 if conn.handle == nil {
704 return nil, ZCLOSING736 return nil, closingError("set", path)
705 }737 }
706738
707 cpath := C.CString(path)739 cpath := C.CString(path)
@@ -714,7 +746,7 @@
714 if rc == C.ZOK {746 if rc == C.ZOK {
715 stat = &cstat747 stat = &cstat
716 } else {748 } else {
717 err = zkError(rc, cerr)749 err = zkError(rc, cerr, "set", path)
718 }750 }
719 return751 return
720}752}
@@ -726,13 +758,13 @@
726 conn.mutex.RLock()758 conn.mutex.RLock()
727 defer conn.mutex.RUnlock()759 defer conn.mutex.RUnlock()
728 if conn.handle == nil {760 if conn.handle == nil {
729 return ZCLOSING761 return closingError("delete", path)
730 }762 }
731763
732 cpath := C.CString(path)764 cpath := C.CString(path)
733 defer C.free(unsafe.Pointer(cpath))765 defer C.free(unsafe.Pointer(cpath))
734 rc, cerr := C.zoo_delete(conn.handle, cpath, C.int(version))766 rc, cerr := C.zoo_delete(conn.handle, cpath, C.int(version))
735 return zkError(rc, cerr)767 return zkError(rc, cerr, "delete", path)
736}768}
737769
738// AddAuth adds a new authentication certificate to the ZooKeeper770// AddAuth adds a new authentication certificate to the ZooKeeper
@@ -744,7 +776,7 @@
744 conn.mutex.RLock()776 conn.mutex.RLock()
745 defer conn.mutex.RUnlock()777 defer conn.mutex.RUnlock()
746 if conn.handle == nil {778 if conn.handle == nil {
747 return ZCLOSING779 return closingError("addauth", "")
748 }780 }
749781
750 cscheme := C.CString(scheme)782 cscheme := C.CString(scheme)
@@ -760,13 +792,13 @@
760792
761 rc, cerr := C.zoo_add_auth(conn.handle, cscheme, ccert, C.int(len(cert)), C.handle_void_completion, unsafe.Pointer(data))793 rc, cerr := C.zoo_add_auth(conn.handle, cscheme, ccert, C.int(len(cert)), C.handle_void_completion, unsafe.Pointer(data))
762 if rc != C.ZOK {794 if rc != C.ZOK {
763 return zkError(rc, cerr)795 return zkError(rc, cerr, "addauth", "")
764 }796 }
765797
766 C.wait_for_completion(data)798 C.wait_for_completion(data)
767799
768 rc = C.int(uintptr(data.data))800 rc = C.int(uintptr(data.data))
769 return zkError(rc, nil)801 return zkError(rc, nil, "addauth", "")
770}802}
771803
772// ACL returns the access control list for path.804// ACL returns the access control list for path.
@@ -774,7 +806,7 @@
774 conn.mutex.RLock()806 conn.mutex.RLock()
775 defer conn.mutex.RUnlock()807 defer conn.mutex.RUnlock()
776 if conn.handle == nil {808 if conn.handle == nil {
777 return nil, nil, ZCLOSING809 return nil, nil, closingError("acl", path)
778 }810 }
779811
780 cpath := C.CString(path)812 cpath := C.CString(path)
@@ -785,7 +817,7 @@
785 var cstat Stat817 var cstat Stat
786 rc, cerr := C.zoo_get_acl(conn.handle, cpath, &caclv, &cstat.c)818 rc, cerr := C.zoo_get_acl(conn.handle, cpath, &caclv, &cstat.c)
787 if rc != C.ZOK {819 if rc != C.ZOK {
788 return nil, nil, zkError(rc, cerr)820 return nil, nil, zkError(rc, cerr, "acl", path)
789 }821 }
790822
791 aclv := parseACLVector(&caclv)823 aclv := parseACLVector(&caclv)
@@ -798,7 +830,7 @@
798 conn.mutex.RLock()830 conn.mutex.RLock()
799 defer conn.mutex.RUnlock()831 defer conn.mutex.RUnlock()
800 if conn.handle == nil {832 if conn.handle == nil {
801 return ZCLOSING833 return closingError("setacl", path)
802 }834 }
803835
804 cpath := C.CString(path)836 cpath := C.CString(path)
@@ -808,7 +840,7 @@
808 defer C.deallocate_ACL_vector(caclv)840 defer C.deallocate_ACL_vector(caclv)
809841
810 rc, cerr := C.zoo_set_acl(conn.handle, cpath, C.int(version), caclv)842 rc, cerr := C.zoo_set_acl(conn.handle, cpath, C.int(version), caclv)
811 return zkError(rc, cerr)843 return zkError(rc, cerr, "setacl", path)
812}844}
813845
814func parseACLVector(caclv *C.struct_ACL_vector) []ACL {846func parseACLVector(caclv *C.struct_ACL_vector) []ACL {
@@ -890,7 +922,7 @@
890func (conn *Conn) RetryChange(path string, flags int, acl []ACL, changeFunc ChangeFunc) error {922func (conn *Conn) RetryChange(path string, flags int, acl []ACL, changeFunc ChangeFunc) error {
891 for {923 for {
892 oldValue, oldStat, err := conn.Get(path)924 oldValue, oldStat, err := conn.Get(path)
893 if err != nil && err != ZNONODE {925 if err != nil && !IsError(err, ZNONODE) {
894 return err926 return err
895 }927 }
896 newValue, err := changeFunc(oldValue, oldStat)928 newValue, err := changeFunc(oldValue, oldStat)
@@ -899,7 +931,7 @@
899 }931 }
900 if oldStat == nil {932 if oldStat == nil {
901 _, err := conn.Create(path, newValue, flags, acl)933 _, err := conn.Create(path, newValue, flags, acl)
902 if err == nil || err != ZNODEEXISTS {934 if err == nil || !IsError(err, ZNODEEXISTS) {
903 return err935 return err
904 }936 }
905 continue937 continue
@@ -908,7 +940,7 @@
908 return nil // Nothing to do.940 return nil // Nothing to do.
909 }941 }
910 _, err = conn.Set(path, newValue, oldStat.Version())942 _, err = conn.Set(path, newValue, oldStat.Version())
911 if err == nil || (err != ZBADVERSION && err != ZNONODE) {943 if err == nil || !IsError(err, ZBADVERSION) && !IsError(err, ZNONODE) {
912 return err944 return err
913 }945 }
914 }946 }
915947
=== modified file 'zk_test.go'
--- zk_test.go 2012-02-27 17:15:50 +0000
+++ zk_test.go 2012-03-15 15:14:18 +0000
@@ -1,6 +1,7 @@
1package zookeeper_test1package zookeeper_test
22
3import (3import (
4 "errors"
4 . "launchpad.net/gocheck"5 . "launchpad.net/gocheck"
5 zk "launchpad.net/gozk/zookeeper"6 zk "launchpad.net/gozk/zookeeper"
6 "time"7 "time"
@@ -25,7 +26,45 @@
25 }26 }
26 c.Assert(conn, IsNil)27 c.Assert(conn, IsNil)
27 c.Assert(watch, IsNil)28 c.Assert(watch, IsNil)
28 c.Assert(err, ErrorMatches, "invalid argument")29 c.Assert(err, ErrorMatches, "zookeeper: dial: invalid argument")
30}
31
32func (s *S) TestErrorMessages(c *C) {
33 tests := []struct {
34 err zk.Error
35 msg string
36 }{{
37 zk.Error{
38 Op: "foo",
39 Code: zk.ZNONODE,
40 Path: "/blah",
41 },
42 `zookeeper: foo "/blah": no node`,
43 }, {
44 zk.Error{
45 Op: "foo",
46 Code: zk.ZNONODE,
47 },
48 `zookeeper: foo: no node`,
49 }, {
50 zk.Error{
51 Op: "foo",
52 Code: zk.ZSYSTEMERROR,
53 SystemError: errors.New("an error"),
54 Path: "/blah",
55 },
56 `zookeeper: foo "/blah": an error`,
57 }, {
58 zk.Error{
59 Op: "foo",
60 Code: zk.ZSYSTEMERROR,
61 Path: "/blah",
62 },
63 `zookeeper: foo "/blah": system error`,
64 }}
65 for _, t := range tests {
66 c.Check(t.err.Error(), Equals, t.msg)
67 }
29}68}
3069
31func (s *S) TestRecvTimeoutInitParameter(c *C) {70func (s *S) TestRecvTimeoutInitParameter(c *C) {
@@ -42,7 +81,7 @@
42 for i := 0; i != 1000; i++ {81 for i := 0; i != 1000; i++ {
43 _, _, err := conn.Get("/zookeeper")82 _, _, err := conn.Get("/zookeeper")
44 if err != nil {83 if err != nil {
45 c.Assert(err, ErrorMatches, "operation timeout")84 c.Check(zk.IsError(err, zk.ZOPERATIONTIMEOUT), Equals, true, Commentf("%v", err))
46 c.SucceedNow()85 c.SucceedNow()
47 }86 }
48 }87 }
@@ -158,8 +197,8 @@
158197
159 c.Assert(data, Equals, "")198 c.Assert(data, Equals, "")
160 c.Assert(stat, IsNil)199 c.Assert(stat, IsNil)
161 c.Assert(err, ErrorMatches, "no node")200 c.Assert(err, ErrorMatches, `zookeeper: get "/non-existent": no node`)
162 c.Assert(err, Equals, zk.ZNONODE)201 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
163}202}
164203
165func (s *S) TestCreateAndGet(c *C) {204func (s *S) TestCreateAndGet(c *C) {
@@ -171,7 +210,7 @@
171210
172 // Check the error condition from Create().211 // Check the error condition from Create().
173 _, err = conn.Create(path, "", zk.EPHEMERAL, zk.WorldACL(zk.PERM_ALL))212 _, err = conn.Create(path, "", zk.EPHEMERAL, zk.WorldACL(zk.PERM_ALL))
174 c.Assert(err, ErrorMatches, "node exists")213 c.Check(zk.IsError(err, zk.ZNODEEXISTS), Equals, true, Commentf("%v", err))
175214
176 data, _, err := conn.Get(path)215 data, _, err := conn.Get(path)
177 c.Assert(err, IsNil)216 c.Assert(err, IsNil)
@@ -270,7 +309,7 @@
270309
271 _, _, watch, err := conn.GetW("/test")310 _, _, watch, err := conn.GetW("/test")
272 c.Assert(err, NotNil)311 c.Assert(err, NotNil)
273 c.Assert(err, Equals, zk.ZNONODE)312 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
274 c.Assert(watch, IsNil)313 c.Assert(watch, IsNil)
275314
276 c.Check(zk.CountPendingWatches(), Equals, 1)315 c.Check(zk.CountPendingWatches(), Equals, 1)
@@ -304,7 +343,7 @@
304 c.Assert(err, IsNil)343 c.Assert(err, IsNil)
305 err = conn.Close()344 err = conn.Close()
306 c.Assert(err, NotNil)345 c.Assert(err, NotNil)
307 c.Assert(err, Equals, zk.ZCLOSING)346 c.Check(zk.IsError(err, zk.ZCLOSING), Equals, true, Commentf("%v", err))
308}347}
309348
310func (s *S) TestChildren(c *C) {349func (s *S) TestChildren(c *C) {
@@ -316,7 +355,7 @@
316 c.Assert(stat.NumChildren(), Equals, 1)355 c.Assert(stat.NumChildren(), Equals, 1)
317356
318 children, stat, err = conn.Children("/non-existent")357 children, stat, err = conn.Children("/non-existent")
319 c.Assert(err, Equals, zk.ZNONODE)358 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
320 c.Assert(children, IsNil)359 c.Assert(children, IsNil)
321 c.Assert(stat, IsNil)360 c.Assert(stat, IsNil)
322}361}
@@ -383,7 +422,7 @@
383422
384 _, stat, watch, err := conn.ChildrenW("/test")423 _, stat, watch, err := conn.ChildrenW("/test")
385 c.Assert(err, NotNil)424 c.Assert(err, NotNil)
386 c.Assert(err, Equals, zk.ZNONODE)425 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
387 c.Assert(watch, IsNil)426 c.Assert(watch, IsNil)
388 c.Assert(stat, IsNil)427 c.Assert(stat, IsNil)
389428
@@ -447,7 +486,7 @@
447486
448 stat, watch, err := conn.ExistsW("///")487 stat, watch, err := conn.ExistsW("///")
449 c.Assert(err, NotNil)488 c.Assert(err, NotNil)
450 c.Assert(err, Equals, zk.ZBADARGUMENTS)489 c.Check(zk.IsError(err, zk.ZBADARGUMENTS), Equals, true, Commentf("%v", err))
451 c.Assert(stat, IsNil)490 c.Assert(stat, IsNil)
452 c.Assert(watch, IsNil)491 c.Assert(watch, IsNil)
453492
@@ -462,14 +501,14 @@
462501
463 err = conn.Delete("/test", 5)502 err = conn.Delete("/test", 5)
464 c.Assert(err, NotNil)503 c.Assert(err, NotNil)
465 c.Assert(err, Equals, zk.ZBADVERSION)504 c.Check(zk.IsError(err, zk.ZBADVERSION), Equals, true, Commentf("%v", err))
466505
467 err = conn.Delete("/test", -1)506 err = conn.Delete("/test", -1)
468 c.Assert(err, IsNil)507 c.Assert(err, IsNil)
469508
470 err = conn.Delete("/test", -1)509 err = conn.Delete("/test", -1)
471 c.Assert(err, NotNil)510 c.Assert(err, NotNil)
472 c.Assert(err, Equals, zk.ZNONODE)511 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
473}512}
474513
475func (s *S) TestClientIdAndReInit(c *C) {514func (s *S) TestClientIdAndReInit(c *C) {
@@ -518,7 +557,7 @@
518557
519 acl, stat, err = conn.ACL("/non-existent")558 acl, stat, err = conn.ACL("/non-existent")
520 c.Assert(err, NotNil)559 c.Assert(err, NotNil)
521 c.Assert(err, Equals, zk.ZNONODE)560 c.Check(zk.IsError(err, zk.ZNONODE), Equals, true, Commentf("%v", err))
522 c.Assert(acl, IsNil)561 c.Assert(acl, IsNil)
523 c.Assert(stat, IsNil)562 c.Assert(stat, IsNil)
524}563}
@@ -531,7 +570,7 @@
531570
532 err = conn.SetACL("/test", zk.WorldACL(zk.PERM_ALL), 5)571 err = conn.SetACL("/test", zk.WorldACL(zk.PERM_ALL), 5)
533 c.Assert(err, NotNil)572 c.Assert(err, NotNil)
534 c.Assert(err, Equals, zk.ZBADVERSION)573 c.Check(zk.IsError(err, zk.ZBADVERSION), Equals, true, Commentf("%v", err))
535574
536 err = conn.SetACL("/test", zk.WorldACL(zk.PERM_READ), -1)575 err = conn.SetACL("/test", zk.WorldACL(zk.PERM_READ), -1)
537 c.Assert(err, IsNil)576 c.Assert(err, IsNil)
@@ -551,7 +590,7 @@
551590
552 _, _, err = conn.Get("/test")591 _, _, err = conn.Get("/test")
553 c.Assert(err, NotNil)592 c.Assert(err, NotNil)
554 c.Assert(err, Equals, zk.ZNOAUTH)593 c.Check(zk.IsError(err, zk.ZNOAUTH), Equals, true, Commentf("%v", err))
555594
556 err = conn.AddAuth("digest", "joe:passwd")595 err = conn.AddAuth("digest", "joe:passwd")
557 c.Assert(err, IsNil)596 c.Assert(err, IsNil)

Subscribers

People subscribed via source and target branches