Update etcd godep to 3.0.9 to address TestWatch issues
This commit is contained in:
		
							
								
								
									
										244
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										244
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							| @@ -353,263 +353,263 @@ | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/alarm", | 			"ImportPath": "github.com/coreos/etcd/alarm", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/auth", | 			"ImportPath": "github.com/coreos/etcd/auth", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/auth/authpb", | 			"ImportPath": "github.com/coreos/etcd/auth/authpb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/client", | 			"ImportPath": "github.com/coreos/etcd/client", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/clientv3", | 			"ImportPath": "github.com/coreos/etcd/clientv3", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/compactor", | 			"ImportPath": "github.com/coreos/etcd/compactor", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/discovery", | 			"ImportPath": "github.com/coreos/etcd/discovery", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/error", | 			"ImportPath": "github.com/coreos/etcd/error", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver", | 			"ImportPath": "github.com/coreos/etcd/etcdserver", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/api", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/api", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v2http/httptypes", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/auth", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/auth", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/etcdserverpb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/membership", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/membership", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/etcdserver/stats", | 			"ImportPath": "github.com/coreos/etcd/etcdserver/stats", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/integration", | 			"ImportPath": "github.com/coreos/etcd/integration", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/lease", | 			"ImportPath": "github.com/coreos/etcd/lease", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/lease/leasehttp", | 			"ImportPath": "github.com/coreos/etcd/lease/leasehttp", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/lease/leasepb", | 			"ImportPath": "github.com/coreos/etcd/lease/leasepb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/mvcc", | 			"ImportPath": "github.com/coreos/etcd/mvcc", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/mvcc/backend", | 			"ImportPath": "github.com/coreos/etcd/mvcc/backend", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb", | 			"ImportPath": "github.com/coreos/etcd/mvcc/mvccpb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/adt", | 			"ImportPath": "github.com/coreos/etcd/pkg/adt", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/contention", | 			"ImportPath": "github.com/coreos/etcd/pkg/contention", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/crc", | 			"ImportPath": "github.com/coreos/etcd/pkg/crc", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/fileutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/fileutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/httputil", | 			"ImportPath": "github.com/coreos/etcd/pkg/httputil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/idutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/idutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/ioutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/ioutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/logutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/logutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/netutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/netutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/pathutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/pathutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/pbutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/pbutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/runtime", | 			"ImportPath": "github.com/coreos/etcd/pkg/runtime", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/schedule", | 			"ImportPath": "github.com/coreos/etcd/pkg/schedule", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/testutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/testutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/tlsutil", | 			"ImportPath": "github.com/coreos/etcd/pkg/tlsutil", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/transport", | 			"ImportPath": "github.com/coreos/etcd/pkg/transport", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/types", | 			"ImportPath": "github.com/coreos/etcd/pkg/types", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/pkg/wait", | 			"ImportPath": "github.com/coreos/etcd/pkg/wait", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/raft", | 			"ImportPath": "github.com/coreos/etcd/raft", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/raft/raftpb", | 			"ImportPath": "github.com/coreos/etcd/raft/raftpb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/rafthttp", | 			"ImportPath": "github.com/coreos/etcd/rafthttp", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/snap", | 			"ImportPath": "github.com/coreos/etcd/snap", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/snap/snappb", | 			"ImportPath": "github.com/coreos/etcd/snap/snappb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/store", | 			"ImportPath": "github.com/coreos/etcd/store", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/version", | 			"ImportPath": "github.com/coreos/etcd/version", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/wal", | 			"ImportPath": "github.com/coreos/etcd/wal", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/etcd/wal/walpb", | 			"ImportPath": "github.com/coreos/etcd/wal/walpb", | ||||||
| 			"Comment": "v3.0.6", | 			"Comment": "v3.0.9", | ||||||
| 			"Rev": "9efa00d1030d4bf62eb8e5ec130023aeb1b8e2d0" | 			"Rev": "494c0126596c0e7cd59686a2e7afc90fe3296079" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/coreos/go-oidc/http", | 			"ImportPath": "github.com/coreos/go-oidc/http", | ||||||
| @@ -2418,48 +2418,48 @@ | |||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc", | 			"ImportPath": "google.golang.org/grpc", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/codes", | 			"ImportPath": "google.golang.org/grpc/codes", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/credentials", | 			"ImportPath": "google.golang.org/grpc/credentials", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/grpclog", | 			"ImportPath": "google.golang.org/grpc/grpclog", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/internal", | 			"ImportPath": "google.golang.org/grpc/internal", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/metadata", | 			"ImportPath": "google.golang.org/grpc/metadata", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/naming", | 			"ImportPath": "google.golang.org/grpc/naming", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/peer", | 			"ImportPath": "google.golang.org/grpc/peer", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "google.golang.org/grpc/transport", | 			"ImportPath": "google.golang.org/grpc/transport", | ||||||
| 			"Comment": "v1.0.0-6-g02fca89", | 			"Comment": "v1.0.0-183-g231b4cf", | ||||||
| 			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03" | 			"Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "gopkg.in/gcfg.v1", | 			"ImportPath": "gopkg.in/gcfg.v1", | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								vendor/github.com/coreos/etcd/auth/range_perm_cache.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/coreos/etcd/auth/range_perm_cache.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -22,7 +22,10 @@ import ( | |||||||
| 	"github.com/coreos/etcd/mvcc/backend" | 	"github.com/coreos/etcd/mvcc/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // isSubset returns true if a is a subset of b | // isSubset returns true if a is a subset of b. | ||||||
|  | // If a is a prefix of b, then a is a subset of b. | ||||||
|  | // Given intervals [a1,a2) and [b1,b2), is | ||||||
|  | // the a interval a subset of b? | ||||||
| func isSubset(a, b *rangePerm) bool { | func isSubset(a, b *rangePerm) bool { | ||||||
| 	switch { | 	switch { | ||||||
| 	case len(a.end) == 0 && len(b.end) == 0: | 	case len(a.end) == 0 && len(b.end) == 0: | ||||||
| @@ -32,9 +35,11 @@ func isSubset(a, b *rangePerm) bool { | |||||||
| 		// b is a key, a is a range | 		// b is a key, a is a range | ||||||
| 		return false | 		return false | ||||||
| 	case len(a.end) == 0: | 	case len(a.end) == 0: | ||||||
| 		return 0 <= bytes.Compare(a.begin, b.begin) && bytes.Compare(a.begin, b.end) <= 0 | 		// a is a key, b is a range. need b1 <= a1 and a1 < b2 | ||||||
|  | 		return bytes.Compare(b.begin, a.begin) <= 0 && bytes.Compare(a.begin, b.end) < 0 | ||||||
| 	default: | 	default: | ||||||
| 		return 0 <= bytes.Compare(a.begin, b.begin) && bytes.Compare(a.end, b.end) <= 0 | 		// both are ranges. need b1 <= a1 and a2 <= b2 | ||||||
|  | 		return bytes.Compare(b.begin, a.begin) <= 0 && bytes.Compare(a.end, b.end) <= 0 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -88,12 +93,18 @@ func mergeRangePerms(perms []*rangePerm) []*rangePerm { | |||||||
| 	i := 0 | 	i := 0 | ||||||
| 	for i < len(perms) { | 	for i < len(perms) { | ||||||
| 		begin, next := i, i | 		begin, next := i, i | ||||||
| 		for next+1 < len(perms) && bytes.Compare(perms[next].end, perms[next+1].begin) != -1 { | 		for next+1 < len(perms) && bytes.Compare(perms[next].end, perms[next+1].begin) >= 0 { | ||||||
| 			next++ | 			next++ | ||||||
| 		} | 		} | ||||||
|  | 		// don't merge ["a", "b") with ["b", ""), because perms[next+1].end is empty. | ||||||
|  | 		if next != begin && len(perms[next].end) > 0 { | ||||||
| 			merged = append(merged, &rangePerm{begin: perms[begin].begin, end: perms[next].end}) | 			merged = append(merged, &rangePerm{begin: perms[begin].begin, end: perms[next].end}) | ||||||
|  | 		} else { | ||||||
|  | 			merged = append(merged, perms[begin]) | ||||||
|  | 			if next != begin { | ||||||
|  | 				merged = append(merged, perms[next]) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		i = next + 1 | 		i = next + 1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								vendor/github.com/coreos/etcd/clientv3/balancer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/coreos/etcd/clientv3/balancer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -45,6 +45,8 @@ type simpleBalancer struct { | |||||||
| 	// pinAddr is the currently pinned address; set to the empty string on | 	// pinAddr is the currently pinned address; set to the empty string on | ||||||
| 	// intialization and shutdown. | 	// intialization and shutdown. | ||||||
| 	pinAddr string | 	pinAddr string | ||||||
|  |  | ||||||
|  | 	closed bool | ||||||
| } | } | ||||||
|  |  | ||||||
| func newSimpleBalancer(eps []string) *simpleBalancer { | func newSimpleBalancer(eps []string) *simpleBalancer { | ||||||
| @@ -74,15 +76,25 @@ func (b *simpleBalancer) ConnectNotify() <-chan struct{} { | |||||||
|  |  | ||||||
| func (b *simpleBalancer) Up(addr grpc.Address) func(error) { | func (b *simpleBalancer) Up(addr grpc.Address) func(error) { | ||||||
| 	b.mu.Lock() | 	b.mu.Lock() | ||||||
|  | 	defer b.mu.Unlock() | ||||||
|  |  | ||||||
|  | 	// gRPC might call Up after it called Close. We add this check | ||||||
|  | 	// to "fix" it up at application layer. Or our simplerBalancer | ||||||
|  | 	// might panic since b.upc is closed. | ||||||
|  | 	if b.closed { | ||||||
|  | 		return func(err error) {} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if len(b.upEps) == 0 { | 	if len(b.upEps) == 0 { | ||||||
| 		// notify waiting Get()s and pin first connected address | 		// notify waiting Get()s and pin first connected address | ||||||
| 		close(b.upc) | 		close(b.upc) | ||||||
| 		b.pinAddr = addr.Addr | 		b.pinAddr = addr.Addr | ||||||
| 	} | 	} | ||||||
| 	b.upEps[addr.Addr] = struct{}{} | 	b.upEps[addr.Addr] = struct{}{} | ||||||
| 	b.mu.Unlock() |  | ||||||
| 	// notify client that a connection is up | 	// notify client that a connection is up | ||||||
| 	b.readyOnce.Do(func() { close(b.readyc) }) | 	b.readyOnce.Do(func() { close(b.readyc) }) | ||||||
|  |  | ||||||
| 	return func(err error) { | 	return func(err error) { | ||||||
| 		b.mu.Lock() | 		b.mu.Lock() | ||||||
| 		delete(b.upEps, addr.Addr) | 		delete(b.upEps, addr.Addr) | ||||||
| @@ -128,13 +140,19 @@ func (b *simpleBalancer) Notify() <-chan []grpc.Address { return b.notifyCh } | |||||||
|  |  | ||||||
| func (b *simpleBalancer) Close() error { | func (b *simpleBalancer) Close() error { | ||||||
| 	b.mu.Lock() | 	b.mu.Lock() | ||||||
|  | 	defer b.mu.Unlock() | ||||||
|  | 	// In case gRPC calls close twice. TODO: remove the checking | ||||||
|  | 	// when we are sure that gRPC wont call close twice. | ||||||
|  | 	if b.closed { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	b.closed = true | ||||||
| 	close(b.notifyCh) | 	close(b.notifyCh) | ||||||
| 	// terminate all waiting Get()s | 	// terminate all waiting Get()s | ||||||
| 	b.pinAddr = "" | 	b.pinAddr = "" | ||||||
| 	if len(b.upEps) == 0 { | 	if len(b.upEps) == 0 { | ||||||
| 		close(b.upc) | 		close(b.upc) | ||||||
| 	} | 	} | ||||||
| 	b.mu.Unlock() |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								vendor/github.com/coreos/etcd/clientv3/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/coreos/etcd/clientv3/watch.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -669,6 +669,10 @@ func (w *watchGrpcStream) resumeWatchers(wc pb.Watch_WatchClient) error { | |||||||
| 	w.mu.RUnlock() | 	w.mu.RUnlock() | ||||||
|  |  | ||||||
| 	for _, ws := range streams { | 	for _, ws := range streams { | ||||||
|  | 		// drain recvc so no old WatchResponses (e.g., Created messages) | ||||||
|  | 		// are processed while resuming | ||||||
|  | 		ws.drain() | ||||||
|  |  | ||||||
| 		// pause serveStream | 		// pause serveStream | ||||||
| 		ws.resumec <- -1 | 		ws.resumec <- -1 | ||||||
|  |  | ||||||
| @@ -701,6 +705,17 @@ func (w *watchGrpcStream) resumeWatchers(wc pb.Watch_WatchClient) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // drain removes all buffered WatchResponses from the stream's receive channel. | ||||||
|  | func (ws *watcherStream) drain() { | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case <-ws.recvc: | ||||||
|  | 		default: | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // toPB converts an internal watch request structure to its protobuf messagefunc (wr *watchRequest) | // toPB converts an internal watch request structure to its protobuf messagefunc (wr *watchRequest) | ||||||
| func (wr *watchRequest) toPB() *pb.WatchRequest { | func (wr *watchRequest) toPB() *pb.WatchRequest { | ||||||
| 	req := &pb.WatchCreateRequest{ | 	req := &pb.WatchCreateRequest{ | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								vendor/github.com/coreos/etcd/discovery/srv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/coreos/etcd/discovery/srv.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -53,8 +53,8 @@ func SRVGetCluster(name, dns string, defaultToken string, apurls types.URLs) (st | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		for _, srv := range addrs { | 		for _, srv := range addrs { | ||||||
| 			target := strings.TrimSuffix(srv.Target, ".") | 			port := fmt.Sprintf("%d", srv.Port) | ||||||
| 			host := net.JoinHostPort(target, fmt.Sprintf("%d", srv.Port)) | 			host := net.JoinHostPort(srv.Target, port) | ||||||
| 			tcpAddr, err := resolveTCPAddr("tcp", host) | 			tcpAddr, err := resolveTCPAddr("tcp", host) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				plog.Warningf("couldn't resolve host %s during SRV discovery", host) | 				plog.Warningf("couldn't resolve host %s during SRV discovery", host) | ||||||
| @@ -70,8 +70,11 @@ func SRVGetCluster(name, dns string, defaultToken string, apurls types.URLs) (st | |||||||
| 				n = fmt.Sprintf("%d", tempName) | 				n = fmt.Sprintf("%d", tempName) | ||||||
| 				tempName += 1 | 				tempName += 1 | ||||||
| 			} | 			} | ||||||
| 			stringParts = append(stringParts, fmt.Sprintf("%s=%s%s", n, prefix, host)) | 			// SRV records have a trailing dot but URL shouldn't. | ||||||
| 			plog.Noticef("got bootstrap from DNS for %s at %s%s", service, prefix, host) | 			shortHost := strings.TrimSuffix(srv.Target, ".") | ||||||
|  | 			urlHost := net.JoinHostPort(shortHost, port) | ||||||
|  | 			stringParts = append(stringParts, fmt.Sprintf("%s=%s%s", n, prefix, urlHost)) | ||||||
|  | 			plog.Noticef("got bootstrap from DNS for %s at %s%s", service, prefix, urlHost) | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								vendor/github.com/coreos/etcd/etcdserver/server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/coreos/etcd/etcdserver/server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -412,9 +412,14 @@ func NewServer(cfg *ServerConfig) (srv *EtcdServer, err error) { | |||||||
| 	srv.kv = mvcc.New(srv.be, srv.lessor, &srv.consistIndex) | 	srv.kv = mvcc.New(srv.be, srv.lessor, &srv.consistIndex) | ||||||
| 	if beExist { | 	if beExist { | ||||||
| 		kvindex := srv.kv.ConsistentIndex() | 		kvindex := srv.kv.ConsistentIndex() | ||||||
|  | 		// TODO: remove kvindex != 0 checking when we do not expect users to upgrade | ||||||
|  | 		// etcd from pre-3.0 release. | ||||||
| 		if snapshot != nil && kvindex < snapshot.Metadata.Index { | 		if snapshot != nil && kvindex < snapshot.Metadata.Index { | ||||||
|  | 			if kvindex != 0 { | ||||||
| 				return nil, fmt.Errorf("database file (%v index %d) does not match with snapshot (index %d).", bepath, kvindex, snapshot.Metadata.Index) | 				return nil, fmt.Errorf("database file (%v index %d) does not match with snapshot (index %d).", bepath, kvindex, snapshot.Metadata.Index) | ||||||
| 			} | 			} | ||||||
|  | 			plog.Warningf("consistent index never saved (snapshot index=%d)", snapshot.Metadata.Index) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	srv.consistIndex.setConsistentIndex(srv.kv.ConsistentIndex()) | 	srv.consistIndex.setConsistentIndex(srv.kv.ConsistentIndex()) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/dir_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/dir_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // Copyright 2016 The etcd Authors | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | // See the License for the specific language governing permissions and | ||||||
|  | // limitations under the License. | ||||||
|  |  | ||||||
|  | // +build !windows | ||||||
|  |  | ||||||
|  | package fileutil | ||||||
|  |  | ||||||
|  | import "os" | ||||||
|  |  | ||||||
|  | // OpenDir opens a directory for syncing. | ||||||
|  | func OpenDir(path string) (*os.File, error) { return os.Open(path) } | ||||||
							
								
								
									
										46
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/dir_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/dir_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // Copyright 2016 The etcd Authors | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | // See the License for the specific language governing permissions and | ||||||
|  | // limitations under the License. | ||||||
|  |  | ||||||
|  | // +build windows | ||||||
|  |  | ||||||
|  | package fileutil | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"syscall" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // OpenDir opens a directory in windows with write access for syncing. | ||||||
|  | func OpenDir(path string) (*os.File, error) { | ||||||
|  | 	fd, err := openDir(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return os.NewFile(uintptr(fd), path), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func openDir(path string) (fd syscall.Handle, err error) { | ||||||
|  | 	if len(path) == 0 { | ||||||
|  | 		return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND | ||||||
|  | 	} | ||||||
|  | 	pathp, err := syscall.UTF16PtrFromString(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return syscall.InvalidHandle, err | ||||||
|  | 	} | ||||||
|  | 	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE) | ||||||
|  | 	sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE) | ||||||
|  | 	createmode := uint32(syscall.OPEN_EXISTING) | ||||||
|  | 	fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) | ||||||
|  | 	return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0) | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/fileutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/coreos/etcd/pkg/fileutil/fileutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -96,3 +96,26 @@ func Exist(name string) bool { | |||||||
| 	_, err := os.Stat(name) | 	_, err := os.Stat(name) | ||||||
| 	return err == nil | 	return err == nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily | ||||||
|  | // shorten the length of the file. | ||||||
|  | func ZeroToEnd(f *os.File) error { | ||||||
|  | 	// TODO: support FALLOC_FL_ZERO_RANGE | ||||||
|  | 	off, err := f.Seek(0, os.SEEK_CUR) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	lenf, lerr := f.Seek(0, os.SEEK_END) | ||||||
|  | 	if lerr != nil { | ||||||
|  | 		return lerr | ||||||
|  | 	} | ||||||
|  | 	if err = f.Truncate(off); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	// make sure blocks remain allocated | ||||||
|  | 	if err = Preallocate(f, lenf, true); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	_, err = f.Seek(off, os.SEEK_SET) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										103
									
								
								vendor/github.com/coreos/etcd/pkg/ioutil/pagewriter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								vendor/github.com/coreos/etcd/pkg/ioutil/pagewriter.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | // Copyright 2016 The etcd Authors | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | // See the License for the specific language governing permissions and | ||||||
|  | // limitations under the License. | ||||||
|  |  | ||||||
|  | package ioutil | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"io" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var defaultBufferBytes = 128 * 1024 | ||||||
|  |  | ||||||
|  | // PageWriter implements the io.Writer interface so that writes will | ||||||
|  | // either be in page chunks or from flushing. | ||||||
|  | type PageWriter struct { | ||||||
|  | 	w io.Writer | ||||||
|  | 	// pageOffset tracks the page offset of the base of the buffer | ||||||
|  | 	pageOffset int | ||||||
|  | 	// pageBytes is the number of bytes per page | ||||||
|  | 	pageBytes int | ||||||
|  | 	// bufferedBytes counts the number of bytes pending for write in the buffer | ||||||
|  | 	bufferedBytes int | ||||||
|  | 	// buf holds the write buffer | ||||||
|  | 	buf []byte | ||||||
|  | 	// bufWatermarkBytes is the number of bytes the buffer can hold before it needs | ||||||
|  | 	// to be flushed. It is less than len(buf) so there is space for slack writes | ||||||
|  | 	// to bring the writer to page alignment. | ||||||
|  | 	bufWatermarkBytes int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewPageWriter(w io.Writer, pageBytes int) *PageWriter { | ||||||
|  | 	return &PageWriter{ | ||||||
|  | 		w:                 w, | ||||||
|  | 		pageBytes:         pageBytes, | ||||||
|  | 		buf:               make([]byte, defaultBufferBytes+pageBytes), | ||||||
|  | 		bufWatermarkBytes: defaultBufferBytes, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (pw *PageWriter) Write(p []byte) (n int, err error) { | ||||||
|  | 	if len(p)+pw.bufferedBytes <= pw.bufWatermarkBytes { | ||||||
|  | 		// no overflow | ||||||
|  | 		copy(pw.buf[pw.bufferedBytes:], p) | ||||||
|  | 		pw.bufferedBytes += len(p) | ||||||
|  | 		return len(p), nil | ||||||
|  | 	} | ||||||
|  | 	// complete the slack page in the buffer if unaligned | ||||||
|  | 	slack := pw.pageBytes - ((pw.pageOffset + pw.bufferedBytes) % pw.pageBytes) | ||||||
|  | 	if slack != pw.pageBytes { | ||||||
|  | 		partial := slack > len(p) | ||||||
|  | 		if partial { | ||||||
|  | 			// not enough data to complete the slack page | ||||||
|  | 			slack = len(p) | ||||||
|  | 		} | ||||||
|  | 		// special case: writing to slack page in buffer | ||||||
|  | 		copy(pw.buf[pw.bufferedBytes:], p[:slack]) | ||||||
|  | 		pw.bufferedBytes += slack | ||||||
|  | 		n = slack | ||||||
|  | 		p = p[slack:] | ||||||
|  | 		if partial { | ||||||
|  | 			// avoid forcing an unaligned flush | ||||||
|  | 			return n, nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// buffer contents are now page-aligned; clear out | ||||||
|  | 	if err = pw.Flush(); err != nil { | ||||||
|  | 		return n, err | ||||||
|  | 	} | ||||||
|  | 	// directly write all complete pages without copying | ||||||
|  | 	if len(p) > pw.pageBytes { | ||||||
|  | 		pages := len(p) / pw.pageBytes | ||||||
|  | 		c, werr := pw.w.Write(p[:pages*pw.pageBytes]) | ||||||
|  | 		n += c | ||||||
|  | 		if werr != nil { | ||||||
|  | 			return n, werr | ||||||
|  | 		} | ||||||
|  | 		p = p[pages*pw.pageBytes:] | ||||||
|  | 	} | ||||||
|  | 	// write remaining tail to buffer | ||||||
|  | 	c, werr := pw.Write(p) | ||||||
|  | 	n += c | ||||||
|  | 	return n, werr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (pw *PageWriter) Flush() error { | ||||||
|  | 	if pw.bufferedBytes == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	_, err := pw.w.Write(pw.buf[:pw.bufferedBytes]) | ||||||
|  | 	pw.pageOffset = (pw.pageOffset + pw.bufferedBytes) % pw.pageBytes | ||||||
|  | 	pw.bufferedBytes = 0 | ||||||
|  | 	return err | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/github.com/coreos/etcd/version/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/coreos/etcd/version/version.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -29,7 +29,7 @@ import ( | |||||||
| var ( | var ( | ||||||
| 	// MinClusterVersion is the min cluster version this etcd binary is compatible with. | 	// MinClusterVersion is the min cluster version this etcd binary is compatible with. | ||||||
| 	MinClusterVersion = "2.3.0" | 	MinClusterVersion = "2.3.0" | ||||||
| 	Version           = "3.0.6" | 	Version           = "3.0.9" | ||||||
|  |  | ||||||
| 	// Git SHA Value will be set during build | 	// Git SHA Value will be set during build | ||||||
| 	GitSHA = "Not provided (use ./build instead of go build)" | 	GitSHA = "Not provided (use ./build instead of go build)" | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								vendor/github.com/coreos/etcd/wal/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/coreos/etcd/wal/encoder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -15,19 +15,24 @@ | |||||||
| package wal | package wal | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bufio" |  | ||||||
| 	"encoding/binary" | 	"encoding/binary" | ||||||
| 	"hash" | 	"hash" | ||||||
| 	"io" | 	"io" | ||||||
| 	"sync" | 	"sync" | ||||||
|  |  | ||||||
| 	"github.com/coreos/etcd/pkg/crc" | 	"github.com/coreos/etcd/pkg/crc" | ||||||
|  | 	"github.com/coreos/etcd/pkg/ioutil" | ||||||
| 	"github.com/coreos/etcd/wal/walpb" | 	"github.com/coreos/etcd/wal/walpb" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // walPageBytes is the alignment for flushing records to the backing Writer. | ||||||
|  | // It should be a multiple of the minimum sector size so that WAL repair can | ||||||
|  | // safely between torn writes and ordinary data corruption. | ||||||
|  | const walPageBytes = 8 * minSectorSize | ||||||
|  |  | ||||||
| type encoder struct { | type encoder struct { | ||||||
| 	mu sync.Mutex | 	mu sync.Mutex | ||||||
| 	bw *bufio.Writer | 	bw *ioutil.PageWriter | ||||||
|  |  | ||||||
| 	crc       hash.Hash32 | 	crc       hash.Hash32 | ||||||
| 	buf       []byte | 	buf       []byte | ||||||
| @@ -36,7 +41,7 @@ type encoder struct { | |||||||
|  |  | ||||||
| func newEncoder(w io.Writer, prevCrc uint32) *encoder { | func newEncoder(w io.Writer, prevCrc uint32) *encoder { | ||||||
| 	return &encoder{ | 	return &encoder{ | ||||||
| 		bw:  bufio.NewWriter(w), | 		bw:  ioutil.NewPageWriter(w, walPageBytes), | ||||||
| 		crc: crc.New(prevCrc, crcTable), | 		crc: crc.New(prevCrc, crcTable), | ||||||
| 		// 1MB buffer | 		// 1MB buffer | ||||||
| 		buf:       make([]byte, 1024*1024), | 		buf:       make([]byte, 1024*1024), | ||||||
|   | |||||||
							
								
								
									
										67
									
								
								vendor/github.com/coreos/etcd/wal/wal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								vendor/github.com/coreos/etcd/wal/wal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -68,6 +68,10 @@ var ( | |||||||
| // The WAL will be ready for appending after reading out all the previous records. | // The WAL will be ready for appending after reading out all the previous records. | ||||||
| type WAL struct { | type WAL struct { | ||||||
| 	dir string // the living directory of the underlay files | 	dir string // the living directory of the underlay files | ||||||
|  |  | ||||||
|  | 	// dirFile is a fd for the wal directory for syncing on Rename | ||||||
|  | 	dirFile *os.File | ||||||
|  |  | ||||||
| 	metadata []byte           // metadata recorded at the head of each WAL | 	metadata []byte           // metadata recorded at the head of each WAL | ||||||
| 	state    raftpb.HardState // hardstate recorded at the head of WAL | 	state    raftpb.HardState // hardstate recorded at the head of WAL | ||||||
|  |  | ||||||
| @@ -106,10 +110,10 @@ func Create(dirpath string, metadata []byte) (*WAL, error) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if _, err := f.Seek(0, os.SEEK_END); err != nil { | 	if _, err = f.Seek(0, os.SEEK_END); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if err := fileutil.Preallocate(f.File, segmentSizeBytes, true); err != nil { | 	if err = fileutil.Preallocate(f.File, segmentSizeBytes, true); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -119,32 +123,33 @@ func Create(dirpath string, metadata []byte) (*WAL, error) { | |||||||
| 		encoder:  newEncoder(f, 0), | 		encoder:  newEncoder(f, 0), | ||||||
| 	} | 	} | ||||||
| 	w.locks = append(w.locks, f) | 	w.locks = append(w.locks, f) | ||||||
| 	if err := w.saveCrc(0); err != nil { | 	if err = w.saveCrc(0); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if err := w.encoder.encode(&walpb.Record{Type: metadataType, Data: metadata}); err != nil { | 	if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: metadata}); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if err := w.SaveSnapshot(walpb.Snapshot{}); err != nil { | 	if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// rename of directory with locked files doesn't work on windows; close | 	if w, err = w.renameWal(tmpdirpath); err != nil { | ||||||
| 	// the WAL to release the locks so the directory can be renamed |  | ||||||
| 	w.Close() |  | ||||||
| 	if err := os.Rename(tmpdirpath, dirpath); err != nil { |  | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	// reopen and relock |  | ||||||
| 	newWAL, oerr := Open(dirpath, walpb.Snapshot{}) | 	// directory was renamed; sync parent dir to persist rename | ||||||
| 	if oerr != nil { | 	pdir, perr := fileutil.OpenDir(path.Dir(w.dir)) | ||||||
| 		return nil, oerr | 	if perr != nil { | ||||||
|  | 		return nil, perr | ||||||
| 	} | 	} | ||||||
| 	if _, _, _, err := newWAL.ReadAll(); err != nil { | 	if perr = fileutil.Fsync(pdir); perr != nil { | ||||||
| 		newWAL.Close() | 		return nil, perr | ||||||
| 		return nil, err |  | ||||||
| 	} | 	} | ||||||
| 	return newWAL, nil | 	if perr = pdir.Close(); err != nil { | ||||||
|  | 		return nil, perr | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return w, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Open opens the WAL at the given snap. | // Open opens the WAL at the given snap. | ||||||
| @@ -154,7 +159,14 @@ func Create(dirpath string, metadata []byte) (*WAL, error) { | |||||||
| // the given snap. The WAL cannot be appended to before reading out all of its | // the given snap. The WAL cannot be appended to before reading out all of its | ||||||
| // previous records. | // previous records. | ||||||
| func Open(dirpath string, snap walpb.Snapshot) (*WAL, error) { | func Open(dirpath string, snap walpb.Snapshot) (*WAL, error) { | ||||||
| 	return openAtIndex(dirpath, snap, true) | 	w, err := openAtIndex(dirpath, snap, true) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if w.dirFile, err = fileutil.OpenDir(w.dir); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return w, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // OpenForRead only opens the wal files for read. | // OpenForRead only opens the wal files for read. | ||||||
| @@ -299,6 +311,18 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. | |||||||
| 			state.Reset() | 			state.Reset() | ||||||
| 			return nil, state, nil, err | 			return nil, state, nil, err | ||||||
| 		} | 		} | ||||||
|  | 		// decodeRecord() will return io.EOF if it detects a zero record, | ||||||
|  | 		// but this zero record may be followed by non-zero records from | ||||||
|  | 		// a torn write. Overwriting some of these non-zero records, but | ||||||
|  | 		// not all, will cause CRC errors on WAL open. Since the records | ||||||
|  | 		// were never fully synced to disk in the first place, it's safe | ||||||
|  | 		// to zero them out to avoid any CRC errors from new writes. | ||||||
|  | 		if _, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET); err != nil { | ||||||
|  | 			return nil, state, nil, err | ||||||
|  | 		} | ||||||
|  | 		if err = fileutil.ZeroToEnd(w.tail().File); err != nil { | ||||||
|  | 			return nil, state, nil, err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = nil | 	err = nil | ||||||
| @@ -317,7 +341,6 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. | |||||||
|  |  | ||||||
| 	if w.tail() != nil { | 	if w.tail() != nil { | ||||||
| 		// create encoder (chain crc with the decoder), enable appending | 		// create encoder (chain crc with the decoder), enable appending | ||||||
| 		_, err = w.tail().Seek(w.decoder.lastOffset(), os.SEEK_SET) |  | ||||||
| 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC()) | 		w.encoder = newEncoder(w.tail(), w.decoder.lastCRC()) | ||||||
| 	} | 	} | ||||||
| 	w.decoder = nil | 	w.decoder = nil | ||||||
| @@ -375,6 +398,10 @@ func (w *WAL) cut() error { | |||||||
| 	if err = os.Rename(newTail.Name(), fpath); err != nil { | 	if err = os.Rename(newTail.Name(), fpath); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	if err = fileutil.Fsync(w.dirFile); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	newTail.Close() | 	newTail.Close() | ||||||
|  |  | ||||||
| 	if newTail, err = fileutil.LockFile(fpath, os.O_WRONLY, fileutil.PrivateFileMode); err != nil { | 	if newTail, err = fileutil.LockFile(fpath, os.O_WRONLY, fileutil.PrivateFileMode); err != nil { | ||||||
| @@ -477,7 +504,7 @@ func (w *WAL) Close() error { | |||||||
| 			plog.Errorf("failed to unlock during closing wal: %s", err) | 			plog.Errorf("failed to unlock during closing wal: %s", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return w.dirFile.Close() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (w *WAL) saveEntry(e *raftpb.Entry) error { | func (w *WAL) saveEntry(e *raftpb.Entry) error { | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								vendor/github.com/coreos/etcd/wal/wal_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/coreos/etcd/wal/wal_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | // Copyright 2016 The etcd Authors | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | // See the License for the specific language governing permissions and | ||||||
|  | // limitations under the License. | ||||||
|  |  | ||||||
|  | // +build !windows | ||||||
|  |  | ||||||
|  | package wal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/coreos/etcd/pkg/fileutil" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) { | ||||||
|  | 	// On non-Windows platforms, hold the lock while renaming. Releasing | ||||||
|  | 	// the lock and trying to reacquire it quickly can be flaky because | ||||||
|  | 	// it's possible the process will fork to spawn a process while this is | ||||||
|  | 	// happening. The fds are set up as close-on-exec by the Go runtime, | ||||||
|  | 	// but there is a window between the fork and the exec where another | ||||||
|  | 	// process holds the lock. | ||||||
|  |  | ||||||
|  | 	if err := os.RemoveAll(w.dir); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if err := os.Rename(tmpdirpath, w.dir); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	w.fp = newFilePipeline(w.dir, segmentSizeBytes) | ||||||
|  | 	df, err := fileutil.OpenDir(w.dir) | ||||||
|  | 	w.dirFile = df | ||||||
|  | 	return w, err | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								vendor/github.com/coreos/etcd/wal/wal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/coreos/etcd/wal/wal_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | // Copyright 2016 The etcd Authors | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | // See the License for the specific language governing permissions and | ||||||
|  | // limitations under the License. | ||||||
|  |  | ||||||
|  | package wal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/coreos/etcd/wal/walpb" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) { | ||||||
|  | 	// rename of directory with locked files doesn't work on | ||||||
|  | 	// windows; close the WAL to release the locks so the directory | ||||||
|  | 	// can be renamed | ||||||
|  | 	w.Close() | ||||||
|  | 	if err := os.Rename(tmpdirpath, w.dir); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	// reopen and relock | ||||||
|  | 	newWAL, oerr := Open(w.dir, walpb.Snapshot{}) | ||||||
|  | 	if oerr != nil { | ||||||
|  | 		return nil, oerr | ||||||
|  | 	} | ||||||
|  | 	if _, _, _, err := newWAL.ReadAll(); err != nil { | ||||||
|  | 		newWAL.Close() | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return newWAL, nil | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								vendor/google.golang.org/grpc/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/google.golang.org/grpc/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +1,21 @@ | |||||||
| language: go | language: go | ||||||
|  |  | ||||||
| go: | go: | ||||||
|   - 1.5.3 |   - 1.5.4 | ||||||
|   - 1.6 |   - 1.6.3 | ||||||
|  |  | ||||||
|  | go_import_path: google.golang.org/grpc | ||||||
|  |  | ||||||
| before_install: | before_install: | ||||||
|  |   - go get golang.org/x/tools/cmd/goimports | ||||||
|  |   - go get github.com/golang/lint/golint | ||||||
|   - go get github.com/axw/gocov/gocov |   - go get github.com/axw/gocov/gocov | ||||||
|   - go get github.com/mattn/goveralls |   - go get github.com/mattn/goveralls | ||||||
|   - go get golang.org/x/tools/cmd/cover |   - go get golang.org/x/tools/cmd/cover | ||||||
|  |  | ||||||
| install: |  | ||||||
|   - mkdir -p "$GOPATH/src/google.golang.org" |  | ||||||
|   - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/google.golang.org/grpc" |  | ||||||
|  |  | ||||||
| script: | script: | ||||||
|  |   - '! gofmt -s -d -l . 2>&1 | read' | ||||||
|  |   - '! goimports -l . | read' | ||||||
|  |   - '! golint ./... | grep -vE "(_string|\.pb)\.go:"' | ||||||
|  |   - '! go tool vet -all . 2>&1 | grep -vE "constant [0-9]+ not a string in call to Errorf"' | ||||||
|   - make test testrace |   - make test testrace | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								vendor/google.golang.org/grpc/call.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/google.golang.org/grpc/call.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -36,6 +36,7 @@ package grpc | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"math" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"golang.org/x/net/context" | 	"golang.org/x/net/context" | ||||||
| @@ -51,13 +52,20 @@ import ( | |||||||
| func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { | func recvResponse(dopts dialOptions, t transport.ClientTransport, c *callInfo, stream *transport.Stream, reply interface{}) error { | ||||||
| 	// Try to acquire header metadata from the server if there is any. | 	// Try to acquire header metadata from the server if there is any. | ||||||
| 	var err error | 	var err error | ||||||
|  | 	defer func() { | ||||||
|  | 		if err != nil { | ||||||
|  | 			if _, ok := err.(transport.ConnectionError); !ok { | ||||||
|  | 				t.CloseStream(stream, err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
| 	c.headerMD, err = stream.Header() | 	c.headerMD, err = stream.Header() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	p := &parser{r: stream} | 	p := &parser{r: stream} | ||||||
| 	for { | 	for { | ||||||
| 		if err = recv(p, dopts.codec, stream, dopts.dc, reply); err != nil { | 		if err = recv(p, dopts.codec, stream, dopts.dc, reply, math.MaxInt32); err != nil { | ||||||
| 			if err == io.EOF { | 			if err == io.EOF { | ||||||
| 				break | 				break | ||||||
| 			} | 			} | ||||||
| @@ -76,6 +84,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd | |||||||
| 	} | 	} | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  | 			// If err is connection error, t will be closed, no need to close stream here. | ||||||
| 			if _, ok := err.(transport.ConnectionError); !ok { | 			if _, ok := err.(transport.ConnectionError); !ok { | ||||||
| 				t.CloseStream(stream, err) | 				t.CloseStream(stream, err) | ||||||
| 			} | 			} | ||||||
| @@ -90,7 +99,10 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd | |||||||
| 		return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err) | 		return nil, transport.StreamErrorf(codes.Internal, "grpc: %v", err) | ||||||
| 	} | 	} | ||||||
| 	err = t.Write(stream, outBuf, opts) | 	err = t.Write(stream, outBuf, opts) | ||||||
| 	if err != nil { | 	// t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method | ||||||
|  | 	// does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following | ||||||
|  | 	// recvResponse to get the final status. | ||||||
|  | 	if err != nil && err != io.EOF { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	// Sent successfully. | 	// Sent successfully. | ||||||
| @@ -158,9 +170,9 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli | |||||||
| 			if _, ok := err.(*rpcError); ok { | 			if _, ok := err.(*rpcError); ok { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			if err == errConnClosing { | 			if err == errConnClosing || err == errConnUnavailable { | ||||||
| 				if c.failFast { | 				if c.failFast { | ||||||
| 					return Errorf(codes.Unavailable, "%v", errConnClosing) | 					return Errorf(codes.Unavailable, "%v", err) | ||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| @@ -176,7 +188,10 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli | |||||||
| 				put() | 				put() | ||||||
| 				put = nil | 				put = nil | ||||||
| 			} | 			} | ||||||
| 			if _, ok := err.(transport.ConnectionError); ok { | 			// Retry a non-failfast RPC when | ||||||
|  | 			// i) there is a connection error; or | ||||||
|  | 			// ii) the server started to drain before this RPC was initiated. | ||||||
|  | 			if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { | ||||||
| 				if c.failFast { | 				if c.failFast { | ||||||
| 					return toRPCErr(err) | 					return toRPCErr(err) | ||||||
| 				} | 				} | ||||||
| @@ -184,20 +199,18 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli | |||||||
| 			} | 			} | ||||||
| 			return toRPCErr(err) | 			return toRPCErr(err) | ||||||
| 		} | 		} | ||||||
| 		// Receive the response |  | ||||||
| 		err = recvResponse(cc.dopts, t, &c, stream, reply) | 		err = recvResponse(cc.dopts, t, &c, stream, reply) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if put != nil { | 			if put != nil { | ||||||
| 				put() | 				put() | ||||||
| 				put = nil | 				put = nil | ||||||
| 			} | 			} | ||||||
| 			if _, ok := err.(transport.ConnectionError); ok { | 			if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { | ||||||
| 				if c.failFast { | 				if c.failFast { | ||||||
| 					return toRPCErr(err) | 					return toRPCErr(err) | ||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 			t.CloseStream(stream, err) |  | ||||||
| 			return toRPCErr(err) | 			return toRPCErr(err) | ||||||
| 		} | 		} | ||||||
| 		if c.traceInfo.tr != nil { | 		if c.traceInfo.tr != nil { | ||||||
|   | |||||||
							
								
								
									
										267
									
								
								vendor/google.golang.org/grpc/clientconn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										267
									
								
								vendor/google.golang.org/grpc/clientconn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -43,7 +43,6 @@ import ( | |||||||
|  |  | ||||||
| 	"golang.org/x/net/context" | 	"golang.org/x/net/context" | ||||||
| 	"golang.org/x/net/trace" | 	"golang.org/x/net/trace" | ||||||
| 	"google.golang.org/grpc/codes" |  | ||||||
| 	"google.golang.org/grpc/credentials" | 	"google.golang.org/grpc/credentials" | ||||||
| 	"google.golang.org/grpc/grpclog" | 	"google.golang.org/grpc/grpclog" | ||||||
| 	"google.golang.org/grpc/transport" | 	"google.golang.org/grpc/transport" | ||||||
| @@ -68,12 +67,14 @@ var ( | |||||||
| 	// errCredentialsConflict indicates that grpc.WithTransportCredentials() | 	// errCredentialsConflict indicates that grpc.WithTransportCredentials() | ||||||
| 	// and grpc.WithInsecure() are both called for a connection. | 	// and grpc.WithInsecure() are both called for a connection. | ||||||
| 	errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)") | 	errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)") | ||||||
| 	// errNetworkIP indicates that the connection is down due to some network I/O error. | 	// errNetworkIO indicates that the connection is down due to some network I/O error. | ||||||
| 	errNetworkIO = errors.New("grpc: failed with network I/O error") | 	errNetworkIO = errors.New("grpc: failed with network I/O error") | ||||||
| 	// errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs. | 	// errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs. | ||||||
| 	errConnDrain = errors.New("grpc: the connection is drained") | 	errConnDrain = errors.New("grpc: the connection is drained") | ||||||
| 	// errConnClosing indicates that the connection is closing. | 	// errConnClosing indicates that the connection is closing. | ||||||
| 	errConnClosing = errors.New("grpc: the connection is closing") | 	errConnClosing = errors.New("grpc: the connection is closing") | ||||||
|  | 	// errConnUnavailable indicates that the connection is unavailable. | ||||||
|  | 	errConnUnavailable = errors.New("grpc: the connection is unavailable") | ||||||
| 	errNoAddr          = errors.New("grpc: there is no address available to dial") | 	errNoAddr          = errors.New("grpc: there is no address available to dial") | ||||||
| 	// minimum time to give a connection to complete | 	// minimum time to give a connection to complete | ||||||
| 	minConnectTimeout = 20 * time.Second | 	minConnectTimeout = 20 * time.Second | ||||||
| @@ -196,9 +197,14 @@ func WithTimeout(d time.Duration) DialOption { | |||||||
| } | } | ||||||
|  |  | ||||||
| // WithDialer returns a DialOption that specifies a function to use for dialing network addresses. | // WithDialer returns a DialOption that specifies a function to use for dialing network addresses. | ||||||
| func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) DialOption { | func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption { | ||||||
| 	return func(o *dialOptions) { | 	return func(o *dialOptions) { | ||||||
| 		o.copts.Dialer = f | 		o.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) { | ||||||
|  | 			if deadline, ok := ctx.Deadline(); ok { | ||||||
|  | 				return f(addr, deadline.Sub(time.Now())) | ||||||
|  | 			} | ||||||
|  | 			return f(addr, 0) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -209,12 +215,19 @@ func WithUserAgent(s string) DialOption { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Dial creates a client connection the given target. | // Dial creates a client connection to the given target. | ||||||
| func Dial(target string, opts ...DialOption) (*ClientConn, error) { | func Dial(target string, opts ...DialOption) (*ClientConn, error) { | ||||||
|  | 	return DialContext(context.Background(), target, opts...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DialContext creates a client connection to the given target | ||||||
|  | // using the supplied context. | ||||||
|  | func DialContext(ctx context.Context, target string, opts ...DialOption) (*ClientConn, error) { | ||||||
| 	cc := &ClientConn{ | 	cc := &ClientConn{ | ||||||
| 		target: target, | 		target: target, | ||||||
| 		conns:  make(map[Address]*addrConn), | 		conns:  make(map[Address]*addrConn), | ||||||
| 	} | 	} | ||||||
|  | 	cc.ctx, cc.cancel = context.WithCancel(ctx) | ||||||
| 	for _, opt := range opts { | 	for _, opt := range opts { | ||||||
| 		opt(&cc.dopts) | 		opt(&cc.dopts) | ||||||
| 	} | 	} | ||||||
| @@ -226,17 +239,18 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { | |||||||
| 	if cc.dopts.bs == nil { | 	if cc.dopts.bs == nil { | ||||||
| 		cc.dopts.bs = DefaultBackoffConfig | 		cc.dopts.bs = DefaultBackoffConfig | ||||||
| 	} | 	} | ||||||
| 	if cc.dopts.balancer == nil { |  | ||||||
| 		cc.dopts.balancer = RoundRobin(nil) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if err := cc.dopts.balancer.Start(target); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	var ( | 	var ( | ||||||
| 		ok    bool | 		ok    bool | ||||||
| 		addrs []Address | 		addrs []Address | ||||||
| 	) | 	) | ||||||
|  | 	if cc.dopts.balancer == nil { | ||||||
|  | 		// Connect to target directly if balancer is nil. | ||||||
|  | 		addrs = append(addrs, Address{Addr: target}) | ||||||
|  | 	} else { | ||||||
|  | 		if err := cc.dopts.balancer.Start(target); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
| 		ch := cc.dopts.balancer.Notify() | 		ch := cc.dopts.balancer.Notify() | ||||||
| 		if ch == nil { | 		if ch == nil { | ||||||
| 			// There is no name resolver installed. | 			// There is no name resolver installed. | ||||||
| @@ -247,10 +261,11 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { | |||||||
| 				return nil, errNoAddr | 				return nil, errNoAddr | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 	waitC := make(chan error, 1) | 	waitC := make(chan error, 1) | ||||||
| 	go func() { | 	go func() { | ||||||
| 		for _, a := range addrs { | 		for _, a := range addrs { | ||||||
| 			if err := cc.newAddrConn(a, false); err != nil { | 			if err := cc.resetAddrConn(a, false, nil); err != nil { | ||||||
| 				waitC <- err | 				waitC <- err | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| @@ -267,10 +282,15 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { | |||||||
| 			cc.Close() | 			cc.Close() | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  | 	case <-cc.ctx.Done(): | ||||||
|  | 		cc.Close() | ||||||
|  | 		return nil, cc.ctx.Err() | ||||||
| 	case <-timeoutCh: | 	case <-timeoutCh: | ||||||
| 		cc.Close() | 		cc.Close() | ||||||
| 		return nil, ErrClientConnTimeout | 		return nil, ErrClientConnTimeout | ||||||
| 	} | 	} | ||||||
|  | 	// If balancer is nil or balancer.Notify() is nil, ok will be false here. | ||||||
|  | 	// The lbWatcher goroutine will not be created. | ||||||
| 	if ok { | 	if ok { | ||||||
| 		go cc.lbWatcher() | 		go cc.lbWatcher() | ||||||
| 	} | 	} | ||||||
| @@ -317,6 +337,9 @@ func (s ConnectivityState) String() string { | |||||||
|  |  | ||||||
| // ClientConn represents a client connection to an RPC server. | // ClientConn represents a client connection to an RPC server. | ||||||
| type ClientConn struct { | type ClientConn struct { | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	cancel context.CancelFunc | ||||||
|  |  | ||||||
| 	target    string | 	target    string | ||||||
| 	authority string | 	authority string | ||||||
| 	dopts     dialOptions | 	dopts     dialOptions | ||||||
| @@ -347,11 +370,12 @@ func (cc *ClientConn) lbWatcher() { | |||||||
| 			} | 			} | ||||||
| 			if !keep { | 			if !keep { | ||||||
| 				del = append(del, c) | 				del = append(del, c) | ||||||
|  | 				delete(cc.conns, c.addr) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		cc.mu.Unlock() | 		cc.mu.Unlock() | ||||||
| 		for _, a := range add { | 		for _, a := range add { | ||||||
| 			cc.newAddrConn(a, true) | 			cc.resetAddrConn(a, true, nil) | ||||||
| 		} | 		} | ||||||
| 		for _, c := range del { | 		for _, c := range del { | ||||||
| 			c.tearDown(errConnDrain) | 			c.tearDown(errConnDrain) | ||||||
| @@ -359,13 +383,17 @@ func (cc *ClientConn) lbWatcher() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error { | // resetAddrConn creates an addrConn for addr and adds it to cc.conns. | ||||||
|  | // If there is an old addrConn for addr, it will be torn down, using tearDownErr as the reason. | ||||||
|  | // If tearDownErr is nil, errConnDrain will be used instead. | ||||||
|  | func (cc *ClientConn) resetAddrConn(addr Address, skipWait bool, tearDownErr error) error { | ||||||
| 	ac := &addrConn{ | 	ac := &addrConn{ | ||||||
| 		cc:    cc, | 		cc:    cc, | ||||||
| 		addr:  addr, | 		addr:  addr, | ||||||
| 		dopts: cc.dopts, | 		dopts: cc.dopts, | ||||||
| 		shutdownChan: make(chan struct{}), |  | ||||||
| 	} | 	} | ||||||
|  | 	ac.ctx, ac.cancel = context.WithCancel(cc.ctx) | ||||||
|  | 	ac.stateCV = sync.NewCond(&ac.mu) | ||||||
| 	if EnableTracing { | 	if EnableTracing { | ||||||
| 		ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr) | 		ac.events = trace.NewEventLog("grpc.ClientConn", ac.addr.Addr) | ||||||
| 	} | 	} | ||||||
| @@ -383,26 +411,44 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Insert ac into ac.cc.conns. This needs to be done before any getTransport(...) is called. | 	// Track ac in cc. This needs to be done before any getTransport(...) is called. | ||||||
| 	ac.cc.mu.Lock() | 	cc.mu.Lock() | ||||||
| 	if ac.cc.conns == nil { | 	if cc.conns == nil { | ||||||
| 		ac.cc.mu.Unlock() | 		cc.mu.Unlock() | ||||||
| 		return ErrClientConnClosing | 		return ErrClientConnClosing | ||||||
| 	} | 	} | ||||||
| 	stale := ac.cc.conns[ac.addr] | 	stale := cc.conns[ac.addr] | ||||||
| 	ac.cc.conns[ac.addr] = ac | 	cc.conns[ac.addr] = ac | ||||||
| 	ac.cc.mu.Unlock() | 	cc.mu.Unlock() | ||||||
| 	if stale != nil { | 	if stale != nil { | ||||||
| 		// There is an addrConn alive on ac.addr already. This could be due to | 		// There is an addrConn alive on ac.addr already. This could be due to | ||||||
| 		// i) stale's Close is undergoing; | 		// 1) a buggy Balancer notifies duplicated Addresses; | ||||||
| 		// ii) a buggy Balancer notifies duplicated Addresses. | 		// 2) goaway was received, a new ac will replace the old ac. | ||||||
|  | 		//    The old ac should be deleted from cc.conns, but the | ||||||
|  | 		//    underlying transport should drain rather than close. | ||||||
|  | 		if tearDownErr == nil { | ||||||
|  | 			// tearDownErr is nil if resetAddrConn is called by | ||||||
|  | 			// 1) Dial | ||||||
|  | 			// 2) lbWatcher | ||||||
|  | 			// In both cases, the stale ac should drain, not close. | ||||||
| 			stale.tearDown(errConnDrain) | 			stale.tearDown(errConnDrain) | ||||||
|  | 		} else { | ||||||
|  | 			stale.tearDown(tearDownErr) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	ac.stateCV = sync.NewCond(&ac.mu) |  | ||||||
| 	// skipWait may overwrite the decision in ac.dopts.block. | 	// skipWait may overwrite the decision in ac.dopts.block. | ||||||
| 	if ac.dopts.block && !skipWait { | 	if ac.dopts.block && !skipWait { | ||||||
| 		if err := ac.resetTransport(false); err != nil { | 		if err := ac.resetTransport(false); err != nil { | ||||||
|  | 			if err != errConnClosing { | ||||||
|  | 				// Tear down ac and delete it from cc.conns. | ||||||
|  | 				cc.mu.Lock() | ||||||
|  | 				delete(cc.conns, ac.addr) | ||||||
|  | 				cc.mu.Unlock() | ||||||
| 				ac.tearDown(err) | 				ac.tearDown(err) | ||||||
|  | 			} | ||||||
|  | 			if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { | ||||||
|  | 				return e.Origin() | ||||||
|  | 			} | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		// Start to monitor the error status of transport. | 		// Start to monitor the error status of transport. | ||||||
| @@ -412,7 +458,10 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error { | |||||||
| 		go func() { | 		go func() { | ||||||
| 			if err := ac.resetTransport(false); err != nil { | 			if err := ac.resetTransport(false); err != nil { | ||||||
| 				grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err) | 				grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err) | ||||||
|  | 				if err != errConnClosing { | ||||||
|  | 					// Keep this ac in cc.conns, to get the reason it's torn down. | ||||||
| 					ac.tearDown(err) | 					ac.tearDown(err) | ||||||
|  | 				} | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			ac.transportMonitor() | 			ac.transportMonitor() | ||||||
| @@ -422,7 +471,30 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { | func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { | ||||||
| 	addr, put, err := cc.dopts.balancer.Get(ctx, opts) | 	var ( | ||||||
|  | 		ac  *addrConn | ||||||
|  | 		ok  bool | ||||||
|  | 		put func() | ||||||
|  | 	) | ||||||
|  | 	if cc.dopts.balancer == nil { | ||||||
|  | 		// If balancer is nil, there should be only one addrConn available. | ||||||
|  | 		cc.mu.RLock() | ||||||
|  | 		if cc.conns == nil { | ||||||
|  | 			cc.mu.RUnlock() | ||||||
|  | 			return nil, nil, toRPCErr(ErrClientConnClosing) | ||||||
|  | 		} | ||||||
|  | 		for _, ac = range cc.conns { | ||||||
|  | 			// Break after the first iteration to get the first addrConn. | ||||||
|  | 			ok = true | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		cc.mu.RUnlock() | ||||||
|  | 	} else { | ||||||
|  | 		var ( | ||||||
|  | 			addr Address | ||||||
|  | 			err  error | ||||||
|  | 		) | ||||||
|  | 		addr, put, err = cc.dopts.balancer.Get(ctx, opts) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, nil, toRPCErr(err) | 			return nil, nil, toRPCErr(err) | ||||||
| 		} | 		} | ||||||
| @@ -431,15 +503,16 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) | |||||||
| 			cc.mu.RUnlock() | 			cc.mu.RUnlock() | ||||||
| 			return nil, nil, toRPCErr(ErrClientConnClosing) | 			return nil, nil, toRPCErr(ErrClientConnClosing) | ||||||
| 		} | 		} | ||||||
| 	ac, ok := cc.conns[addr] | 		ac, ok = cc.conns[addr] | ||||||
| 		cc.mu.RUnlock() | 		cc.mu.RUnlock() | ||||||
|  | 	} | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		if put != nil { | 		if put != nil { | ||||||
| 			put() | 			put() | ||||||
| 		} | 		} | ||||||
| 		return nil, nil, Errorf(codes.Internal, "grpc: failed to find the transport to send the rpc") | 		return nil, nil, errConnClosing | ||||||
| 	} | 	} | ||||||
| 	t, err := ac.wait(ctx, !opts.BlockingWait) | 	t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if put != nil { | 		if put != nil { | ||||||
| 			put() | 			put() | ||||||
| @@ -451,6 +524,8 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) | |||||||
|  |  | ||||||
| // Close tears down the ClientConn and all underlying connections. | // Close tears down the ClientConn and all underlying connections. | ||||||
| func (cc *ClientConn) Close() error { | func (cc *ClientConn) Close() error { | ||||||
|  | 	cc.cancel() | ||||||
|  |  | ||||||
| 	cc.mu.Lock() | 	cc.mu.Lock() | ||||||
| 	if cc.conns == nil { | 	if cc.conns == nil { | ||||||
| 		cc.mu.Unlock() | 		cc.mu.Unlock() | ||||||
| @@ -459,7 +534,9 @@ func (cc *ClientConn) Close() error { | |||||||
| 	conns := cc.conns | 	conns := cc.conns | ||||||
| 	cc.conns = nil | 	cc.conns = nil | ||||||
| 	cc.mu.Unlock() | 	cc.mu.Unlock() | ||||||
|  | 	if cc.dopts.balancer != nil { | ||||||
| 		cc.dopts.balancer.Close() | 		cc.dopts.balancer.Close() | ||||||
|  | 	} | ||||||
| 	for _, ac := range conns { | 	for _, ac := range conns { | ||||||
| 		ac.tearDown(ErrClientConnClosing) | 		ac.tearDown(ErrClientConnClosing) | ||||||
| 	} | 	} | ||||||
| @@ -468,10 +545,12 @@ func (cc *ClientConn) Close() error { | |||||||
|  |  | ||||||
| // addrConn is a network connection to a given address. | // addrConn is a network connection to a given address. | ||||||
| type addrConn struct { | type addrConn struct { | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	cancel context.CancelFunc | ||||||
|  |  | ||||||
| 	cc     *ClientConn | 	cc     *ClientConn | ||||||
| 	addr   Address | 	addr   Address | ||||||
| 	dopts  dialOptions | 	dopts  dialOptions | ||||||
| 	shutdownChan chan struct{} |  | ||||||
| 	events trace.EventLog | 	events trace.EventLog | ||||||
|  |  | ||||||
| 	mu      sync.Mutex | 	mu      sync.Mutex | ||||||
| @@ -482,6 +561,9 @@ type addrConn struct { | |||||||
| 	// due to timeout. | 	// due to timeout. | ||||||
| 	ready     chan struct{} | 	ready     chan struct{} | ||||||
| 	transport transport.ClientTransport | 	transport transport.ClientTransport | ||||||
|  |  | ||||||
|  | 	// The reason this addrConn is torn down. | ||||||
|  | 	tearDownErr error | ||||||
| } | } | ||||||
|  |  | ||||||
| // printf records an event in ac's event log, unless ac has been closed. | // printf records an event in ac's event log, unless ac has been closed. | ||||||
| @@ -537,8 +619,7 @@ func (ac *addrConn) waitForStateChange(ctx context.Context, sourceState Connecti | |||||||
| } | } | ||||||
|  |  | ||||||
| func (ac *addrConn) resetTransport(closeTransport bool) error { | func (ac *addrConn) resetTransport(closeTransport bool) error { | ||||||
| 	var retries int | 	for retries := 0; ; retries++ { | ||||||
| 	for { |  | ||||||
| 		ac.mu.Lock() | 		ac.mu.Lock() | ||||||
| 		ac.printf("connecting") | 		ac.printf("connecting") | ||||||
| 		if ac.state == Shutdown { | 		if ac.state == Shutdown { | ||||||
| @@ -558,13 +639,20 @@ func (ac *addrConn) resetTransport(closeTransport bool) error { | |||||||
| 			t.Close() | 			t.Close() | ||||||
| 		} | 		} | ||||||
| 		sleepTime := ac.dopts.bs.backoff(retries) | 		sleepTime := ac.dopts.bs.backoff(retries) | ||||||
| 		ac.dopts.copts.Timeout = sleepTime | 		timeout := minConnectTimeout | ||||||
| 		if sleepTime < minConnectTimeout { | 		if timeout < sleepTime { | ||||||
| 			ac.dopts.copts.Timeout = minConnectTimeout | 			timeout = sleepTime | ||||||
| 		} | 		} | ||||||
|  | 		ctx, cancel := context.WithTimeout(ac.ctx, timeout) | ||||||
| 		connectTime := time.Now() | 		connectTime := time.Now() | ||||||
| 		newTransport, err := transport.NewClientTransport(ac.addr.Addr, &ac.dopts.copts) | 		newTransport, err := transport.NewClientTransport(ctx, ac.addr.Addr, ac.dopts.copts) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  | 			cancel() | ||||||
|  |  | ||||||
|  | 			if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) | ||||||
| 			ac.mu.Lock() | 			ac.mu.Lock() | ||||||
| 			if ac.state == Shutdown { | 			if ac.state == Shutdown { | ||||||
| 				// ac.tearDown(...) has been invoked. | 				// ac.tearDown(...) has been invoked. | ||||||
| @@ -579,17 +667,12 @@ func (ac *addrConn) resetTransport(closeTransport bool) error { | |||||||
| 				ac.ready = nil | 				ac.ready = nil | ||||||
| 			} | 			} | ||||||
| 			ac.mu.Unlock() | 			ac.mu.Unlock() | ||||||
| 			sleepTime -= time.Since(connectTime) |  | ||||||
| 			if sleepTime < 0 { |  | ||||||
| 				sleepTime = 0 |  | ||||||
| 			} |  | ||||||
| 			closeTransport = false | 			closeTransport = false | ||||||
| 			select { | 			select { | ||||||
| 			case <-time.After(sleepTime): | 			case <-time.After(sleepTime - time.Since(connectTime)): | ||||||
| 			case <-ac.shutdownChan: | 			case <-ac.ctx.Done(): | ||||||
|  | 				return ac.ctx.Err() | ||||||
| 			} | 			} | ||||||
| 			retries++ |  | ||||||
| 			grpclog.Printf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %q", err, ac.addr) |  | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		ac.mu.Lock() | 		ac.mu.Lock() | ||||||
| @@ -607,7 +690,9 @@ func (ac *addrConn) resetTransport(closeTransport bool) error { | |||||||
| 			close(ac.ready) | 			close(ac.ready) | ||||||
| 			ac.ready = nil | 			ac.ready = nil | ||||||
| 		} | 		} | ||||||
|  | 		if ac.cc.dopts.balancer != nil { | ||||||
| 			ac.down = ac.cc.dopts.balancer.Up(ac.addr) | 			ac.down = ac.cc.dopts.balancer.Up(ac.addr) | ||||||
|  | 		} | ||||||
| 		ac.mu.Unlock() | 		ac.mu.Unlock() | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| @@ -621,14 +706,42 @@ func (ac *addrConn) transportMonitor() { | |||||||
| 		t := ac.transport | 		t := ac.transport | ||||||
| 		ac.mu.Unlock() | 		ac.mu.Unlock() | ||||||
| 		select { | 		select { | ||||||
| 		// shutdownChan is needed to detect the teardown when | 		// This is needed to detect the teardown when | ||||||
| 		// the addrConn is idle (i.e., no RPC in flight). | 		// the addrConn is idle (i.e., no RPC in flight). | ||||||
| 		case <-ac.shutdownChan: | 		case <-ac.ctx.Done(): | ||||||
|  | 			select { | ||||||
|  | 			case <-t.Error(): | ||||||
|  | 				t.Close() | ||||||
|  | 			default: | ||||||
|  | 			} | ||||||
|  | 			return | ||||||
|  | 		case <-t.GoAway(): | ||||||
|  | 			// If GoAway happens without any network I/O error, ac is closed without shutting down the | ||||||
|  | 			// underlying transport (the transport will be closed when all the pending RPCs finished or | ||||||
|  | 			// failed.). | ||||||
|  | 			// If GoAway and some network I/O error happen concurrently, ac and its underlying transport | ||||||
|  | 			// are closed. | ||||||
|  | 			// In both cases, a new ac is created. | ||||||
|  | 			select { | ||||||
|  | 			case <-t.Error(): | ||||||
|  | 				ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) | ||||||
|  | 			default: | ||||||
|  | 				ac.cc.resetAddrConn(ac.addr, true, errConnDrain) | ||||||
|  | 			} | ||||||
| 			return | 			return | ||||||
| 		case <-t.Error(): | 		case <-t.Error(): | ||||||
|  | 			select { | ||||||
|  | 			case <-ac.ctx.Done(): | ||||||
|  | 				t.Close() | ||||||
|  | 				return | ||||||
|  | 			case <-t.GoAway(): | ||||||
|  | 				ac.cc.resetAddrConn(ac.addr, true, errNetworkIO) | ||||||
|  | 				return | ||||||
|  | 			default: | ||||||
|  | 			} | ||||||
| 			ac.mu.Lock() | 			ac.mu.Lock() | ||||||
| 			if ac.state == Shutdown { | 			if ac.state == Shutdown { | ||||||
| 				// ac.tearDown(...) has been invoked. | 				// ac has been shutdown. | ||||||
| 				ac.mu.Unlock() | 				ac.mu.Unlock() | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| @@ -640,6 +753,10 @@ func (ac *addrConn) transportMonitor() { | |||||||
| 				ac.printf("transport exiting: %v", err) | 				ac.printf("transport exiting: %v", err) | ||||||
| 				ac.mu.Unlock() | 				ac.mu.Unlock() | ||||||
| 				grpclog.Printf("grpc: addrConn.transportMonitor exits due to: %v", err) | 				grpclog.Printf("grpc: addrConn.transportMonitor exits due to: %v", err) | ||||||
|  | 				if err != errConnClosing { | ||||||
|  | 					// Keep this ac in cc.conns, to get the reason it's torn down. | ||||||
|  | 					ac.tearDown(err) | ||||||
|  | 				} | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -647,22 +764,30 @@ func (ac *addrConn) transportMonitor() { | |||||||
| } | } | ||||||
|  |  | ||||||
| // wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or | // wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or | ||||||
| // iv) transport is in TransientFailure and the RPC is fail-fast. | // iv) transport is in TransientFailure and there's no balancer/failfast is true. | ||||||
| func (ac *addrConn) wait(ctx context.Context, failFast bool) (transport.ClientTransport, error) { | func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) { | ||||||
| 	for { | 	for { | ||||||
| 		ac.mu.Lock() | 		ac.mu.Lock() | ||||||
| 		switch { | 		switch { | ||||||
| 		case ac.state == Shutdown: | 		case ac.state == Shutdown: | ||||||
|  | 			if failfast || !hasBalancer { | ||||||
|  | 				// RPC is failfast or balancer is nil. This RPC should fail with ac.tearDownErr. | ||||||
|  | 				err := ac.tearDownErr | ||||||
|  | 				ac.mu.Unlock() | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
| 			ac.mu.Unlock() | 			ac.mu.Unlock() | ||||||
| 			return nil, errConnClosing | 			return nil, errConnClosing | ||||||
| 		case ac.state == Ready: | 		case ac.state == Ready: | ||||||
| 			ct := ac.transport | 			ct := ac.transport | ||||||
| 			ac.mu.Unlock() | 			ac.mu.Unlock() | ||||||
| 			return ct, nil | 			return ct, nil | ||||||
| 		case ac.state == TransientFailure && failFast: | 		case ac.state == TransientFailure: | ||||||
|  | 			if failfast || hasBalancer { | ||||||
| 				ac.mu.Unlock() | 				ac.mu.Unlock() | ||||||
| 			return nil, Errorf(codes.Unavailable, "grpc: RPC failed fast due to transport failure") | 				return nil, errConnUnavailable | ||||||
| 		default: | 			} | ||||||
|  | 		} | ||||||
| 		ready := ac.ready | 		ready := ac.ready | ||||||
| 		if ready == nil { | 		if ready == nil { | ||||||
| 			ready = make(chan struct{}) | 			ready = make(chan struct{}) | ||||||
| @@ -677,30 +802,33 @@ func (ac *addrConn) wait(ctx context.Context, failFast bool) (transport.ClientTr | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| } |  | ||||||
|  |  | ||||||
| // tearDown starts to tear down the addrConn. | // tearDown starts to tear down the addrConn. | ||||||
| // TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in | // TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in | ||||||
| // some edge cases (e.g., the caller opens and closes many addrConn's in a | // some edge cases (e.g., the caller opens and closes many addrConn's in a | ||||||
| // tight loop. | // tight loop. | ||||||
|  | // tearDown doesn't remove ac from ac.cc.conns. | ||||||
| func (ac *addrConn) tearDown(err error) { | func (ac *addrConn) tearDown(err error) { | ||||||
|  | 	ac.cancel() | ||||||
|  |  | ||||||
| 	ac.mu.Lock() | 	ac.mu.Lock() | ||||||
| 	defer func() { | 	defer ac.mu.Unlock() | ||||||
| 		ac.mu.Unlock() |  | ||||||
| 		ac.cc.mu.Lock() |  | ||||||
| 		if ac.cc.conns != nil { |  | ||||||
| 			delete(ac.cc.conns, ac.addr) |  | ||||||
| 		} |  | ||||||
| 		ac.cc.mu.Unlock() |  | ||||||
| 	}() |  | ||||||
| 	if ac.state == Shutdown { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	ac.state = Shutdown |  | ||||||
| 	if ac.down != nil { | 	if ac.down != nil { | ||||||
| 		ac.down(downErrorf(false, false, "%v", err)) | 		ac.down(downErrorf(false, false, "%v", err)) | ||||||
| 		ac.down = nil | 		ac.down = nil | ||||||
| 	} | 	} | ||||||
|  | 	if err == errConnDrain && ac.transport != nil { | ||||||
|  | 		// GracefulClose(...) may be executed multiple times when | ||||||
|  | 		// i) receiving multiple GoAway frames from the server; or | ||||||
|  | 		// ii) there are concurrent name resolver/Balancer triggered | ||||||
|  | 		// address removal and GoAway. | ||||||
|  | 		ac.transport.GracefulClose() | ||||||
|  | 	} | ||||||
|  | 	if ac.state == Shutdown { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	ac.state = Shutdown | ||||||
|  | 	ac.tearDownErr = err | ||||||
| 	ac.stateCV.Broadcast() | 	ac.stateCV.Broadcast() | ||||||
| 	if ac.events != nil { | 	if ac.events != nil { | ||||||
| 		ac.events.Finish() | 		ac.events.Finish() | ||||||
| @@ -710,15 +838,8 @@ func (ac *addrConn) tearDown(err error) { | |||||||
| 		close(ac.ready) | 		close(ac.ready) | ||||||
| 		ac.ready = nil | 		ac.ready = nil | ||||||
| 	} | 	} | ||||||
| 	if ac.transport != nil { | 	if ac.transport != nil && err != errConnDrain { | ||||||
| 		if err == errConnDrain { |  | ||||||
| 			ac.transport.GracefulClose() |  | ||||||
| 		} else { |  | ||||||
| 		ac.transport.Close() | 		ac.transport.Close() | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 	if ac.shutdownChan != nil { |  | ||||||
| 		close(ac.shutdownChan) |  | ||||||
| 	} |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								vendor/google.golang.org/grpc/credentials/credentials.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/google.golang.org/grpc/credentials/credentials.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -44,7 +44,6 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net" | 	"net" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"golang.org/x/net/context" | 	"golang.org/x/net/context" | ||||||
| ) | ) | ||||||
| @@ -93,11 +92,12 @@ type TransportCredentials interface { | |||||||
| 	// ClientHandshake does the authentication handshake specified by the corresponding | 	// ClientHandshake does the authentication handshake specified by the corresponding | ||||||
| 	// authentication protocol on rawConn for clients. It returns the authenticated | 	// authentication protocol on rawConn for clients. It returns the authenticated | ||||||
| 	// connection and the corresponding auth information about the connection. | 	// connection and the corresponding auth information about the connection. | ||||||
| 	ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (net.Conn, AuthInfo, error) | 	// Implementations must use the provided context to implement timely cancellation. | ||||||
|  | 	ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) | ||||||
| 	// ServerHandshake does the authentication handshake for servers. It returns | 	// ServerHandshake does the authentication handshake for servers. It returns | ||||||
| 	// the authenticated connection and the corresponding auth information about | 	// the authenticated connection and the corresponding auth information about | ||||||
| 	// the connection. | 	// the connection. | ||||||
| 	ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) | 	ServerHandshake(net.Conn) (net.Conn, AuthInfo, error) | ||||||
| 	// Info provides the ProtocolInfo of this TransportCredentials. | 	// Info provides the ProtocolInfo of this TransportCredentials. | ||||||
| 	Info() ProtocolInfo | 	Info() ProtocolInfo | ||||||
| } | } | ||||||
| @@ -136,43 +136,29 @@ func (c *tlsCreds) RequireTransportSecurity() bool { | |||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| type timeoutError struct{} | func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) { | ||||||
|  |  | ||||||
| func (timeoutError) Error() string   { return "credentials: Dial timed out" } |  | ||||||
| func (timeoutError) Timeout() bool   { return true } |  | ||||||
| func (timeoutError) Temporary() bool { return true } |  | ||||||
|  |  | ||||||
| func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ AuthInfo, err error) { |  | ||||||
| 	// borrow some code from tls.DialWithDialer |  | ||||||
| 	var errChannel chan error |  | ||||||
| 	if timeout != 0 { |  | ||||||
| 		errChannel = make(chan error, 2) |  | ||||||
| 		time.AfterFunc(timeout, func() { |  | ||||||
| 			errChannel <- timeoutError{} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| 	// use local cfg to avoid clobbering ServerName if using multiple endpoints | 	// use local cfg to avoid clobbering ServerName if using multiple endpoints | ||||||
| 	cfg := *c.config | 	cfg := cloneTLSConfig(c.config) | ||||||
| 	if c.config.ServerName == "" { | 	if cfg.ServerName == "" { | ||||||
| 		colonPos := strings.LastIndex(addr, ":") | 		colonPos := strings.LastIndex(addr, ":") | ||||||
| 		if colonPos == -1 { | 		if colonPos == -1 { | ||||||
| 			colonPos = len(addr) | 			colonPos = len(addr) | ||||||
| 		} | 		} | ||||||
| 		cfg.ServerName = addr[:colonPos] | 		cfg.ServerName = addr[:colonPos] | ||||||
| 	} | 	} | ||||||
| 	conn := tls.Client(rawConn, &cfg) | 	conn := tls.Client(rawConn, cfg) | ||||||
| 	if timeout == 0 { | 	errChannel := make(chan error, 1) | ||||||
| 		err = conn.Handshake() |  | ||||||
| 	} else { |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		errChannel <- conn.Handshake() | 		errChannel <- conn.Handshake() | ||||||
| 	}() | 	}() | ||||||
| 		err = <-errChannel | 	select { | ||||||
| 	} | 	case err := <-errChannel: | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 		rawConn.Close() |  | ||||||
| 			return nil, nil, err | 			return nil, nil, err | ||||||
| 		} | 		} | ||||||
|  | 	case <-ctx.Done(): | ||||||
|  | 		return nil, nil, ctx.Err() | ||||||
|  | 	} | ||||||
| 	// TODO(zhaoq): Omit the auth info for client now. It is more for | 	// TODO(zhaoq): Omit the auth info for client now. It is more for | ||||||
| 	// information than anything else. | 	// information than anything else. | ||||||
| 	return conn, nil, nil | 	return conn, nil, nil | ||||||
| @@ -181,7 +167,6 @@ func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.D | |||||||
| func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { | func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { | ||||||
| 	conn := tls.Server(rawConn, c.config) | 	conn := tls.Server(rawConn, c.config) | ||||||
| 	if err := conn.Handshake(); err != nil { | 	if err := conn.Handshake(); err != nil { | ||||||
| 		rawConn.Close() |  | ||||||
| 		return nil, nil, err | 		return nil, nil, err | ||||||
| 	} | 	} | ||||||
| 	return conn, TLSInfo{conn.ConnectionState()}, nil | 	return conn, TLSInfo{conn.ConnectionState()}, nil | ||||||
| @@ -189,7 +174,7 @@ func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) | |||||||
|  |  | ||||||
| // NewTLS uses c to construct a TransportCredentials based on TLS. | // NewTLS uses c to construct a TransportCredentials based on TLS. | ||||||
| func NewTLS(c *tls.Config) TransportCredentials { | func NewTLS(c *tls.Config) TransportCredentials { | ||||||
| 	tc := &tlsCreds{c} | 	tc := &tlsCreds{cloneTLSConfig(c)} | ||||||
| 	tc.config.NextProtos = alpnProtoStr | 	tc.config.NextProtos = alpnProtoStr | ||||||
| 	return tc | 	return tc | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								vendor/google.golang.org/grpc/credentials/credentials_util_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/google.golang.org/grpc/credentials/credentials_util_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | // +build go1.7 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * Copyright 2016, Google Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  * notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above | ||||||
|  |  * copyright notice, this list of conditions and the following disclaimer | ||||||
|  |  * in the documentation and/or other materials provided with the | ||||||
|  |  * distribution. | ||||||
|  |  *     * Neither the name of Google Inc. nor the names of its | ||||||
|  |  * contributors may be used to endorse or promote products derived from | ||||||
|  |  * this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package credentials | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // cloneTLSConfig returns a shallow clone of the exported | ||||||
|  | // fields of cfg, ignoring the unexported sync.Once, which | ||||||
|  | // contains a mutex and must not be copied. | ||||||
|  | // | ||||||
|  | // If cfg is nil, a new zero tls.Config is returned. | ||||||
|  | // | ||||||
|  | // TODO replace this function with official clone function. | ||||||
|  | func cloneTLSConfig(cfg *tls.Config) *tls.Config { | ||||||
|  | 	if cfg == nil { | ||||||
|  | 		return &tls.Config{} | ||||||
|  | 	} | ||||||
|  | 	return &tls.Config{ | ||||||
|  | 		Rand:                        cfg.Rand, | ||||||
|  | 		Time:                        cfg.Time, | ||||||
|  | 		Certificates:                cfg.Certificates, | ||||||
|  | 		NameToCertificate:           cfg.NameToCertificate, | ||||||
|  | 		GetCertificate:              cfg.GetCertificate, | ||||||
|  | 		RootCAs:                     cfg.RootCAs, | ||||||
|  | 		NextProtos:                  cfg.NextProtos, | ||||||
|  | 		ServerName:                  cfg.ServerName, | ||||||
|  | 		ClientAuth:                  cfg.ClientAuth, | ||||||
|  | 		ClientCAs:                   cfg.ClientCAs, | ||||||
|  | 		InsecureSkipVerify:          cfg.InsecureSkipVerify, | ||||||
|  | 		CipherSuites:                cfg.CipherSuites, | ||||||
|  | 		PreferServerCipherSuites:    cfg.PreferServerCipherSuites, | ||||||
|  | 		SessionTicketsDisabled:      cfg.SessionTicketsDisabled, | ||||||
|  | 		SessionTicketKey:            cfg.SessionTicketKey, | ||||||
|  | 		ClientSessionCache:          cfg.ClientSessionCache, | ||||||
|  | 		MinVersion:                  cfg.MinVersion, | ||||||
|  | 		MaxVersion:                  cfg.MaxVersion, | ||||||
|  | 		CurvePreferences:            cfg.CurvePreferences, | ||||||
|  | 		DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, | ||||||
|  | 		Renegotiation:               cfg.Renegotiation, | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										74
									
								
								vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/google.golang.org/grpc/credentials/credentials_util_pre_go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | // +build !go1.7 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * Copyright 2016, Google Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  * notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above | ||||||
|  |  * copyright notice, this list of conditions and the following disclaimer | ||||||
|  |  * in the documentation and/or other materials provided with the | ||||||
|  |  * distribution. | ||||||
|  |  *     * Neither the name of Google Inc. nor the names of its | ||||||
|  |  * contributors may be used to endorse or promote products derived from | ||||||
|  |  * this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package credentials | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // cloneTLSConfig returns a shallow clone of the exported | ||||||
|  | // fields of cfg, ignoring the unexported sync.Once, which | ||||||
|  | // contains a mutex and must not be copied. | ||||||
|  | // | ||||||
|  | // If cfg is nil, a new zero tls.Config is returned. | ||||||
|  | // | ||||||
|  | // TODO replace this function with official clone function. | ||||||
|  | func cloneTLSConfig(cfg *tls.Config) *tls.Config { | ||||||
|  | 	if cfg == nil { | ||||||
|  | 		return &tls.Config{} | ||||||
|  | 	} | ||||||
|  | 	return &tls.Config{ | ||||||
|  | 		Rand:                     cfg.Rand, | ||||||
|  | 		Time:                     cfg.Time, | ||||||
|  | 		Certificates:             cfg.Certificates, | ||||||
|  | 		NameToCertificate:        cfg.NameToCertificate, | ||||||
|  | 		GetCertificate:           cfg.GetCertificate, | ||||||
|  | 		RootCAs:                  cfg.RootCAs, | ||||||
|  | 		NextProtos:               cfg.NextProtos, | ||||||
|  | 		ServerName:               cfg.ServerName, | ||||||
|  | 		ClientAuth:               cfg.ClientAuth, | ||||||
|  | 		ClientCAs:                cfg.ClientCAs, | ||||||
|  | 		InsecureSkipVerify:       cfg.InsecureSkipVerify, | ||||||
|  | 		CipherSuites:             cfg.CipherSuites, | ||||||
|  | 		PreferServerCipherSuites: cfg.PreferServerCipherSuites, | ||||||
|  | 		SessionTicketsDisabled:   cfg.SessionTicketsDisabled, | ||||||
|  | 		SessionTicketKey:         cfg.SessionTicketKey, | ||||||
|  | 		ClientSessionCache:       cfg.ClientSessionCache, | ||||||
|  | 		MinVersion:               cfg.MinVersion, | ||||||
|  | 		MaxVersion:               cfg.MaxVersion, | ||||||
|  | 		CurvePreferences:         cfg.CurvePreferences, | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								vendor/google.golang.org/grpc/metadata/metadata.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/google.golang.org/grpc/metadata/metadata.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -60,15 +60,21 @@ func encodeKeyValue(k, v string) (string, string) { | |||||||
|  |  | ||||||
| // DecodeKeyValue returns the original key and value corresponding to the | // DecodeKeyValue returns the original key and value corresponding to the | ||||||
| // encoded data in k, v. | // encoded data in k, v. | ||||||
|  | // If k is a binary header and v contains comma, v is split on comma before decoded, | ||||||
|  | // and the decoded v will be joined with comma before returned. | ||||||
| func DecodeKeyValue(k, v string) (string, string, error) { | func DecodeKeyValue(k, v string) (string, string, error) { | ||||||
| 	if !strings.HasSuffix(k, binHdrSuffix) { | 	if !strings.HasSuffix(k, binHdrSuffix) { | ||||||
| 		return k, v, nil | 		return k, v, nil | ||||||
| 	} | 	} | ||||||
| 	val, err := base64.StdEncoding.DecodeString(v) | 	vvs := strings.Split(v, ",") | ||||||
|  | 	for i, vv := range vvs { | ||||||
|  | 		val, err := base64.StdEncoding.DecodeString(vv) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return "", "", err | 			return "", "", err | ||||||
| 		} | 		} | ||||||
| 	return k, string(val), nil | 		vvs[i] = string(val) | ||||||
|  | 	} | ||||||
|  | 	return k, strings.Join(vvs, ","), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // MD is a mapping from metadata keys to values. Users should use the following | // MD is a mapping from metadata keys to values. Users should use the following | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								vendor/google.golang.org/grpc/rpc_util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/google.golang.org/grpc/rpc_util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -227,7 +227,7 @@ type parser struct { | |||||||
| // No other error values or types must be returned, which also means | // No other error values or types must be returned, which also means | ||||||
| // that the underlying io.Reader must not return an incompatible | // that the underlying io.Reader must not return an incompatible | ||||||
| // error. | // error. | ||||||
| func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) { | func (p *parser) recvMsg(maxMsgSize int) (pf payloadFormat, msg []byte, err error) { | ||||||
| 	if _, err := io.ReadFull(p.r, p.header[:]); err != nil { | 	if _, err := io.ReadFull(p.r, p.header[:]); err != nil { | ||||||
| 		return 0, nil, err | 		return 0, nil, err | ||||||
| 	} | 	} | ||||||
| @@ -238,6 +238,9 @@ func (p *parser) recvMsg() (pf payloadFormat, msg []byte, err error) { | |||||||
| 	if length == 0 { | 	if length == 0 { | ||||||
| 		return pf, nil, nil | 		return pf, nil, nil | ||||||
| 	} | 	} | ||||||
|  | 	if length > uint32(maxMsgSize) { | ||||||
|  | 		return 0, nil, Errorf(codes.Internal, "grpc: received message length %d exceeding the max size %d", length, maxMsgSize) | ||||||
|  | 	} | ||||||
| 	// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead | 	// TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead | ||||||
| 	// of making it for each message: | 	// of making it for each message: | ||||||
| 	msg = make([]byte, int(length)) | 	msg = make([]byte, int(length)) | ||||||
| @@ -308,8 +311,8 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, dc Decompressor) er | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}) error { | func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{}, maxMsgSize int) error { | ||||||
| 	pf, d, err := p.recvMsg() | 	pf, d, err := p.recvMsg(maxMsgSize) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -319,11 +322,16 @@ func recv(p *parser, c Codec, s *transport.Stream, dc Decompressor, m interface{ | |||||||
| 	if pf == compressionMade { | 	if pf == compressionMade { | ||||||
| 		d, err = dc.Do(bytes.NewReader(d)) | 		d, err = dc.Do(bytes.NewReader(d)) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return transport.StreamErrorf(codes.Internal, "grpc: failed to decompress the received message %v", err) | 			return Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	if len(d) > maxMsgSize { | ||||||
|  | 		// TODO: Revisit the error code. Currently keep it consistent with java | ||||||
|  | 		// implementation. | ||||||
|  | 		return Errorf(codes.Internal, "grpc: received a message of %d bytes exceeding %d limit", len(d), maxMsgSize) | ||||||
|  | 	} | ||||||
| 	if err := c.Unmarshal(d, m); err != nil { | 	if err := c.Unmarshal(d, m); err != nil { | ||||||
| 		return transport.StreamErrorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) | 		return Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										75
									
								
								vendor/google.golang.org/grpc/server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										75
									
								
								vendor/google.golang.org/grpc/server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -92,6 +92,10 @@ type Server struct { | |||||||
| 	mu    sync.Mutex // guards following | 	mu    sync.Mutex // guards following | ||||||
| 	lis   map[net.Listener]bool | 	lis   map[net.Listener]bool | ||||||
| 	conns map[io.Closer]bool | 	conns map[io.Closer]bool | ||||||
|  | 	drain bool | ||||||
|  | 	// A CondVar to let GracefulStop() blocks until all the pending RPCs are finished | ||||||
|  | 	// and all the transport goes away. | ||||||
|  | 	cv     *sync.Cond | ||||||
| 	m      map[string]*service // service name -> service info | 	m      map[string]*service // service name -> service info | ||||||
| 	events trace.EventLog | 	events trace.EventLog | ||||||
| } | } | ||||||
| @@ -101,12 +105,15 @@ type options struct { | |||||||
| 	codec                Codec | 	codec                Codec | ||||||
| 	cp                   Compressor | 	cp                   Compressor | ||||||
| 	dc                   Decompressor | 	dc                   Decompressor | ||||||
|  | 	maxMsgSize           int | ||||||
| 	unaryInt             UnaryServerInterceptor | 	unaryInt             UnaryServerInterceptor | ||||||
| 	streamInt            StreamServerInterceptor | 	streamInt            StreamServerInterceptor | ||||||
| 	maxConcurrentStreams uint32 | 	maxConcurrentStreams uint32 | ||||||
| 	useHandlerImpl       bool // use http.Handler-based server | 	useHandlerImpl       bool // use http.Handler-based server | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var defaultMaxMsgSize = 1024 * 1024 * 4 // use 4MB as the default message size limit | ||||||
|  |  | ||||||
| // A ServerOption sets options. | // A ServerOption sets options. | ||||||
| type ServerOption func(*options) | type ServerOption func(*options) | ||||||
|  |  | ||||||
| @@ -117,20 +124,28 @@ func CustomCodec(codec Codec) ServerOption { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // RPCCompressor returns a ServerOption that sets a compressor for outbound message. | // RPCCompressor returns a ServerOption that sets a compressor for outbound messages. | ||||||
| func RPCCompressor(cp Compressor) ServerOption { | func RPCCompressor(cp Compressor) ServerOption { | ||||||
| 	return func(o *options) { | 	return func(o *options) { | ||||||
| 		o.cp = cp | 		o.cp = cp | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // RPCDecompressor returns a ServerOption that sets a decompressor for inbound message. | // RPCDecompressor returns a ServerOption that sets a decompressor for inbound messages. | ||||||
| func RPCDecompressor(dc Decompressor) ServerOption { | func RPCDecompressor(dc Decompressor) ServerOption { | ||||||
| 	return func(o *options) { | 	return func(o *options) { | ||||||
| 		o.dc = dc | 		o.dc = dc | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // MaxMsgSize returns a ServerOption to set the max message size in bytes for inbound mesages. | ||||||
|  | // If this is not set, gRPC uses the default 4MB. | ||||||
|  | func MaxMsgSize(m int) ServerOption { | ||||||
|  | 	return func(o *options) { | ||||||
|  | 		o.maxMsgSize = m | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number | // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number | ||||||
| // of concurrent streams to each ServerTransport. | // of concurrent streams to each ServerTransport. | ||||||
| func MaxConcurrentStreams(n uint32) ServerOption { | func MaxConcurrentStreams(n uint32) ServerOption { | ||||||
| @@ -173,6 +188,7 @@ func StreamInterceptor(i StreamServerInterceptor) ServerOption { | |||||||
| // started to accept requests yet. | // started to accept requests yet. | ||||||
| func NewServer(opt ...ServerOption) *Server { | func NewServer(opt ...ServerOption) *Server { | ||||||
| 	var opts options | 	var opts options | ||||||
|  | 	opts.maxMsgSize = defaultMaxMsgSize | ||||||
| 	for _, o := range opt { | 	for _, o := range opt { | ||||||
| 		o(&opts) | 		o(&opts) | ||||||
| 	} | 	} | ||||||
| @@ -186,6 +202,7 @@ func NewServer(opt ...ServerOption) *Server { | |||||||
| 		conns: make(map[io.Closer]bool), | 		conns: make(map[io.Closer]bool), | ||||||
| 		m:     make(map[string]*service), | 		m:     make(map[string]*service), | ||||||
| 	} | 	} | ||||||
|  | 	s.cv = sync.NewCond(&s.mu) | ||||||
| 	if EnableTracing { | 	if EnableTracing { | ||||||
| 		_, file, line, _ := runtime.Caller(1) | 		_, file, line, _ := runtime.Caller(1) | ||||||
| 		s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) | 		s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) | ||||||
| @@ -264,8 +281,8 @@ type ServiceInfo struct { | |||||||
|  |  | ||||||
| // GetServiceInfo returns a map from service names to ServiceInfo. | // GetServiceInfo returns a map from service names to ServiceInfo. | ||||||
| // Service names include the package names, in the form of <package>.<service>. | // Service names include the package names, in the form of <package>.<service>. | ||||||
| func (s *Server) GetServiceInfo() map[string]*ServiceInfo { | func (s *Server) GetServiceInfo() map[string]ServiceInfo { | ||||||
| 	ret := make(map[string]*ServiceInfo) | 	ret := make(map[string]ServiceInfo) | ||||||
| 	for n, srv := range s.m { | 	for n, srv := range s.m { | ||||||
| 		methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd)) | 		methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd)) | ||||||
| 		for m := range srv.md { | 		for m := range srv.md { | ||||||
| @@ -283,7 +300,7 @@ func (s *Server) GetServiceInfo() map[string]*ServiceInfo { | |||||||
| 			}) | 			}) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ret[n] = &ServiceInfo{ | 		ret[n] = ServiceInfo{ | ||||||
| 			Methods:  methods, | 			Methods:  methods, | ||||||
| 			Metadata: srv.mdata, | 			Metadata: srv.mdata, | ||||||
| 		} | 		} | ||||||
| @@ -468,7 +485,7 @@ func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Strea | |||||||
| func (s *Server) addConn(c io.Closer) bool { | func (s *Server) addConn(c io.Closer) bool { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 	if s.conns == nil { | 	if s.conns == nil || s.drain { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
| 	s.conns[c] = true | 	s.conns[c] = true | ||||||
| @@ -480,6 +497,7 @@ func (s *Server) removeConn(c io.Closer) { | |||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 	if s.conns != nil { | 	if s.conns != nil { | ||||||
| 		delete(s.conns, c) | 		delete(s.conns, c) | ||||||
|  | 		s.cv.Signal() | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -520,7 +538,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. | |||||||
| 	} | 	} | ||||||
| 	p := &parser{r: stream} | 	p := &parser{r: stream} | ||||||
| 	for { | 	for { | ||||||
| 		pf, req, err := p.recvMsg() | 		pf, req, err := p.recvMsg(s.opts.maxMsgSize) | ||||||
| 		if err == io.EOF { | 		if err == io.EOF { | ||||||
| 			// The entire stream is done (for unary RPC only). | 			// The entire stream is done (for unary RPC only). | ||||||
| 			return err | 			return err | ||||||
| @@ -530,6 +548,10 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. | |||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			switch err := err.(type) { | 			switch err := err.(type) { | ||||||
|  | 			case *rpcError: | ||||||
|  | 				if err := t.WriteStatus(stream, err.code, err.desc); err != nil { | ||||||
|  | 					grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) | ||||||
|  | 				} | ||||||
| 			case transport.ConnectionError: | 			case transport.ConnectionError: | ||||||
| 				// Nothing to do here. | 				// Nothing to do here. | ||||||
| 			case transport.StreamError: | 			case transport.StreamError: | ||||||
| @@ -569,6 +591,12 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. | |||||||
| 					return err | 					return err | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 			if len(req) > s.opts.maxMsgSize { | ||||||
|  | 				// TODO: Revisit the error code. Currently keep it consistent with | ||||||
|  | 				// java implementation. | ||||||
|  | 				statusCode = codes.Internal | ||||||
|  | 				statusDesc = fmt.Sprintf("grpc: server received a message of %d bytes exceeding %d limit", len(req), s.opts.maxMsgSize) | ||||||
|  | 			} | ||||||
| 			if err := s.opts.codec.Unmarshal(req, v); err != nil { | 			if err := s.opts.codec.Unmarshal(req, v); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @@ -634,6 +662,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp | |||||||
| 		codec:      s.opts.codec, | 		codec:      s.opts.codec, | ||||||
| 		cp:         s.opts.cp, | 		cp:         s.opts.cp, | ||||||
| 		dc:         s.opts.dc, | 		dc:         s.opts.dc, | ||||||
|  | 		maxMsgSize: s.opts.maxMsgSize, | ||||||
| 		trInfo:     trInfo, | 		trInfo:     trInfo, | ||||||
| 	} | 	} | ||||||
| 	if ss.cp != nil { | 	if ss.cp != nil { | ||||||
| @@ -766,14 +795,16 @@ func (s *Server) Stop() { | |||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	listeners := s.lis | 	listeners := s.lis | ||||||
| 	s.lis = nil | 	s.lis = nil | ||||||
| 	cs := s.conns | 	st := s.conns | ||||||
| 	s.conns = nil | 	s.conns = nil | ||||||
|  | 	// interrupt GracefulStop if Stop and GracefulStop are called concurrently. | ||||||
|  | 	s.cv.Signal() | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
|  |  | ||||||
| 	for lis := range listeners { | 	for lis := range listeners { | ||||||
| 		lis.Close() | 		lis.Close() | ||||||
| 	} | 	} | ||||||
| 	for c := range cs { | 	for c := range st { | ||||||
| 		c.Close() | 		c.Close() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -785,6 +816,32 @@ func (s *Server) Stop() { | |||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GracefulStop stops the gRPC server gracefully. It stops the server to accept new | ||||||
|  | // connections and RPCs and blocks until all the pending RPCs are finished. | ||||||
|  | func (s *Server) GracefulStop() { | ||||||
|  | 	s.mu.Lock() | ||||||
|  | 	defer s.mu.Unlock() | ||||||
|  | 	if s.drain == true || s.conns == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	s.drain = true | ||||||
|  | 	for lis := range s.lis { | ||||||
|  | 		lis.Close() | ||||||
|  | 	} | ||||||
|  | 	s.lis = nil | ||||||
|  | 	for c := range s.conns { | ||||||
|  | 		c.(transport.ServerTransport).Drain() | ||||||
|  | 	} | ||||||
|  | 	for len(s.conns) != 0 { | ||||||
|  | 		s.cv.Wait() | ||||||
|  | 	} | ||||||
|  | 	s.conns = nil | ||||||
|  | 	if s.events != nil { | ||||||
|  | 		s.events.Finish() | ||||||
|  | 		s.events = nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	internal.TestingCloseConns = func(arg interface{}) { | 	internal.TestingCloseConns = func(arg interface{}) { | ||||||
| 		arg.(*Server).testingCloseConns() | 		arg.(*Server).testingCloseConns() | ||||||
|   | |||||||
							
								
								
									
										115
									
								
								vendor/google.golang.org/grpc/stream.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										115
									
								
								vendor/google.golang.org/grpc/stream.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -37,6 +37,7 @@ import ( | |||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"math" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -84,12 +85,9 @@ type ClientStream interface { | |||||||
| 	// Header returns the header metadata received from the server if there | 	// Header returns the header metadata received from the server if there | ||||||
| 	// is any. It blocks if the metadata is not ready to read. | 	// is any. It blocks if the metadata is not ready to read. | ||||||
| 	Header() (metadata.MD, error) | 	Header() (metadata.MD, error) | ||||||
| 	// Trailer returns the trailer metadata from the server. It must be called | 	// Trailer returns the trailer metadata from the server, if there is any. | ||||||
| 	// after stream.Recv() returns non-nil error (including io.EOF) for | 	// It must only be called after stream.CloseAndRecv has returned, or | ||||||
| 	// bi-directional streaming and server streaming or stream.CloseAndRecv() | 	// stream.Recv has returned a non-nil error (including io.EOF). | ||||||
| 	// returns for client streaming in order to receive trailer metadata if |  | ||||||
| 	// present. Otherwise, it could returns an empty MD even though trailer |  | ||||||
| 	// is present. |  | ||||||
| 	Trailer() metadata.MD | 	Trailer() metadata.MD | ||||||
| 	// CloseSend closes the send direction of the stream. It closes the stream | 	// CloseSend closes the send direction of the stream. It closes the stream | ||||||
| 	// when non-nil error is met. | 	// when non-nil error is met. | ||||||
| @@ -99,11 +97,10 @@ type ClientStream interface { | |||||||
|  |  | ||||||
| // NewClientStream creates a new Stream for the client side. This is called | // NewClientStream creates a new Stream for the client side. This is called | ||||||
| // by generated code. | // by generated code. | ||||||
| func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) { | func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { | ||||||
| 	var ( | 	var ( | ||||||
| 		t   transport.ClientTransport | 		t   transport.ClientTransport | ||||||
| 		s   *transport.Stream | 		s   *transport.Stream | ||||||
| 		err error |  | ||||||
| 		put func() | 		put func() | ||||||
| 	) | 	) | ||||||
| 	c := defaultCallInfo | 	c := defaultCallInfo | ||||||
| @@ -120,27 +117,24 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth | |||||||
| 	if cc.dopts.cp != nil { | 	if cc.dopts.cp != nil { | ||||||
| 		callHdr.SendCompress = cc.dopts.cp.Type() | 		callHdr.SendCompress = cc.dopts.cp.Type() | ||||||
| 	} | 	} | ||||||
| 	cs := &clientStream{ | 	var trInfo traceInfo | ||||||
| 		opts:    opts, | 	if EnableTracing { | ||||||
| 		c:       c, | 		trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) | ||||||
| 		desc:    desc, | 		trInfo.firstLine.client = true | ||||||
| 		codec:   cc.dopts.codec, |  | ||||||
| 		cp:      cc.dopts.cp, |  | ||||||
| 		dc:      cc.dopts.dc, |  | ||||||
| 		tracing: EnableTracing, |  | ||||||
| 	} |  | ||||||
| 	if cc.dopts.cp != nil { |  | ||||||
| 		callHdr.SendCompress = cc.dopts.cp.Type() |  | ||||||
| 		cs.cbuf = new(bytes.Buffer) |  | ||||||
| 	} |  | ||||||
| 	if cs.tracing { |  | ||||||
| 		cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) |  | ||||||
| 		cs.trInfo.firstLine.client = true |  | ||||||
| 		if deadline, ok := ctx.Deadline(); ok { | 		if deadline, ok := ctx.Deadline(); ok { | ||||||
| 			cs.trInfo.firstLine.deadline = deadline.Sub(time.Now()) | 			trInfo.firstLine.deadline = deadline.Sub(time.Now()) | ||||||
| 		} | 		} | ||||||
| 		cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false) | 		trInfo.tr.LazyLog(&trInfo.firstLine, false) | ||||||
| 		ctx = trace.NewContext(ctx, cs.trInfo.tr) | 		ctx = trace.NewContext(ctx, trInfo.tr) | ||||||
|  | 		defer func() { | ||||||
|  | 			if err != nil { | ||||||
|  | 				// Need to call tr.finish() if error is returned. | ||||||
|  | 				// Because tr will not be returned to caller. | ||||||
|  | 				trInfo.tr.LazyPrintf("RPC: [%v]", err) | ||||||
|  | 				trInfo.tr.SetError() | ||||||
|  | 				trInfo.tr.Finish() | ||||||
|  | 			} | ||||||
|  | 		}() | ||||||
| 	} | 	} | ||||||
| 	gopts := BalancerGetOptions{ | 	gopts := BalancerGetOptions{ | ||||||
| 		BlockingWait: !c.failFast, | 		BlockingWait: !c.failFast, | ||||||
| @@ -152,9 +146,9 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth | |||||||
| 			if _, ok := err.(*rpcError); ok { | 			if _, ok := err.(*rpcError); ok { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 			if err == errConnClosing { | 			if err == errConnClosing || err == errConnUnavailable { | ||||||
| 				if c.failFast { | 				if c.failFast { | ||||||
| 					return nil, Errorf(codes.Unavailable, "%v", errConnClosing) | 					return nil, Errorf(codes.Unavailable, "%v", err) | ||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| @@ -168,9 +162,8 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth | |||||||
| 				put() | 				put() | ||||||
| 				put = nil | 				put = nil | ||||||
| 			} | 			} | ||||||
| 			if _, ok := err.(transport.ConnectionError); ok { | 			if _, ok := err.(transport.ConnectionError); ok || err == transport.ErrStreamDrain { | ||||||
| 				if c.failFast { | 				if c.failFast { | ||||||
| 					cs.finish(err) |  | ||||||
| 					return nil, toRPCErr(err) | 					return nil, toRPCErr(err) | ||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| @@ -179,16 +172,43 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth | |||||||
| 		} | 		} | ||||||
| 		break | 		break | ||||||
| 	} | 	} | ||||||
| 	cs.put = put | 	cs := &clientStream{ | ||||||
| 	cs.t = t | 		opts:  opts, | ||||||
| 	cs.s = s | 		c:     c, | ||||||
| 	cs.p = &parser{r: s} | 		desc:  desc, | ||||||
| 	// Listen on ctx.Done() to detect cancellation when there is no pending | 		codec: cc.dopts.codec, | ||||||
| 	// I/O operations on this stream. | 		cp:    cc.dopts.cp, | ||||||
|  | 		dc:    cc.dopts.dc, | ||||||
|  |  | ||||||
|  | 		put: put, | ||||||
|  | 		t:   t, | ||||||
|  | 		s:   s, | ||||||
|  | 		p:   &parser{r: s}, | ||||||
|  |  | ||||||
|  | 		tracing: EnableTracing, | ||||||
|  | 		trInfo:  trInfo, | ||||||
|  | 	} | ||||||
|  | 	if cc.dopts.cp != nil { | ||||||
|  | 		cs.cbuf = new(bytes.Buffer) | ||||||
|  | 	} | ||||||
|  | 	// Listen on ctx.Done() to detect cancellation and s.Done() to detect normal termination | ||||||
|  | 	// when there is no pending I/O operations on this stream. | ||||||
| 	go func() { | 	go func() { | ||||||
| 		select { | 		select { | ||||||
| 		case <-t.Error(): | 		case <-t.Error(): | ||||||
| 			// Incur transport error, simply exit. | 			// Incur transport error, simply exit. | ||||||
|  | 		case <-s.Done(): | ||||||
|  | 			// TODO: The trace of the RPC is terminated here when there is no pending | ||||||
|  | 			// I/O, which is probably not the optimal solution. | ||||||
|  | 			if s.StatusCode() == codes.OK { | ||||||
|  | 				cs.finish(nil) | ||||||
|  | 			} else { | ||||||
|  | 				cs.finish(Errorf(s.StatusCode(), "%s", s.StatusDesc())) | ||||||
|  | 			} | ||||||
|  | 			cs.closeTransportStream(nil) | ||||||
|  | 		case <-s.GoAway(): | ||||||
|  | 			cs.finish(errConnDrain) | ||||||
|  | 			cs.closeTransportStream(errConnDrain) | ||||||
| 		case <-s.Context().Done(): | 		case <-s.Context().Done(): | ||||||
| 			err := s.Context().Err() | 			err := s.Context().Err() | ||||||
| 			cs.finish(err) | 			cs.finish(err) | ||||||
| @@ -251,7 +271,17 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			cs.finish(err) | 			cs.finish(err) | ||||||
| 		} | 		} | ||||||
| 		if err == nil || err == io.EOF { | 		if err == nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if err == io.EOF { | ||||||
|  | 			// Specialize the process for server streaming. SendMesg is only called | ||||||
|  | 			// once when creating the stream object. io.EOF needs to be skipped when | ||||||
|  | 			// the rpc is early finished (before the stream object is created.). | ||||||
|  | 			// TODO: It is probably better to move this into the generated code. | ||||||
|  | 			if !cs.desc.ClientStreams && cs.desc.ServerStreams { | ||||||
|  | 				err = nil | ||||||
|  | 			} | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		if _, ok := err.(transport.ConnectionError); !ok { | 		if _, ok := err.(transport.ConnectionError); !ok { | ||||||
| @@ -272,7 +302,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (cs *clientStream) RecvMsg(m interface{}) (err error) { | func (cs *clientStream) RecvMsg(m interface{}) (err error) { | ||||||
| 	err = recv(cs.p, cs.codec, cs.s, cs.dc, m) | 	err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		// err != nil indicates the termination of the stream. | 		// err != nil indicates the termination of the stream. | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @@ -291,7 +321,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		// Special handling for client streaming rpc. | 		// Special handling for client streaming rpc. | ||||||
| 		err = recv(cs.p, cs.codec, cs.s, cs.dc, m) | 		err = recv(cs.p, cs.codec, cs.s, cs.dc, m, math.MaxInt32) | ||||||
| 		cs.closeTransportStream(err) | 		cs.closeTransportStream(err) | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| 			return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) | 			return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) | ||||||
| @@ -326,7 +356,7 @@ func (cs *clientStream) CloseSend() (err error) { | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
| 	if err == nil || err == io.EOF { | 	if err == nil || err == io.EOF { | ||||||
| 		return | 		return nil | ||||||
| 	} | 	} | ||||||
| 	if _, ok := err.(transport.ConnectionError); !ok { | 	if _, ok := err.(transport.ConnectionError); !ok { | ||||||
| 		cs.closeTransportStream(err) | 		cs.closeTransportStream(err) | ||||||
| @@ -392,6 +422,7 @@ type serverStream struct { | |||||||
| 	cp         Compressor | 	cp         Compressor | ||||||
| 	dc         Decompressor | 	dc         Decompressor | ||||||
| 	cbuf       *bytes.Buffer | 	cbuf       *bytes.Buffer | ||||||
|  | 	maxMsgSize int | ||||||
| 	statusCode codes.Code | 	statusCode codes.Code | ||||||
| 	statusDesc string | 	statusDesc string | ||||||
| 	trInfo     *traceInfo | 	trInfo     *traceInfo | ||||||
| @@ -458,5 +489,5 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { | |||||||
| 			ss.mu.Unlock() | 			ss.mu.Unlock() | ||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
| 	return recv(ss.p, ss.codec, ss.s, ss.dc, m) | 	return recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxMsgSize) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								vendor/google.golang.org/grpc/transport/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/google.golang.org/grpc/transport/control.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -72,6 +72,11 @@ type resetStream struct { | |||||||
|  |  | ||||||
| func (*resetStream) item() {} | func (*resetStream) item() {} | ||||||
|  |  | ||||||
|  | type goAway struct { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (*goAway) item() {} | ||||||
|  |  | ||||||
| type flushIO struct { | type flushIO struct { | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								vendor/google.golang.org/grpc/transport/go16.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/google.golang.org/grpc/transport/go16.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // +build go1.6,!go1.7 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Copyright 2016, Google Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  * notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above | ||||||
|  |  * copyright notice, this list of conditions and the following disclaimer | ||||||
|  |  * in the documentation and/or other materials provided with the | ||||||
|  |  * distribution. | ||||||
|  |  *     * Neither the name of Google Inc. nor the names of its | ||||||
|  |  * contributors may be used to endorse or promote products derived from | ||||||
|  |  * this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package transport | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // dialContext connects to the address on the named network. | ||||||
|  | func dialContext(ctx context.Context, network, address string) (net.Conn, error) { | ||||||
|  | 	return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address) | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								vendor/google.golang.org/grpc/transport/go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/google.golang.org/grpc/transport/go17.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // +build go1.7 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Copyright 2016, Google Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  * notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above | ||||||
|  |  * copyright notice, this list of conditions and the following disclaimer | ||||||
|  |  * in the documentation and/or other materials provided with the | ||||||
|  |  * distribution. | ||||||
|  |  *     * Neither the name of Google Inc. nor the names of its | ||||||
|  |  * contributors may be used to endorse or promote products derived from | ||||||
|  |  * this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package transport | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // dialContext connects to the address on the named network. | ||||||
|  | func dialContext(ctx context.Context, network, address string) (net.Conn, error) { | ||||||
|  | 	return (&net.Dialer{}).DialContext(ctx, network, address) | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								vendor/google.golang.org/grpc/transport/handler_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/google.golang.org/grpc/transport/handler_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -83,7 +83,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTr | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if v := r.Header.Get("grpc-timeout"); v != "" { | 	if v := r.Header.Get("grpc-timeout"); v != "" { | ||||||
| 		to, err := timeoutDecode(v) | 		to, err := decodeTimeout(v) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, StreamErrorf(codes.Internal, "malformed time-out: %v", err) | 			return nil, StreamErrorf(codes.Internal, "malformed time-out: %v", err) | ||||||
| 		} | 		} | ||||||
| @@ -194,7 +194,7 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, statusCode codes.Code, | |||||||
| 		h := ht.rw.Header() | 		h := ht.rw.Header() | ||||||
| 		h.Set("Grpc-Status", fmt.Sprintf("%d", statusCode)) | 		h.Set("Grpc-Status", fmt.Sprintf("%d", statusCode)) | ||||||
| 		if statusDesc != "" { | 		if statusDesc != "" { | ||||||
| 			h.Set("Grpc-Message", statusDesc) | 			h.Set("Grpc-Message", encodeGrpcMessage(statusDesc)) | ||||||
| 		} | 		} | ||||||
| 		if md := s.Trailer(); len(md) > 0 { | 		if md := s.Trailer(); len(md) > 0 { | ||||||
| 			for k, vv := range md { | 			for k, vv := range md { | ||||||
| @@ -370,6 +370,10 @@ func (ht *serverHandlerTransport) runStream() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ht *serverHandlerTransport) Drain() { | ||||||
|  | 	panic("Drain() is not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
| // mapRecvMsgError returns the non-nil err into the appropriate | // mapRecvMsgError returns the non-nil err into the appropriate | ||||||
| // error value as expected by callers of *grpc.parser.recvMsg. | // error value as expected by callers of *grpc.parser.recvMsg. | ||||||
| // In particular, in can only be: | // In particular, in can only be: | ||||||
|   | |||||||
							
								
								
									
										202
									
								
								vendor/google.golang.org/grpc/transport/http2_client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										202
									
								
								vendor/google.golang.org/grpc/transport/http2_client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -35,6 +35,7 @@ package transport | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"math" | 	"math" | ||||||
| 	"net" | 	"net" | ||||||
| @@ -71,6 +72,9 @@ type http2Client struct { | |||||||
| 	shutdownChan chan struct{} | 	shutdownChan chan struct{} | ||||||
| 	// errorChan is closed to notify the I/O error to the caller. | 	// errorChan is closed to notify the I/O error to the caller. | ||||||
| 	errorChan chan struct{} | 	errorChan chan struct{} | ||||||
|  | 	// goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor) | ||||||
|  | 	// that the server sent GoAway on this transport. | ||||||
|  | 	goAway chan struct{} | ||||||
|  |  | ||||||
| 	framer *framer | 	framer *framer | ||||||
| 	hBuf   *bytes.Buffer  // the buffer for HPACK encoding | 	hBuf   *bytes.Buffer  // the buffer for HPACK encoding | ||||||
| @@ -97,41 +101,44 @@ type http2Client struct { | |||||||
| 	maxStreams int | 	maxStreams int | ||||||
| 	// the per-stream outbound flow control window size set by the peer. | 	// the per-stream outbound flow control window size set by the peer. | ||||||
| 	streamSendQuota uint32 | 	streamSendQuota uint32 | ||||||
|  | 	// goAwayID records the Last-Stream-ID in the GoAway frame from the server. | ||||||
|  | 	goAwayID uint32 | ||||||
|  | 	// prevGoAway ID records the Last-Stream-ID in the previous GOAway frame. | ||||||
|  | 	prevGoAwayID uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func dial(fn func(context.Context, string) (net.Conn, error), ctx context.Context, addr string) (net.Conn, error) { | ||||||
|  | 	if fn != nil { | ||||||
|  | 		return fn(ctx, addr) | ||||||
|  | 	} | ||||||
|  | 	return dialContext(ctx, "tcp", addr) | ||||||
| } | } | ||||||
|  |  | ||||||
| // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 | // newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2 | ||||||
| // and starts to receive messages on it. Non-nil error returns if construction | // and starts to receive messages on it. Non-nil error returns if construction | ||||||
| // fails. | // fails. | ||||||
| func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err error) { | func newHTTP2Client(ctx context.Context, addr string, opts ConnectOptions) (_ ClientTransport, err error) { | ||||||
| 	if opts.Dialer == nil { |  | ||||||
| 		// Set the default Dialer. |  | ||||||
| 		opts.Dialer = func(addr string, timeout time.Duration) (net.Conn, error) { |  | ||||||
| 			return net.DialTimeout("tcp", addr, timeout) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	scheme := "http" | 	scheme := "http" | ||||||
| 	startT := time.Now() | 	conn, connErr := dial(opts.Dialer, ctx, addr) | ||||||
| 	timeout := opts.Timeout |  | ||||||
| 	conn, connErr := opts.Dialer(addr, timeout) |  | ||||||
| 	if connErr != nil { | 	if connErr != nil { | ||||||
| 		return nil, ConnectionErrorf("transport: %v", connErr) | 		return nil, ConnectionErrorf(true, connErr, "transport: %v", connErr) | ||||||
| 	} | 	} | ||||||
| 	var authInfo credentials.AuthInfo | 	// Any further errors will close the underlying connection | ||||||
| 	if opts.TransportCredentials != nil { | 	defer func(conn net.Conn) { | ||||||
| 		scheme = "https" |  | ||||||
| 		if timeout > 0 { |  | ||||||
| 			timeout -= time.Since(startT) |  | ||||||
| 		} |  | ||||||
| 		conn, authInfo, connErr = opts.TransportCredentials.ClientHandshake(addr, conn, timeout) |  | ||||||
| 	} |  | ||||||
| 	if connErr != nil { |  | ||||||
| 		return nil, ConnectionErrorf("transport: %v", connErr) |  | ||||||
| 	} |  | ||||||
| 	defer func() { |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			conn.Close() | 			conn.Close() | ||||||
| 		} | 		} | ||||||
| 	}() | 	}(conn) | ||||||
|  | 	var authInfo credentials.AuthInfo | ||||||
|  | 	if creds := opts.TransportCredentials; creds != nil { | ||||||
|  | 		scheme = "https" | ||||||
|  | 		conn, authInfo, connErr = creds.ClientHandshake(ctx, addr, conn) | ||||||
|  | 	} | ||||||
|  | 	if connErr != nil { | ||||||
|  | 		// Credentials handshake error is not a temporary error (unless the error | ||||||
|  | 		// was the connection closing). | ||||||
|  | 		return nil, ConnectionErrorf(connErr == io.EOF, connErr, "transport: %v", connErr) | ||||||
|  | 	} | ||||||
| 	ua := primaryUA | 	ua := primaryUA | ||||||
| 	if opts.UserAgent != "" { | 	if opts.UserAgent != "" { | ||||||
| 		ua = opts.UserAgent + " " + ua | 		ua = opts.UserAgent + " " + ua | ||||||
| @@ -147,6 +154,7 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e | |||||||
| 		writableChan:    make(chan int, 1), | 		writableChan:    make(chan int, 1), | ||||||
| 		shutdownChan:    make(chan struct{}), | 		shutdownChan:    make(chan struct{}), | ||||||
| 		errorChan:       make(chan struct{}), | 		errorChan:       make(chan struct{}), | ||||||
|  | 		goAway:          make(chan struct{}), | ||||||
| 		framer:          newFramer(conn), | 		framer:          newFramer(conn), | ||||||
| 		hBuf:            &buf, | 		hBuf:            &buf, | ||||||
| 		hEnc:            hpack.NewEncoder(&buf), | 		hEnc:            hpack.NewEncoder(&buf), | ||||||
| @@ -168,11 +176,11 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e | |||||||
| 	n, err := t.conn.Write(clientPreface) | 	n, err := t.conn.Write(clientPreface) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Close() | 		t.Close() | ||||||
| 		return nil, ConnectionErrorf("transport: %v", err) | 		return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 	} | 	} | ||||||
| 	if n != len(clientPreface) { | 	if n != len(clientPreface) { | ||||||
| 		t.Close() | 		t.Close() | ||||||
| 		return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) | 		return nil, ConnectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface)) | ||||||
| 	} | 	} | ||||||
| 	if initialWindowSize != defaultWindowSize { | 	if initialWindowSize != defaultWindowSize { | ||||||
| 		err = t.framer.writeSettings(true, http2.Setting{ | 		err = t.framer.writeSettings(true, http2.Setting{ | ||||||
| @@ -184,13 +192,13 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e | |||||||
| 	} | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Close() | 		t.Close() | ||||||
| 		return nil, ConnectionErrorf("transport: %v", err) | 		return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 	} | 	} | ||||||
| 	// Adjust the connection flow control window if needed. | 	// Adjust the connection flow control window if needed. | ||||||
| 	if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { | 	if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { | ||||||
| 		if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil { | 		if err := t.framer.writeWindowUpdate(true, 0, delta); err != nil { | ||||||
| 			t.Close() | 			t.Close() | ||||||
| 			return nil, ConnectionErrorf("transport: %v", err) | 			return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	go t.controller() | 	go t.controller() | ||||||
| @@ -202,6 +210,8 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { | |||||||
| 	// TODO(zhaoq): Handle uint32 overflow of Stream.id. | 	// TODO(zhaoq): Handle uint32 overflow of Stream.id. | ||||||
| 	s := &Stream{ | 	s := &Stream{ | ||||||
| 		id:            t.nextID, | 		id:            t.nextID, | ||||||
|  | 		done:          make(chan struct{}), | ||||||
|  | 		goAway:        make(chan struct{}), | ||||||
| 		method:        callHdr.Method, | 		method:        callHdr.Method, | ||||||
| 		sendCompress:  callHdr.SendCompress, | 		sendCompress:  callHdr.SendCompress, | ||||||
| 		buf:           newRecvBuffer(), | 		buf:           newRecvBuffer(), | ||||||
| @@ -217,6 +227,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { | |||||||
| 	s.ctx, s.cancel = context.WithCancel(ctx) | 	s.ctx, s.cancel = context.WithCancel(ctx) | ||||||
| 	s.dec = &recvBufferReader{ | 	s.dec = &recvBufferReader{ | ||||||
| 		ctx:    s.ctx, | 		ctx:    s.ctx, | ||||||
|  | 		goAway: s.goAway, | ||||||
| 		recv:   s.buf, | 		recv:   s.buf, | ||||||
| 	} | 	} | ||||||
| 	return s | 	return s | ||||||
| @@ -271,6 +282,10 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return nil, ErrConnClosing | 		return nil, ErrConnClosing | ||||||
| 	} | 	} | ||||||
|  | 	if t.state == draining { | ||||||
|  | 		t.mu.Unlock() | ||||||
|  | 		return nil, ErrStreamDrain | ||||||
|  | 	} | ||||||
| 	if t.state != reachable { | 	if t.state != reachable { | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return nil, ErrConnClosing | 		return nil, ErrConnClosing | ||||||
| @@ -278,7 +293,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 	checkStreamsQuota := t.streamsQuota != nil | 	checkStreamsQuota := t.streamsQuota != nil | ||||||
| 	t.mu.Unlock() | 	t.mu.Unlock() | ||||||
| 	if checkStreamsQuota { | 	if checkStreamsQuota { | ||||||
| 		sq, err := wait(ctx, t.shutdownChan, t.streamsQuota.acquire()) | 		sq, err := wait(ctx, nil, nil, t.shutdownChan, t.streamsQuota.acquire()) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -287,7 +302,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 			t.streamsQuota.add(sq - 1) | 			t.streamsQuota.add(sq - 1) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if _, err := wait(ctx, t.shutdownChan, t.writableChan); err != nil { | 	if _, err := wait(ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 		// Return the quota back now because there is no stream returned to the caller. | 		// Return the quota back now because there is no stream returned to the caller. | ||||||
| 		if _, ok := err.(StreamError); ok && checkStreamsQuota { | 		if _, ok := err.(StreamError); ok && checkStreamsQuota { | ||||||
| 			t.streamsQuota.add(1) | 			t.streamsQuota.add(1) | ||||||
| @@ -295,6 +310,15 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	t.mu.Lock() | 	t.mu.Lock() | ||||||
|  | 	if t.state == draining { | ||||||
|  | 		t.mu.Unlock() | ||||||
|  | 		if checkStreamsQuota { | ||||||
|  | 			t.streamsQuota.add(1) | ||||||
|  | 		} | ||||||
|  | 		// Need to make t writable again so that the rpc in flight can still proceed. | ||||||
|  | 		t.writableChan <- 0 | ||||||
|  | 		return nil, ErrStreamDrain | ||||||
|  | 	} | ||||||
| 	if t.state != reachable { | 	if t.state != reachable { | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return nil, ErrConnClosing | 		return nil, ErrConnClosing | ||||||
| @@ -329,7 +353,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 		t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) | 		t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress}) | ||||||
| 	} | 	} | ||||||
| 	if timeout > 0 { | 	if timeout > 0 { | ||||||
| 		t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: timeoutEncode(timeout)}) | 		t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)}) | ||||||
| 	} | 	} | ||||||
| 	for k, v := range authData { | 	for k, v := range authData { | ||||||
| 		// Capital header names are illegal in HTTP/2. | 		// Capital header names are illegal in HTTP/2. | ||||||
| @@ -384,7 +408,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea | |||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.notifyError(err) | 			t.notifyError(err) | ||||||
| 			return nil, ConnectionErrorf("transport: %v", err) | 			return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	t.writableChan <- 0 | 	t.writableChan <- 0 | ||||||
| @@ -403,22 +427,17 @@ func (t *http2Client) CloseStream(s *Stream, err error) { | |||||||
| 	if t.streamsQuota != nil { | 	if t.streamsQuota != nil { | ||||||
| 		updateStreams = true | 		updateStreams = true | ||||||
| 	} | 	} | ||||||
| 	if t.state == draining && len(t.activeStreams) == 1 { | 	delete(t.activeStreams, s.id) | ||||||
|  | 	if t.state == draining && len(t.activeStreams) == 0 { | ||||||
| 		// The transport is draining and s is the last live stream on t. | 		// The transport is draining and s is the last live stream on t. | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		t.Close() | 		t.Close() | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	delete(t.activeStreams, s.id) |  | ||||||
| 	t.mu.Unlock() | 	t.mu.Unlock() | ||||||
| 	if updateStreams { | 	if updateStreams { | ||||||
| 		t.streamsQuota.add(1) | 		t.streamsQuota.add(1) | ||||||
| 	} | 	} | ||||||
| 	// In case stream sending and receiving are invoked in separate |  | ||||||
| 	// goroutines (e.g., bi-directional streaming), the caller needs |  | ||||||
| 	// to call cancel on the stream to interrupt the blocking on |  | ||||||
| 	// other goroutines. |  | ||||||
| 	s.cancel() |  | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	if q := s.fc.resetPendingData(); q > 0 { | 	if q := s.fc.resetPendingData(); q > 0 { | ||||||
| 		if n := t.fc.onRead(q); n > 0 { | 		if n := t.fc.onRead(q); n > 0 { | ||||||
| @@ -445,13 +464,13 @@ func (t *http2Client) CloseStream(s *Stream, err error) { | |||||||
| // accessed any more. | // accessed any more. | ||||||
| func (t *http2Client) Close() (err error) { | func (t *http2Client) Close() (err error) { | ||||||
| 	t.mu.Lock() | 	t.mu.Lock() | ||||||
| 	if t.state == reachable { |  | ||||||
| 		close(t.errorChan) |  | ||||||
| 	} |  | ||||||
| 	if t.state == closing { | 	if t.state == closing { | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	if t.state == reachable || t.state == draining { | ||||||
|  | 		close(t.errorChan) | ||||||
|  | 	} | ||||||
| 	t.state = closing | 	t.state = closing | ||||||
| 	t.mu.Unlock() | 	t.mu.Unlock() | ||||||
| 	close(t.shutdownChan) | 	close(t.shutdownChan) | ||||||
| @@ -475,10 +494,35 @@ func (t *http2Client) Close() (err error) { | |||||||
|  |  | ||||||
| func (t *http2Client) GracefulClose() error { | func (t *http2Client) GracefulClose() error { | ||||||
| 	t.mu.Lock() | 	t.mu.Lock() | ||||||
| 	if t.state == closing { | 	switch t.state { | ||||||
|  | 	case unreachable: | ||||||
|  | 		// The server may close the connection concurrently. t is not available for | ||||||
|  | 		// any streams. Close it now. | ||||||
|  | 		t.mu.Unlock() | ||||||
|  | 		t.Close() | ||||||
|  | 		return nil | ||||||
|  | 	case closing: | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  | 	// Notify the streams which were initiated after the server sent GOAWAY. | ||||||
|  | 	select { | ||||||
|  | 	case <-t.goAway: | ||||||
|  | 		n := t.prevGoAwayID | ||||||
|  | 		if n == 0 && t.nextID > 1 { | ||||||
|  | 			n = t.nextID - 2 | ||||||
|  | 		} | ||||||
|  | 		m := t.goAwayID + 2 | ||||||
|  | 		if m == 2 { | ||||||
|  | 			m = 1 | ||||||
|  | 		} | ||||||
|  | 		for i := m; i <= n; i += 2 { | ||||||
|  | 			if s, ok := t.activeStreams[i]; ok { | ||||||
|  | 				close(s.goAway) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 	} | ||||||
| 	if t.state == draining { | 	if t.state == draining { | ||||||
| 		t.mu.Unlock() | 		t.mu.Unlock() | ||||||
| 		return nil | 		return nil | ||||||
| @@ -504,15 +548,15 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 			size := http2MaxFrameLen | 			size := http2MaxFrameLen | ||||||
| 			s.sendQuotaPool.add(0) | 			s.sendQuotaPool.add(0) | ||||||
| 			// Wait until the stream has some quota to send the data. | 			// Wait until the stream has some quota to send the data. | ||||||
| 			sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) | 			sq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, s.sendQuotaPool.acquire()) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			t.sendQuotaPool.add(0) | 			t.sendQuotaPool.add(0) | ||||||
| 			// Wait until the transport has some quota to send the data. | 			// Wait until the transport has some quota to send the data. | ||||||
| 			tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) | 			tq, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.sendQuotaPool.acquire()) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				if _, ok := err.(StreamError); ok { | 				if _, ok := err.(StreamError); ok || err == io.EOF { | ||||||
| 					t.sendQuotaPool.cancel() | 					t.sendQuotaPool.cancel() | ||||||
| 				} | 				} | ||||||
| 				return err | 				return err | ||||||
| @@ -544,8 +588,8 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		// Indicate there is a writer who is about to write a data frame. | 		// Indicate there is a writer who is about to write a data frame. | ||||||
| 		t.framer.adjustNumWriters(1) | 		t.framer.adjustNumWriters(1) | ||||||
| 		// Got some quota. Try to acquire writing privilege on the transport. | 		// Got some quota. Try to acquire writing privilege on the transport. | ||||||
| 		if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { | 		if _, err := wait(s.ctx, s.done, s.goAway, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 			if _, ok := err.(StreamError); ok { | 			if _, ok := err.(StreamError); ok || err == io.EOF { | ||||||
| 				// Return the connection quota back. | 				// Return the connection quota back. | ||||||
| 				t.sendQuotaPool.add(len(p)) | 				t.sendQuotaPool.add(len(p)) | ||||||
| 			} | 			} | ||||||
| @@ -578,7 +622,7 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		// invoked. | 		// invoked. | ||||||
| 		if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil { | 		if err := t.framer.writeData(forceFlush, s.id, endStream, p); err != nil { | ||||||
| 			t.notifyError(err) | 			t.notifyError(err) | ||||||
| 			return ConnectionErrorf("transport: %v", err) | 			return ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 		if t.framer.adjustNumWriters(-1) == 0 { | 		if t.framer.adjustNumWriters(-1) == 0 { | ||||||
| 			t.framer.flushWrite() | 			t.framer.flushWrite() | ||||||
| @@ -593,12 +637,8 @@ func (t *http2Client) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 	} | 	} | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	if s.state != streamDone { | 	if s.state != streamDone { | ||||||
| 		if s.state == streamReadDone { |  | ||||||
| 			s.state = streamDone |  | ||||||
| 		} else { |  | ||||||
| 		s.state = streamWriteDone | 		s.state = streamWriteDone | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -630,7 +670,7 @@ func (t *http2Client) updateWindow(s *Stream, n uint32) { | |||||||
| func (t *http2Client) handleData(f *http2.DataFrame) { | func (t *http2Client) handleData(f *http2.DataFrame) { | ||||||
| 	size := len(f.Data()) | 	size := len(f.Data()) | ||||||
| 	if err := t.fc.onData(uint32(size)); err != nil { | 	if err := t.fc.onData(uint32(size)); err != nil { | ||||||
| 		t.notifyError(ConnectionErrorf("%v", err)) | 		t.notifyError(ConnectionErrorf(true, err, "%v", err)) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// Select the right stream to dispatch. | 	// Select the right stream to dispatch. | ||||||
| @@ -655,6 +695,7 @@ func (t *http2Client) handleData(f *http2.DataFrame) { | |||||||
| 			s.state = streamDone | 			s.state = streamDone | ||||||
| 			s.statusCode = codes.Internal | 			s.statusCode = codes.Internal | ||||||
| 			s.statusDesc = err.Error() | 			s.statusDesc = err.Error() | ||||||
|  | 			close(s.done) | ||||||
| 			s.mu.Unlock() | 			s.mu.Unlock() | ||||||
| 			s.write(recvMsg{err: io.EOF}) | 			s.write(recvMsg{err: io.EOF}) | ||||||
| 			t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl}) | 			t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl}) | ||||||
| @@ -672,13 +713,14 @@ func (t *http2Client) handleData(f *http2.DataFrame) { | |||||||
| 	// the read direction is closed, and set the status appropriately. | 	// the read direction is closed, and set the status appropriately. | ||||||
| 	if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) { | 	if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) { | ||||||
| 		s.mu.Lock() | 		s.mu.Lock() | ||||||
| 		if s.state == streamWriteDone { | 		if s.state == streamDone { | ||||||
| 			s.state = streamDone | 			s.mu.Unlock() | ||||||
| 		} else { | 			return | ||||||
| 			s.state = streamReadDone |  | ||||||
| 		} | 		} | ||||||
|  | 		s.state = streamDone | ||||||
| 		s.statusCode = codes.Internal | 		s.statusCode = codes.Internal | ||||||
| 		s.statusDesc = "server closed the stream without sending trailers" | 		s.statusDesc = "server closed the stream without sending trailers" | ||||||
|  | 		close(s.done) | ||||||
| 		s.mu.Unlock() | 		s.mu.Unlock() | ||||||
| 		s.write(recvMsg{err: io.EOF}) | 		s.write(recvMsg{err: io.EOF}) | ||||||
| 	} | 	} | ||||||
| @@ -704,6 +746,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { | |||||||
| 		grpclog.Println("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error ", f.ErrCode) | 		grpclog.Println("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error ", f.ErrCode) | ||||||
| 		s.statusCode = codes.Unknown | 		s.statusCode = codes.Unknown | ||||||
| 	} | 	} | ||||||
|  | 	s.statusDesc = fmt.Sprintf("stream terminated by RST_STREAM with error code: %d", f.ErrCode) | ||||||
|  | 	close(s.done) | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| 	s.write(recvMsg{err: io.EOF}) | 	s.write(recvMsg{err: io.EOF}) | ||||||
| } | } | ||||||
| @@ -728,7 +772,32 @@ func (t *http2Client) handlePing(f *http2.PingFrame) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { | func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { | ||||||
| 	// TODO(zhaoq): GoAwayFrame handler to be implemented | 	t.mu.Lock() | ||||||
|  | 	if t.state == reachable || t.state == draining { | ||||||
|  | 		if f.LastStreamID > 0 && f.LastStreamID%2 != 1 { | ||||||
|  | 			t.mu.Unlock() | ||||||
|  | 			t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: stream ID %d is even", f.LastStreamID)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		select { | ||||||
|  | 		case <-t.goAway: | ||||||
|  | 			id := t.goAwayID | ||||||
|  | 			// t.goAway has been closed (i.e.,multiple GoAways). | ||||||
|  | 			if id < f.LastStreamID { | ||||||
|  | 				t.mu.Unlock() | ||||||
|  | 				t.notifyError(ConnectionErrorf(true, nil, "received illegal http2 GOAWAY frame: previously recv GOAWAY frame with LastStramID %d, currently recv %d", id, f.LastStreamID)) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			t.prevGoAwayID = id | ||||||
|  | 			t.goAwayID = f.LastStreamID | ||||||
|  | 			t.mu.Unlock() | ||||||
|  | 			return | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 		t.goAwayID = f.LastStreamID | ||||||
|  | 		close(t.goAway) | ||||||
|  | 	} | ||||||
|  | 	t.mu.Unlock() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) { | func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) { | ||||||
| @@ -780,11 +849,11 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { | |||||||
| 	if len(state.mdata) > 0 { | 	if len(state.mdata) > 0 { | ||||||
| 		s.trailer = state.mdata | 		s.trailer = state.mdata | ||||||
| 	} | 	} | ||||||
| 	s.state = streamDone |  | ||||||
| 	s.statusCode = state.statusCode | 	s.statusCode = state.statusCode | ||||||
| 	s.statusDesc = state.statusDesc | 	s.statusDesc = state.statusDesc | ||||||
|  | 	close(s.done) | ||||||
|  | 	s.state = streamDone | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
|  |  | ||||||
| 	s.write(recvMsg{err: io.EOF}) | 	s.write(recvMsg{err: io.EOF}) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -937,13 +1006,22 @@ func (t *http2Client) Error() <-chan struct{} { | |||||||
| 	return t.errorChan | 	return t.errorChan | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (t *http2Client) GoAway() <-chan struct{} { | ||||||
|  | 	return t.goAway | ||||||
|  | } | ||||||
|  |  | ||||||
| func (t *http2Client) notifyError(err error) { | func (t *http2Client) notifyError(err error) { | ||||||
| 	t.mu.Lock() | 	t.mu.Lock() | ||||||
| 	defer t.mu.Unlock() |  | ||||||
| 	// make sure t.errorChan is closed only once. | 	// make sure t.errorChan is closed only once. | ||||||
|  | 	if t.state == draining { | ||||||
|  | 		t.mu.Unlock() | ||||||
|  | 		t.Close() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	if t.state == reachable { | 	if t.state == reachable { | ||||||
| 		t.state = unreachable | 		t.state = unreachable | ||||||
| 		close(t.errorChan) | 		close(t.errorChan) | ||||||
| 		grpclog.Printf("transport: http2Client.notifyError got notified that the client transport was broken %v.", err) | 		grpclog.Printf("transport: http2Client.notifyError got notified that the client transport was broken %v.", err) | ||||||
| 	} | 	} | ||||||
|  | 	t.mu.Unlock() | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								vendor/google.golang.org/grpc/transport/http2_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										74
									
								
								vendor/google.golang.org/grpc/transport/http2_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -111,12 +111,12 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI | |||||||
| 			Val: uint32(initialWindowSize)}) | 			Val: uint32(initialWindowSize)}) | ||||||
| 	} | 	} | ||||||
| 	if err := framer.writeSettings(true, settings...); err != nil { | 	if err := framer.writeSettings(true, settings...); err != nil { | ||||||
| 		return nil, ConnectionErrorf("transport: %v", err) | 		return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 	} | 	} | ||||||
| 	// Adjust the connection flow control window if needed. | 	// Adjust the connection flow control window if needed. | ||||||
| 	if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { | 	if delta := uint32(initialConnWindowSize - defaultWindowSize); delta > 0 { | ||||||
| 		if err := framer.writeWindowUpdate(true, 0, delta); err != nil { | 		if err := framer.writeWindowUpdate(true, 0, delta); err != nil { | ||||||
| 			return nil, ConnectionErrorf("transport: %v", err) | 			return nil, ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	var buf bytes.Buffer | 	var buf bytes.Buffer | ||||||
| @@ -142,7 +142,7 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI | |||||||
| } | } | ||||||
|  |  | ||||||
| // operateHeader takes action on the decoded headers. | // operateHeader takes action on the decoded headers. | ||||||
| func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) { | func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream)) (close bool) { | ||||||
| 	buf := newRecvBuffer() | 	buf := newRecvBuffer() | ||||||
| 	s := &Stream{ | 	s := &Stream{ | ||||||
| 		id:  frame.Header().StreamID, | 		id:  frame.Header().StreamID, | ||||||
| @@ -205,6 +205,13 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( | |||||||
| 		t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) | 		t.controlBuf.put(&resetStream{s.id, http2.ErrCodeRefusedStream}) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	if s.id%2 != 1 || s.id <= t.maxStreamID { | ||||||
|  | 		t.mu.Unlock() | ||||||
|  | 		// illegal gRPC stream id. | ||||||
|  | 		grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", s.id) | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	t.maxStreamID = s.id | ||||||
| 	s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) | 	s.sendQuotaPool = newQuotaPool(int(t.streamSendQuota)) | ||||||
| 	t.activeStreams[s.id] = s | 	t.activeStreams[s.id] = s | ||||||
| 	t.mu.Unlock() | 	t.mu.Unlock() | ||||||
| @@ -212,6 +219,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( | |||||||
| 		t.updateWindow(s, uint32(n)) | 		t.updateWindow(s, uint32(n)) | ||||||
| 	} | 	} | ||||||
| 	handle(s) | 	handle(s) | ||||||
|  | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| // HandleStreams receives incoming streams using the given handler. This is | // HandleStreams receives incoming streams using the given handler. This is | ||||||
| @@ -231,6 +239,10 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	frame, err := t.framer.readFrame() | 	frame, err := t.framer.readFrame() | ||||||
|  | 	if err == io.EOF || err == io.ErrUnexpectedEOF { | ||||||
|  | 		t.Close() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) | 		grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) | ||||||
| 		t.Close() | 		t.Close() | ||||||
| @@ -257,20 +269,20 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { | |||||||
| 				t.controlBuf.put(&resetStream{se.StreamID, se.Code}) | 				t.controlBuf.put(&resetStream{se.StreamID, se.Code}) | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  | 			if err == io.EOF || err == io.ErrUnexpectedEOF { | ||||||
|  | 				t.Close() | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			grpclog.Printf("transport: http2Server.HandleStreams failed to read frame: %v", err) | ||||||
| 			t.Close() | 			t.Close() | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		switch frame := frame.(type) { | 		switch frame := frame.(type) { | ||||||
| 		case *http2.MetaHeadersFrame: | 		case *http2.MetaHeadersFrame: | ||||||
| 			id := frame.Header().StreamID | 			if t.operateHeaders(frame, handle) { | ||||||
| 			if id%2 != 1 || id <= t.maxStreamID { |  | ||||||
| 				// illegal gRPC stream id. |  | ||||||
| 				grpclog.Println("transport: http2Server.HandleStreams received an illegal stream id: ", id) |  | ||||||
| 				t.Close() | 				t.Close() | ||||||
| 				break | 				break | ||||||
| 			} | 			} | ||||||
| 			t.maxStreamID = id |  | ||||||
| 			t.operateHeaders(frame, handle) |  | ||||||
| 		case *http2.DataFrame: | 		case *http2.DataFrame: | ||||||
| 			t.handleData(frame) | 			t.handleData(frame) | ||||||
| 		case *http2.RSTStreamFrame: | 		case *http2.RSTStreamFrame: | ||||||
| @@ -282,7 +294,7 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) { | |||||||
| 		case *http2.WindowUpdateFrame: | 		case *http2.WindowUpdateFrame: | ||||||
| 			t.handleWindowUpdate(frame) | 			t.handleWindowUpdate(frame) | ||||||
| 		case *http2.GoAwayFrame: | 		case *http2.GoAwayFrame: | ||||||
| 			break | 			// TODO: Handle GoAway from the client appropriately. | ||||||
| 		default: | 		default: | ||||||
| 			grpclog.Printf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame) | 			grpclog.Printf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame) | ||||||
| 		} | 		} | ||||||
| @@ -364,12 +376,8 @@ func (t *http2Server) handleData(f *http2.DataFrame) { | |||||||
| 		// Received the end of stream from the client. | 		// Received the end of stream from the client. | ||||||
| 		s.mu.Lock() | 		s.mu.Lock() | ||||||
| 		if s.state != streamDone { | 		if s.state != streamDone { | ||||||
| 			if s.state == streamWriteDone { |  | ||||||
| 				s.state = streamDone |  | ||||||
| 			} else { |  | ||||||
| 			s.state = streamReadDone | 			s.state = streamReadDone | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 		s.mu.Unlock() | 		s.mu.Unlock() | ||||||
| 		s.write(recvMsg{err: io.EOF}) | 		s.write(recvMsg{err: io.EOF}) | ||||||
| 	} | 	} | ||||||
| @@ -440,7 +448,7 @@ func (t *http2Server) writeHeaders(s *Stream, b *bytes.Buffer, endStream bool) e | |||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Close() | 			t.Close() | ||||||
| 			return ConnectionErrorf("transport: %v", err) | 			return ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| @@ -455,7 +463,7 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { | |||||||
| 	} | 	} | ||||||
| 	s.headerOk = true | 	s.headerOk = true | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| 	if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { | 	if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	t.hBuf.Reset() | 	t.hBuf.Reset() | ||||||
| @@ -495,7 +503,7 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s | |||||||
| 		headersSent = true | 		headersSent = true | ||||||
| 	} | 	} | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| 	if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { | 	if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	t.hBuf.Reset() | 	t.hBuf.Reset() | ||||||
| @@ -508,7 +516,7 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s | |||||||
| 			Name:  "grpc-status", | 			Name:  "grpc-status", | ||||||
| 			Value: strconv.Itoa(int(statusCode)), | 			Value: strconv.Itoa(int(statusCode)), | ||||||
| 		}) | 		}) | ||||||
| 	t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: statusDesc}) | 	t.hEnc.WriteField(hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(statusDesc)}) | ||||||
| 	// Attach the trailer metadata. | 	// Attach the trailer metadata. | ||||||
| 	for k, v := range s.trailer { | 	for k, v := range s.trailer { | ||||||
| 		// Clients don't tolerate reading restricted headers after some non restricted ones were sent. | 		// Clients don't tolerate reading restricted headers after some non restricted ones were sent. | ||||||
| @@ -544,7 +552,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 	} | 	} | ||||||
| 	s.mu.Unlock() | 	s.mu.Unlock() | ||||||
| 	if writeHeaderFrame { | 	if writeHeaderFrame { | ||||||
| 		if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { | 		if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		t.hBuf.Reset() | 		t.hBuf.Reset() | ||||||
| @@ -560,7 +568,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		} | 		} | ||||||
| 		if err := t.framer.writeHeaders(false, p); err != nil { | 		if err := t.framer.writeHeaders(false, p); err != nil { | ||||||
| 			t.Close() | 			t.Close() | ||||||
| 			return ConnectionErrorf("transport: %v", err) | 			return ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 		t.writableChan <- 0 | 		t.writableChan <- 0 | ||||||
| 	} | 	} | ||||||
| @@ -572,13 +580,13 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		size := http2MaxFrameLen | 		size := http2MaxFrameLen | ||||||
| 		s.sendQuotaPool.add(0) | 		s.sendQuotaPool.add(0) | ||||||
| 		// Wait until the stream has some quota to send the data. | 		// Wait until the stream has some quota to send the data. | ||||||
| 		sq, err := wait(s.ctx, t.shutdownChan, s.sendQuotaPool.acquire()) | 		sq, err := wait(s.ctx, nil, nil, t.shutdownChan, s.sendQuotaPool.acquire()) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		t.sendQuotaPool.add(0) | 		t.sendQuotaPool.add(0) | ||||||
| 		// Wait until the transport has some quota to send the data. | 		// Wait until the transport has some quota to send the data. | ||||||
| 		tq, err := wait(s.ctx, t.shutdownChan, t.sendQuotaPool.acquire()) | 		tq, err := wait(s.ctx, nil, nil, t.shutdownChan, t.sendQuotaPool.acquire()) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if _, ok := err.(StreamError); ok { | 			if _, ok := err.(StreamError); ok { | ||||||
| 				t.sendQuotaPool.cancel() | 				t.sendQuotaPool.cancel() | ||||||
| @@ -604,7 +612,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		t.framer.adjustNumWriters(1) | 		t.framer.adjustNumWriters(1) | ||||||
| 		// Got some quota. Try to acquire writing privilege on the | 		// Got some quota. Try to acquire writing privilege on the | ||||||
| 		// transport. | 		// transport. | ||||||
| 		if _, err := wait(s.ctx, t.shutdownChan, t.writableChan); err != nil { | 		if _, err := wait(s.ctx, nil, nil, t.shutdownChan, t.writableChan); err != nil { | ||||||
| 			if _, ok := err.(StreamError); ok { | 			if _, ok := err.(StreamError); ok { | ||||||
| 				// Return the connection quota back. | 				// Return the connection quota back. | ||||||
| 				t.sendQuotaPool.add(ps) | 				t.sendQuotaPool.add(ps) | ||||||
| @@ -634,7 +642,7 @@ func (t *http2Server) Write(s *Stream, data []byte, opts *Options) error { | |||||||
| 		} | 		} | ||||||
| 		if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil { | 		if err := t.framer.writeData(forceFlush, s.id, false, p); err != nil { | ||||||
| 			t.Close() | 			t.Close() | ||||||
| 			return ConnectionErrorf("transport: %v", err) | 			return ConnectionErrorf(true, err, "transport: %v", err) | ||||||
| 		} | 		} | ||||||
| 		if t.framer.adjustNumWriters(-1) == 0 { | 		if t.framer.adjustNumWriters(-1) == 0 { | ||||||
| 			t.framer.flushWrite() | 			t.framer.flushWrite() | ||||||
| @@ -679,6 +687,17 @@ func (t *http2Server) controller() { | |||||||
| 					} | 					} | ||||||
| 				case *resetStream: | 				case *resetStream: | ||||||
| 					t.framer.writeRSTStream(true, i.streamID, i.code) | 					t.framer.writeRSTStream(true, i.streamID, i.code) | ||||||
|  | 				case *goAway: | ||||||
|  | 					t.mu.Lock() | ||||||
|  | 					if t.state == closing { | ||||||
|  | 						t.mu.Unlock() | ||||||
|  | 						// The transport is closing. | ||||||
|  | 						return | ||||||
|  | 					} | ||||||
|  | 					sid := t.maxStreamID | ||||||
|  | 					t.state = draining | ||||||
|  | 					t.mu.Unlock() | ||||||
|  | 					t.framer.writeGoAway(true, sid, http2.ErrCodeNo, nil) | ||||||
| 				case *flushIO: | 				case *flushIO: | ||||||
| 					t.framer.flushWrite() | 					t.framer.flushWrite() | ||||||
| 				case *ping: | 				case *ping: | ||||||
| @@ -724,6 +743,9 @@ func (t *http2Server) Close() (err error) { | |||||||
| func (t *http2Server) closeStream(s *Stream) { | func (t *http2Server) closeStream(s *Stream) { | ||||||
| 	t.mu.Lock() | 	t.mu.Lock() | ||||||
| 	delete(t.activeStreams, s.id) | 	delete(t.activeStreams, s.id) | ||||||
|  | 	if t.state == draining && len(t.activeStreams) == 0 { | ||||||
|  | 		defer t.Close() | ||||||
|  | 	} | ||||||
| 	t.mu.Unlock() | 	t.mu.Unlock() | ||||||
| 	// In case stream sending and receiving are invoked in separate | 	// In case stream sending and receiving are invoked in separate | ||||||
| 	// goroutines (e.g., bi-directional streaming), cancel needs to be | 	// goroutines (e.g., bi-directional streaming), cancel needs to be | ||||||
| @@ -746,3 +768,7 @@ func (t *http2Server) closeStream(s *Stream) { | |||||||
| func (t *http2Server) RemoteAddr() net.Addr { | func (t *http2Server) RemoteAddr() net.Addr { | ||||||
| 	return t.conn.RemoteAddr() | 	return t.conn.RemoteAddr() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (t *http2Server) Drain() { | ||||||
|  | 	t.controlBuf.put(&goAway{}) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										83
									
								
								vendor/google.golang.org/grpc/transport/http_util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/google.golang.org/grpc/transport/http_util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -35,6 +35,7 @@ package transport | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bufio" | 	"bufio" | ||||||
|  | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| @@ -174,11 +175,11 @@ func (d *decodeState) processHeaderField(f hpack.HeaderField) { | |||||||
| 		} | 		} | ||||||
| 		d.statusCode = codes.Code(code) | 		d.statusCode = codes.Code(code) | ||||||
| 	case "grpc-message": | 	case "grpc-message": | ||||||
| 		d.statusDesc = f.Value | 		d.statusDesc = decodeGrpcMessage(f.Value) | ||||||
| 	case "grpc-timeout": | 	case "grpc-timeout": | ||||||
| 		d.timeoutSet = true | 		d.timeoutSet = true | ||||||
| 		var err error | 		var err error | ||||||
| 		d.timeout, err = timeoutDecode(f.Value) | 		d.timeout, err = decodeTimeout(f.Value) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err)) | 			d.setErr(StreamErrorf(codes.Internal, "transport: malformed time-out: %v", err)) | ||||||
| 			return | 			return | ||||||
| @@ -251,7 +252,7 @@ func div(d, r time.Duration) int64 { | |||||||
| } | } | ||||||
|  |  | ||||||
| // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it. | // TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it. | ||||||
| func timeoutEncode(t time.Duration) string { | func encodeTimeout(t time.Duration) string { | ||||||
| 	if d := div(t, time.Nanosecond); d <= maxTimeoutValue { | 	if d := div(t, time.Nanosecond); d <= maxTimeoutValue { | ||||||
| 		return strconv.FormatInt(d, 10) + "n" | 		return strconv.FormatInt(d, 10) + "n" | ||||||
| 	} | 	} | ||||||
| @@ -271,7 +272,7 @@ func timeoutEncode(t time.Duration) string { | |||||||
| 	return strconv.FormatInt(div(t, time.Hour), 10) + "H" | 	return strconv.FormatInt(div(t, time.Hour), 10) + "H" | ||||||
| } | } | ||||||
|  |  | ||||||
| func timeoutDecode(s string) (time.Duration, error) { | func decodeTimeout(s string) (time.Duration, error) { | ||||||
| 	size := len(s) | 	size := len(s) | ||||||
| 	if size < 2 { | 	if size < 2 { | ||||||
| 		return 0, fmt.Errorf("transport: timeout string is too short: %q", s) | 		return 0, fmt.Errorf("transport: timeout string is too short: %q", s) | ||||||
| @@ -288,6 +289,80 @@ func timeoutDecode(s string) (time.Duration, error) { | |||||||
| 	return d * time.Duration(t), nil | 	return d * time.Duration(t), nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	spaceByte   = ' ' | ||||||
|  | 	tildaByte   = '~' | ||||||
|  | 	percentByte = '%' | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // encodeGrpcMessage is used to encode status code in header field | ||||||
|  | // "grpc-message". | ||||||
|  | // It checks to see if each individual byte in msg is an | ||||||
|  | // allowable byte, and then either percent encoding or passing it through. | ||||||
|  | // When percent encoding, the byte is converted into hexadecimal notation | ||||||
|  | // with a '%' prepended. | ||||||
|  | func encodeGrpcMessage(msg string) string { | ||||||
|  | 	if msg == "" { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	lenMsg := len(msg) | ||||||
|  | 	for i := 0; i < lenMsg; i++ { | ||||||
|  | 		c := msg[i] | ||||||
|  | 		if !(c >= spaceByte && c < tildaByte && c != percentByte) { | ||||||
|  | 			return encodeGrpcMessageUnchecked(msg) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return msg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func encodeGrpcMessageUnchecked(msg string) string { | ||||||
|  | 	var buf bytes.Buffer | ||||||
|  | 	lenMsg := len(msg) | ||||||
|  | 	for i := 0; i < lenMsg; i++ { | ||||||
|  | 		c := msg[i] | ||||||
|  | 		if c >= spaceByte && c < tildaByte && c != percentByte { | ||||||
|  | 			buf.WriteByte(c) | ||||||
|  | 		} else { | ||||||
|  | 			buf.WriteString(fmt.Sprintf("%%%02X", c)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return buf.String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage. | ||||||
|  | func decodeGrpcMessage(msg string) string { | ||||||
|  | 	if msg == "" { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	lenMsg := len(msg) | ||||||
|  | 	for i := 0; i < lenMsg; i++ { | ||||||
|  | 		if msg[i] == percentByte && i+2 < lenMsg { | ||||||
|  | 			return decodeGrpcMessageUnchecked(msg) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return msg | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func decodeGrpcMessageUnchecked(msg string) string { | ||||||
|  | 	var buf bytes.Buffer | ||||||
|  | 	lenMsg := len(msg) | ||||||
|  | 	for i := 0; i < lenMsg; i++ { | ||||||
|  | 		c := msg[i] | ||||||
|  | 		if c == percentByte && i+2 < lenMsg { | ||||||
|  | 			parsed, err := strconv.ParseInt(msg[i+1:i+3], 16, 8) | ||||||
|  | 			if err != nil { | ||||||
|  | 				buf.WriteByte(c) | ||||||
|  | 			} else { | ||||||
|  | 				buf.WriteByte(byte(parsed)) | ||||||
|  | 				i += 2 | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			buf.WriteByte(c) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return buf.String() | ||||||
|  | } | ||||||
|  |  | ||||||
| type framer struct { | type framer struct { | ||||||
| 	numWriters int32 | 	numWriters int32 | ||||||
| 	reader     io.Reader | 	reader     io.Reader | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								vendor/google.golang.org/grpc/transport/pre_go16.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/google.golang.org/grpc/transport/pre_go16.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | // +build !go1.6 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Copyright 2016, Google Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are | ||||||
|  |  * met: | ||||||
|  |  * | ||||||
|  |  *     * Redistributions of source code must retain the above copyright | ||||||
|  |  * notice, this list of conditions and the following disclaimer. | ||||||
|  |  *     * Redistributions in binary form must reproduce the above | ||||||
|  |  * copyright notice, this list of conditions and the following disclaimer | ||||||
|  |  * in the documentation and/or other materials provided with the | ||||||
|  |  * distribution. | ||||||
|  |  *     * Neither the name of Google Inc. nor the names of its | ||||||
|  |  * contributors may be used to endorse or promote products derived from | ||||||
|  |  * this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package transport | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // dialContext connects to the address on the named network. | ||||||
|  | func dialContext(ctx context.Context, network, address string) (net.Conn, error) { | ||||||
|  | 	var dialer net.Dialer | ||||||
|  | 	if deadline, ok := ctx.Deadline(); ok { | ||||||
|  | 		dialer.Timeout = deadline.Sub(time.Now()) | ||||||
|  | 	} | ||||||
|  | 	return dialer.Dial(network, address) | ||||||
|  | } | ||||||
							
								
								
									
										83
									
								
								vendor/google.golang.org/grpc/transport/transport.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/google.golang.org/grpc/transport/transport.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -44,7 +44,6 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"golang.org/x/net/context" | 	"golang.org/x/net/context" | ||||||
| 	"golang.org/x/net/trace" | 	"golang.org/x/net/trace" | ||||||
| @@ -121,6 +120,7 @@ func (b *recvBuffer) get() <-chan item { | |||||||
| // recvBuffer. | // recvBuffer. | ||||||
| type recvBufferReader struct { | type recvBufferReader struct { | ||||||
| 	ctx    context.Context | 	ctx    context.Context | ||||||
|  | 	goAway chan struct{} | ||||||
| 	recv   *recvBuffer | 	recv   *recvBuffer | ||||||
| 	last   *bytes.Reader // Stores the remaining data in the previous calls. | 	last   *bytes.Reader // Stores the remaining data in the previous calls. | ||||||
| 	err    error | 	err    error | ||||||
| @@ -141,6 +141,8 @@ func (r *recvBufferReader) Read(p []byte) (n int, err error) { | |||||||
| 	select { | 	select { | ||||||
| 	case <-r.ctx.Done(): | 	case <-r.ctx.Done(): | ||||||
| 		return 0, ContextErr(r.ctx.Err()) | 		return 0, ContextErr(r.ctx.Err()) | ||||||
|  | 	case <-r.goAway: | ||||||
|  | 		return 0, ErrStreamDrain | ||||||
| 	case i := <-r.recv.get(): | 	case i := <-r.recv.get(): | ||||||
| 		r.recv.load() | 		r.recv.load() | ||||||
| 		m := i.(*recvMsg) | 		m := i.(*recvMsg) | ||||||
| @@ -158,7 +160,7 @@ const ( | |||||||
| 	streamActive    streamState = iota | 	streamActive    streamState = iota | ||||||
| 	streamWriteDone             // EndStream sent | 	streamWriteDone             // EndStream sent | ||||||
| 	streamReadDone              // EndStream received | 	streamReadDone              // EndStream received | ||||||
| 	streamDone                  // sendDone and recvDone or RSTStreamFrame is sent or received. | 	streamDone                  // the entire stream is finished. | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Stream represents an RPC in the transport layer. | // Stream represents an RPC in the transport layer. | ||||||
| @@ -169,6 +171,10 @@ type Stream struct { | |||||||
| 	// ctx is the associated context of the stream. | 	// ctx is the associated context of the stream. | ||||||
| 	ctx    context.Context | 	ctx    context.Context | ||||||
| 	cancel context.CancelFunc | 	cancel context.CancelFunc | ||||||
|  | 	// done is closed when the final status arrives. | ||||||
|  | 	done chan struct{} | ||||||
|  | 	// goAway is closed when the server sent GoAways signal before this stream was initiated. | ||||||
|  | 	goAway chan struct{} | ||||||
| 	// method records the associated RPC method of the stream. | 	// method records the associated RPC method of the stream. | ||||||
| 	method       string | 	method       string | ||||||
| 	recvCompress string | 	recvCompress string | ||||||
| @@ -214,6 +220,18 @@ func (s *Stream) SetSendCompress(str string) { | |||||||
| 	s.sendCompress = str | 	s.sendCompress = str | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Done returns a chanel which is closed when it receives the final status | ||||||
|  | // from the server. | ||||||
|  | func (s *Stream) Done() <-chan struct{} { | ||||||
|  | 	return s.done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GoAway returns a channel which is closed when the server sent GoAways signal | ||||||
|  | // before this stream was initiated. | ||||||
|  | func (s *Stream) GoAway() <-chan struct{} { | ||||||
|  | 	return s.goAway | ||||||
|  | } | ||||||
|  |  | ||||||
| // Header acquires the key-value pairs of header metadata once it | // Header acquires the key-value pairs of header metadata once it | ||||||
| // is available. It blocks until i) the metadata is ready or ii) there is no | // is available. It blocks until i) the metadata is ready or ii) there is no | ||||||
| // header metadata or iii) the stream is cancelled/expired. | // header metadata or iii) the stream is cancelled/expired. | ||||||
| @@ -221,6 +239,8 @@ func (s *Stream) Header() (metadata.MD, error) { | |||||||
| 	select { | 	select { | ||||||
| 	case <-s.ctx.Done(): | 	case <-s.ctx.Done(): | ||||||
| 		return nil, ContextErr(s.ctx.Err()) | 		return nil, ContextErr(s.ctx.Err()) | ||||||
|  | 	case <-s.goAway: | ||||||
|  | 		return nil, ErrStreamDrain | ||||||
| 	case <-s.headerChan: | 	case <-s.headerChan: | ||||||
| 		return s.header.Copy(), nil | 		return s.header.Copy(), nil | ||||||
| 	} | 	} | ||||||
| @@ -335,19 +355,17 @@ type ConnectOptions struct { | |||||||
| 	// UserAgent is the application user agent. | 	// UserAgent is the application user agent. | ||||||
| 	UserAgent string | 	UserAgent string | ||||||
| 	// Dialer specifies how to dial a network address. | 	// Dialer specifies how to dial a network address. | ||||||
| 	Dialer func(string, time.Duration) (net.Conn, error) | 	Dialer func(context.Context, string) (net.Conn, error) | ||||||
| 	// PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. | 	// PerRPCCredentials stores the PerRPCCredentials required to issue RPCs. | ||||||
| 	PerRPCCredentials []credentials.PerRPCCredentials | 	PerRPCCredentials []credentials.PerRPCCredentials | ||||||
| 	// TransportCredentials stores the Authenticator required to setup a client connection. | 	// TransportCredentials stores the Authenticator required to setup a client connection. | ||||||
| 	TransportCredentials credentials.TransportCredentials | 	TransportCredentials credentials.TransportCredentials | ||||||
| 	// Timeout specifies the timeout for dialing a ClientTransport. |  | ||||||
| 	Timeout time.Duration |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewClientTransport establishes the transport with the required ConnectOptions | // NewClientTransport establishes the transport with the required ConnectOptions | ||||||
| // and returns it to the caller. | // and returns it to the caller. | ||||||
| func NewClientTransport(target string, opts *ConnectOptions) (ClientTransport, error) { | func NewClientTransport(ctx context.Context, target string, opts ConnectOptions) (ClientTransport, error) { | ||||||
| 	return newHTTP2Client(target, opts) | 	return newHTTP2Client(ctx, target, opts) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Options provides additional hints and information for message | // Options provides additional hints and information for message | ||||||
| @@ -417,6 +435,11 @@ type ClientTransport interface { | |||||||
| 	// and create a new one) in error case. It should not return nil | 	// and create a new one) in error case. It should not return nil | ||||||
| 	// once the transport is initiated. | 	// once the transport is initiated. | ||||||
| 	Error() <-chan struct{} | 	Error() <-chan struct{} | ||||||
|  |  | ||||||
|  | 	// GoAway returns a channel that is closed when ClientTranspor | ||||||
|  | 	// receives the draining signal from the server (e.g., GOAWAY frame in | ||||||
|  | 	// HTTP/2). | ||||||
|  | 	GoAway() <-chan struct{} | ||||||
| } | } | ||||||
|  |  | ||||||
| // ServerTransport is the common interface for all gRPC server-side transport | // ServerTransport is the common interface for all gRPC server-side transport | ||||||
| @@ -448,6 +471,9 @@ type ServerTransport interface { | |||||||
|  |  | ||||||
| 	// RemoteAddr returns the remote network address. | 	// RemoteAddr returns the remote network address. | ||||||
| 	RemoteAddr() net.Addr | 	RemoteAddr() net.Addr | ||||||
|  |  | ||||||
|  | 	// Drain notifies the client this ServerTransport stops accepting new RPCs. | ||||||
|  | 	Drain() | ||||||
| } | } | ||||||
|  |  | ||||||
| // StreamErrorf creates an StreamError with the specified error code and description. | // StreamErrorf creates an StreamError with the specified error code and description. | ||||||
| @@ -459,9 +485,11 @@ func StreamErrorf(c codes.Code, format string, a ...interface{}) StreamError { | |||||||
| } | } | ||||||
|  |  | ||||||
| // ConnectionErrorf creates an ConnectionError with the specified error description. | // ConnectionErrorf creates an ConnectionError with the specified error description. | ||||||
| func ConnectionErrorf(format string, a ...interface{}) ConnectionError { | func ConnectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError { | ||||||
| 	return ConnectionError{ | 	return ConnectionError{ | ||||||
| 		Desc: fmt.Sprintf(format, a...), | 		Desc: fmt.Sprintf(format, a...), | ||||||
|  | 		temp: temp, | ||||||
|  | 		err:  e, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -469,14 +497,36 @@ func ConnectionErrorf(format string, a ...interface{}) ConnectionError { | |||||||
| // entire connection and the retry of all the active streams. | // entire connection and the retry of all the active streams. | ||||||
| type ConnectionError struct { | type ConnectionError struct { | ||||||
| 	Desc string | 	Desc string | ||||||
|  | 	temp bool | ||||||
|  | 	err  error | ||||||
| } | } | ||||||
|  |  | ||||||
| func (e ConnectionError) Error() string { | func (e ConnectionError) Error() string { | ||||||
| 	return fmt.Sprintf("connection error: desc = %q", e.Desc) | 	return fmt.Sprintf("connection error: desc = %q", e.Desc) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Temporary indicates if this connection error is temporary or fatal. | ||||||
|  | func (e ConnectionError) Temporary() bool { | ||||||
|  | 	return e.temp | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Origin returns the original error of this connection error. | ||||||
|  | func (e ConnectionError) Origin() error { | ||||||
|  | 	// Never return nil error here. | ||||||
|  | 	// If the original error is nil, return itself. | ||||||
|  | 	if e.err == nil { | ||||||
|  | 		return e | ||||||
|  | 	} | ||||||
|  | 	return e.err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var ( | ||||||
| 	// ErrConnClosing indicates that the transport is closing. | 	// ErrConnClosing indicates that the transport is closing. | ||||||
| var ErrConnClosing = ConnectionError{Desc: "transport is closing"} | 	ErrConnClosing = ConnectionError{Desc: "transport is closing", temp: true} | ||||||
|  | 	// ErrStreamDrain indicates that the stream is rejected by the server because | ||||||
|  | 	// the server stops accepting new RPCs. | ||||||
|  | 	ErrStreamDrain = StreamErrorf(codes.Unavailable, "the server stops accepting new RPCs") | ||||||
|  | ) | ||||||
|  |  | ||||||
| // StreamError is an error that only affects one stream within a connection. | // StreamError is an error that only affects one stream within a connection. | ||||||
| type StreamError struct { | type StreamError struct { | ||||||
| @@ -501,12 +551,25 @@ func ContextErr(err error) StreamError { | |||||||
|  |  | ||||||
| // wait blocks until it can receive from ctx.Done, closing, or proceed. | // wait blocks until it can receive from ctx.Done, closing, or proceed. | ||||||
| // If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. | // If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. | ||||||
|  | // If it receives from done, it returns 0, io.EOF if ctx is not done; otherwise | ||||||
|  | // it return the StreamError for ctx.Err. | ||||||
|  | // If it receives from goAway, it returns 0, ErrStreamDrain. | ||||||
| // If it receives from closing, it returns 0, ErrConnClosing. | // If it receives from closing, it returns 0, ErrConnClosing. | ||||||
| // If it receives from proceed, it returns the received integer, nil. | // If it receives from proceed, it returns the received integer, nil. | ||||||
| func wait(ctx context.Context, closing <-chan struct{}, proceed <-chan int) (int, error) { | func wait(ctx context.Context, done, goAway, closing <-chan struct{}, proceed <-chan int) (int, error) { | ||||||
| 	select { | 	select { | ||||||
| 	case <-ctx.Done(): | 	case <-ctx.Done(): | ||||||
| 		return 0, ContextErr(ctx.Err()) | 		return 0, ContextErr(ctx.Err()) | ||||||
|  | 	case <-done: | ||||||
|  | 		// User cancellation has precedence. | ||||||
|  | 		select { | ||||||
|  | 		case <-ctx.Done(): | ||||||
|  | 			return 0, ContextErr(ctx.Err()) | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 		return 0, io.EOF | ||||||
|  | 	case <-goAway: | ||||||
|  | 		return 0, ErrStreamDrain | ||||||
| 	case <-closing: | 	case <-closing: | ||||||
| 		return 0, ErrConnClosing | 		return 0, ErrConnClosing | ||||||
| 	case i := <-proceed: | 	case i := <-proceed: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Timothy St. Clair
					Timothy St. Clair