// will be spawned as a go-routine by server's connection handler. func requestHandler( req interface{}, conn net.Conn, // Write handle to the tcp socket quitch <-chan interface{}, // client / connection might have quit (done) killch chan bool, // application is shutting down the server. ) { var responses []*protobuf.ResponseStream switch req.(type) { case *protobuf.StatisticsRequest: // responses = getStatistics() case *protobuf.ScanRequest: // responses = scanIndex() case *protobuf.ScanAllRequest: // responses = fullTableScan() } buf := make([]byte, 1024, 1024) loop: for _, resp := range responses { // query storage backend for request protobuf.EncodeAndWrite(conn, buf, resp) select { case <-quitch: close(killch) break loop } } protobuf.EncodeAndWrite(conn, buf, &protobuf.StreamEndResponse{}) // Free resources. }
func (w *protoResponseWriter) Count(c uint64) error { res := &protobuf.CountResponse{ Count: proto.Int64(int64(c)), } return protobuf.EncodeAndWrite(w.conn, *w.encBuf, res) }
func (w *protoResponseWriter) Error(err error) error { var res interface{} protoErr := &protobuf.Error{Error: proto.String(err.Error())} // Drop all collected rows w.rowEntries = nil w.rowSize = 0 switch w.scanType { case StatsReq: res = &protobuf.StatisticsResponse{ Err: protoErr, } case CountReq: res = &protobuf.CountResponse{ Count: proto.Int64(0), Err: protoErr, } case ScanAllReq, ScanReq: res = &protobuf.ResponseStream{ Err: protoErr, } } return protobuf.EncodeAndWrite(w.conn, *w.encBuf, res) }
func (w *protoResponseWriter) Row(pk, sk []byte) error { if w.rowSize+len(pk)+len(sk) > len(*w.rowBuf) { res := &protobuf.ResponseStream{IndexEntries: w.rowEntries} err := protobuf.EncodeAndWrite(w.conn, *w.encBuf, res) if err != nil { return err } w.rowSize = 0 w.rowEntries = nil } pkCopy := (*w.rowBuf)[w.rowSize : w.rowSize+len(pk)] w.rowSize += len(pk) skCopy := (*w.rowBuf)[w.rowSize : w.rowSize+len(sk)] w.rowSize += len(sk) copy(pkCopy, pk) copy(skCopy, sk) row := &protobuf.IndexEntry{ EntryKey: skCopy, PrimaryKey: pkCopy, } w.rowSize += len(sk) + len(pk) w.rowEntries = append(w.rowEntries, row) return nil }
func (w *protoResponseWriter) Stats(rows, unique uint64, min, max []byte) error { res := &protobuf.StatisticsResponse{ Stats: &protobuf.IndexStatistics{ KeysCount: proto.Uint64(rows), UniqueKeysCount: proto.Uint64(unique), KeyMin: min, KeyMax: max, }, } return protobuf.EncodeAndWrite(w.conn, *w.encBuf, res) }
func (w *protoResponseWriter) Done() error { defer p.PutBlock(w.encBuf) defer p.PutBlock(w.rowBuf) if (w.scanType == ScanReq || w.scanType == ScanAllReq) && w.rowSize > 0 { res := &protobuf.ResponseStream{IndexEntries: w.rowEntries} err := protobuf.EncodeAndWrite(w.conn, *w.encBuf, res) if err != nil { return err } } return nil }
func (s *scanCoordinator) respondWithError(conn net.Conn, req *ScanRequest, err error) { var res interface{} buf := p.GetBlock() defer p.PutBlock(buf) protoErr := &protobuf.Error{Error: proto.String(err.Error())} switch req.ScanType { case StatsReq: res = &protobuf.StatisticsResponse{ Err: protoErr, } case CountReq: res = &protobuf.CountResponse{ Count: proto.Int64(0), Err: protoErr, } case ScanAllReq, ScanReq: res = &protobuf.ResponseStream{ Err: protoErr, } } err2 := protobuf.EncodeAndWrite(conn, *buf, res) if err2 != nil { err = fmt.Errorf("%s, %s", err, err2) goto finish } err2 = protobuf.EncodeAndWrite(conn, *buf, &protobuf.StreamEndResponse{}) if err2 != nil { err = fmt.Errorf("%s, %s", err, err2) } finish: logging.Errorf("%s RESPONSE Failed with error (%s)", req.LogPrefix, err) }