func TestPktKeyVersions(t *testing.T) { seqno, nVbs, nMuts, nIndexes := 1, 20, 5, 5 vbsRef := constructVbKeyVersions("default", seqno, nVbs, nMuts, nIndexes) tc := newTestConnection() tc.reset() flags := transport.TransportFlag(0).SetProtobuf() pkt := transport.NewTransportPacket(1000*1024, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) if err := pkt.Send(tc, vbsRef); err != nil { // Send reference t.Fatal(err) } if payload, err := pkt.Receive(tc); err != nil { // Receive reference t.Fatal(err) } else { // compare both val := payload.([]*protobuf.VbKeyVersions) vbs := protobuf2VbKeyVersions(val) if len(vbsRef) != len(vbs) { t.Fatal("Mismatch in length") } for i, vb := range vbs { if vb.Equal(vbsRef[i]) == false { t.Fatal("Mismatch in VbKeyVersions") } } } }
// receive requests from remote, when this function returns // the connection is expected to be closed. func (s *Server) doReceive(conn net.Conn, rcvch chan<- interface{}) { raddr := conn.RemoteAddr() // transport buffer for receiving flags := transport.TransportFlag(0).SetProtobuf() rpkt := transport.NewTransportPacket(s.maxPayload, flags) rpkt.SetDecoder(transport.EncodingProtobuf, protobuf.ProtobufDecode) logging.Infof("%v connection %q doReceive() ...\n", s.logPrefix, raddr) loop: for { // TODO: Fix read timeout correctly // timeoutMs := s.readDeadline * time.Millisecond // conn.SetReadDeadline(time.Now().Add(timeoutMs)) req, err := rpkt.Receive(conn) // TODO: handle close-connection and don't print error message. if err != nil { if err == io.EOF { logging.Tracef("%v connection %q exited %v\n", s.logPrefix, raddr, err) } else { logging.Errorf("%v connection %q exited %v\n", s.logPrefix, raddr, err) } break loop } select { case rcvch <- req: case <-s.killch: break loop } } close(rcvch) }
func (cp *connectionPool) defaultMkConn(host string) (*connection, error) { logging.Infof("%v open new connection ...\n", cp.logPrefix) conn, err := net.Dial("tcp", host) if err != nil { return nil, err } flags := transport.TransportFlag(0).SetProtobuf() pkt := transport.NewTransportPacket(cp.maxPayload, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobuf.ProtobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobuf.ProtobufDecode) return &connection{conn, pkt}, nil }
func BenchmarkSendVbKeyVersions(b *testing.B) { seqno, nVbs, nMuts, nIndexes := 1, 20, 5, 5 vbs := constructVbKeyVersions("default", seqno, nVbs, nMuts, nIndexes) tc := newTestConnection() flags := transport.TransportFlag(0).SetProtobuf() pkt := transport.NewTransportPacket(1000*1024, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) b.ResetTimer() for i := 0; i < b.N; i++ { tc.reset() pkt.Send(tc, vbs) } }
func BenchmarkSendVbmap(b *testing.B) { vbmap := &c.VbConnectionMap{ Bucket: "default", Vbuckets: []uint16{1, 2, 3, 4}, Vbuuids: []uint64{10, 20, 30, 40}, } tc := newTestConnection() flags := transport.TransportFlag(0).SetProtobuf() pkt := transport.NewTransportPacket(1000*1024, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) b.ResetTimer() for i := 0; i < b.N; i++ { tc.reset() pkt.Send(tc, vbmap) } }
func TestPktVbmap(t *testing.T) { vbmapRef := &c.VbConnectionMap{ Bucket: "default", Vbuckets: []uint16{1, 2, 3, 4}, Vbuuids: []uint64{10, 20, 30, 40}, } tc := newTestConnection() tc.reset() flags := transport.TransportFlag(0).SetProtobuf() pkt := transport.NewTransportPacket(1000*1024, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) if err := pkt.Send(tc, vbmapRef); err != nil { // send reference t.Fatal(err) } if payload, err := pkt.Receive(tc); err != nil { // receive reference t.Fatal(err) } else { // Compare both vbmap := protobuf2Vbmap(payload.(*protobuf.VbConnectionMap)) vbmap.Equal(vbmapRef) } }
// NewRouterEndpoint instantiate a new RouterEndpoint // routine and return its reference. func NewRouterEndpoint( cluster, topic, raddr string, maxvbs int, config c.Config) (*RouterEndpoint, error) { conn, err := net.Dial("tcp", raddr) if err != nil { return nil, err } endpoint := &RouterEndpoint{ topic: topic, raddr: raddr, finch: make(chan bool), timestamp: time.Now().UnixNano(), keyChSize: config["keyChanSize"].Int(), block: config["remoteBlock"].Bool(), bufferSize: config["bufferSize"].Int(), bufferTm: time.Duration(config["bufferTimeout"].Int()), harakiriTm: time.Duration(config["harakiriTimeout"].Int()), } endpoint.ch = make(chan []interface{}, endpoint.keyChSize) endpoint.conn = conn // TODO: add configuration params for transport flags. flags := transport.TransportFlag(0).SetProtobuf() maxPayload := config["maxPayload"].Int() endpoint.pkt = transport.NewTransportPacket(maxPayload, flags) endpoint.pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) endpoint.pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) endpoint.logPrefix = fmt.Sprintf( "ENDP[<-(%v,%4x)<-%v #%v]", endpoint.raddr, uint16(endpoint.timestamp), cluster, topic) go endpoint.run(endpoint.ch) logging.Infof("%v started ...\n", endpoint.logPrefix) return endpoint, nil }
// per vbucket routine pushes *VbConnectionMap / *VbKeyVersions to other end. func (c *Client) runTransmitter( logPrefix string, conn net.Conn, flags transport.TransportFlag, payloadch chan interface{}, quitch chan []string) { laddr := conn.LocalAddr().String() defer func() { if r := recover(); r != nil { logging.Errorf( "%v runTransmitter(%q) crashed: %v\n", logPrefix, laddr, r) logging.Errorf("%s", logging.StackTrace()) } quitch <- []string{"quit", laddr} }() pkt := transport.NewTransportPacket(c.maxPayload, flags) pkt.SetEncoder(transport.EncodingProtobuf, protobufEncode) pkt.SetDecoder(transport.EncodingProtobuf, protobufDecode) transmit := func(payload interface{}) bool { if err := pkt.Send(conn, payload); err != nil { logging.Errorf("%v transport %q `%v`\n", logPrefix, laddr, err) return false } logging.Tracef("%v transported from %q\n", logPrefix, laddr) return true } timeout := time.Tick(c.bufferTimeout * time.Millisecond) vbs := make([]*common.VbKeyVersions, 0, c.bufferSize) resetAcc := func() { for _, vb := range vbs { vb.Free() } vbs = vbs[:0] // reset buffer } loop: for { select { case payload, ok := <-payloadch: if !ok { break loop } switch val := payload.(type) { case *common.VbConnectionMap: if transmit(val) == false { break loop } case *common.VbKeyVersions: vbs = append(vbs, val) if len(vbs) > c.bufferSize { if transmit(vbs) == false { break loop } resetAcc() } } case <-timeout: if len(vbs) > 0 && transmit(vbs) == false { break loop } resetAcc() case <-c.finch: break loop } } }