Index: go/src/infra/gae/libs/gae/upstream_errors.go |
diff --git a/go/src/infra/gae/libs/gae/upstream_errors.go b/go/src/infra/gae/libs/gae/upstream_errors.go |
index 6194ac770e18783bfd59cfb5608b5a3952a30831..ca051c33bab7854ae34307f42b54bbef1ae6e490 100644 |
--- a/go/src/infra/gae/libs/gae/upstream_errors.go |
+++ b/go/src/infra/gae/libs/gae/upstream_errors.go |
@@ -20,6 +20,7 @@ package gae |
import ( |
"fmt" |
"reflect" |
+ "sync" |
"google.golang.org/appengine/datastore" |
"google.golang.org/appengine/memcache" |
@@ -123,3 +124,40 @@ func FixError(err error) error { |
} |
return err |
} |
+ |
+// LazyMultiError is a lazily-constructed MultiError. You specify the target |
+// MultiError size up front (as Size), and then you call Assign for each error |
+// encountered, and it's potential index. The MultiError will only be allocated |
+// if one of the Assign'd errors is non-nil. Similarly, Get will retrieve either |
+// the allocated MultiError, or nil if no error was encountered. |
+type LazyMultiError struct { |
+ sync.Mutex |
+ |
+ Size int |
+ me MultiError |
+} |
+ |
+// Assign semantically assigns the error to the given index in the MultiError. |
+// If the error is nil, no action is taken. Otherwise the MultiError is |
+// allocated to its full size (if not already), and the error assigned into it. |
+func (e *LazyMultiError) Assign(i int, err error) { |
+ if err == nil { |
+ return |
+ } |
+ e.Lock() |
+ defer e.Unlock() |
+ if e.me == nil { |
+ e.me = make(MultiError, e.Size) |
+ } |
+ e.me[i] = err |
+} |
+ |
+// Get returns the MultiError, or nil, if no non-nil error was Assign'd. |
+func (e *LazyMultiError) Get() error { |
+ e.Lock() |
+ defer e.Unlock() |
+ if e.me == nil { |
+ return nil |
+ } |
+ return e.me |
+} |