예제 #1
0
func readResponseHeader(r *bufio.Reader) (binprot.ResponseHeader, error) {
	resHeader, err := binprot.ReadResponseHeader(r)
	if err != nil {
		return binprot.ResponseHeader{}, err
	}

	if err := binprot.DecodeError(resHeader); err != nil {
		binprot.PutResponseHeader(resHeader)
		return resHeader, err
	}

	binprot.PutResponseHeader(resHeader)
	return resHeader, nil
}
예제 #2
0
func simpleCmdLocal(rw *bufio.ReadWriter) error {
	if err := rw.Flush(); err != nil {
		return err
	}

	resHeader, err := binprot.ReadResponseHeader(rw)
	if err != nil {
		return err
	}
	defer binprot.PutResponseHeader(resHeader)

	err = binprot.DecodeError(resHeader)
	if err != nil {
		n, ioerr := rw.Discard(int(resHeader.TotalBodyLength))
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if ioerr != nil {
			return ioerr
		}
		return err
	}

	// Read in the message bytes from the body
	n, err := rw.Discard(int(resHeader.TotalBodyLength))
	metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))

	return err
}
예제 #3
0
파일: localComm.go 프로젝트: Netflix/rend
func simpleCmdLocal(rw *bufio.ReadWriter, flush bool) error {
	if flush {
		if err := rw.Flush(); err != nil {
			return err
		}
	}

	resHeader, err := binprot.ReadResponseHeader(rw)
	if err != nil {
		return err
	}

	n, ioerr := rw.Discard(int(resHeader.TotalBodyLength))
	metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
	if ioerr != nil {
		binprot.PutResponseHeader(resHeader)
		return ioerr
	}

	binprot.PutResponseHeader(resHeader)
	return binprot.DecodeError(resHeader)
}
예제 #4
0
func getLocal(rw *bufio.ReadWriter, readExp bool) (data []byte, flags, exp uint32, err error) {
	if err := rw.Flush(); err != nil {
		return nil, 0, 0, err
	}

	resHeader, err := binprot.ReadResponseHeader(rw)
	if err != nil {
		return nil, 0, 0, err
	}
	defer binprot.PutResponseHeader(resHeader)

	err = binprot.DecodeError(resHeader)
	if err != nil {
		n, ioerr := rw.Discard(int(resHeader.TotalBodyLength))
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if ioerr != nil {
			return nil, 0, 0, ioerr
		}
		return nil, 0, 0, err
	}

	var serverFlags uint32
	binary.Read(rw, binary.BigEndian, &serverFlags)
	metrics.IncCounterBy(common.MetricBytesReadLocal, 4)

	var serverExp uint32
	if readExp {
		binary.Read(rw, binary.BigEndian, &serverExp)
		metrics.IncCounterBy(common.MetricBytesReadLocal, 4)
	}

	// total body - key - extra
	dataLen := resHeader.TotalBodyLength - uint32(resHeader.KeyLength) - uint32(resHeader.ExtraLength)
	buf := make([]byte, dataLen)

	// Read in value
	n, err := io.ReadAtLeast(rw, buf, int(dataLen))
	metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
	if err != nil {
		return nil, 0, 0, err
	}

	return buf, serverFlags, serverExp, nil
}
예제 #5
0
파일: localComm.go 프로젝트: Netflix/rend
func getMetadataCommon(rw *bufio.ReadWriter) (metadata, error) {
	if err := rw.Flush(); err != nil {
		return emptyMeta, err
	}

	resHeader, err := binprot.ReadResponseHeader(rw)
	if err != nil {
		return emptyMeta, err
	}
	defer binprot.PutResponseHeader(resHeader)

	err = binprot.DecodeError(resHeader)
	if err != nil {
		// read in the message "Not found" after a miss
		n, ioerr := rw.Discard(int(resHeader.TotalBodyLength))
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if ioerr != nil {
			return emptyMeta, ioerr
		}
		return emptyMeta, err
	}

	// we currently do nothing with the flags
	//buf := make([]byte, 4)
	//n, err := io.ReadAtLeast(rw, buf, 4)
	//metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
	//if err != nil {
	//	return emptyMeta, err
	//}
	//serverFlags := binary.BigEndian.Uint32(buf)

	// instead of reading and parsing flags, just discard
	rw.Discard(4)
	metrics.IncCounterBy(common.MetricBytesReadLocal, 4)

	metaData, err := readMetadata(rw)
	if err != nil {
		return emptyMeta, err
	}

	return metaData, nil
}
예제 #6
0
파일: localComm.go 프로젝트: Netflix/rend
func getLocalIntoBuf(rw *bufio.Reader, metaData metadata, tokenBuf, dataBuf []byte, chunkNum, totalDataLength int) (opcodeNoop bool, err error) {
	resHeader, err := binprot.ReadResponseHeader(rw)
	if err != nil {
		return false, err
	}
	defer binprot.PutResponseHeader(resHeader)

	// it feels a bit dirty knowing about batch gets here, but it's the most logical place to put
	// a check for an opcode that signals the end of a batch get or GAT. This code is a bit too big
	// to copy-paste in multiple places.
	if resHeader.Opcode == binprot.OpcodeNoop {
		return true, nil
	}

	err = binprot.DecodeError(resHeader)
	if err != nil {
		// read in the message "Not found" after a miss
		n, ioerr := rw.Discard(int(resHeader.TotalBodyLength))
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if ioerr != nil {
			return false, ioerr
		}
		return false, err
	}

	// we currently do nothing with the flags
	//buf := make([]byte, 4)
	//n, err := io.ReadAtLeast(rw, buf, 4)
	//metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
	//if err != nil {
	//	return emptyMeta, err
	//}
	//serverFlags := binary.BigEndian.Uint32(buf)

	// instead of reading and parsing flags, just discard
	rw.Discard(4)
	metrics.IncCounterBy(common.MetricBytesReadLocal, 4)

	// Read in token if requested
	if tokenBuf != nil {
		n, err := io.ReadAtLeast(rw, tokenBuf, tokenSize)
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if err != nil {
			return false, err
		}
	}

	// indices for slicing, end exclusive
	start, end := chunkSliceIndices(int(metaData.ChunkSize), chunkNum, int(metaData.Length))
	// read data directly into buf
	chunkBuf := dataBuf[start:end]

	// Read in value
	n, err := io.ReadAtLeast(rw, chunkBuf, len(chunkBuf))
	metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
	if err != nil {
		return false, err
	}

	// consume padding at end of chunk if needed
	if len(chunkBuf) < totalDataLength {
		n, ioerr := rw.Discard(totalDataLength - len(chunkBuf))
		metrics.IncCounterBy(common.MetricBytesReadLocal, uint64(n))
		if ioerr != nil {
			return false, ioerr
		}
	}

	return false, nil
}