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

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

	err = binprot.DecodeError(resHeader)
	if err != nil {
		// read in the message "Not found" after a miss
		if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
			return metadata{}, ioerr
		}
		return metadata{}, err
	}

	serverFlags := make([]byte, 4)
	binary.Read(rw, binary.BigEndian, &serverFlags)

	var metaData metadata
	binary.Read(rw, binary.BigEndian, &metaData)

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

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

	err = binprot.DecodeError(resHeader)
	if err != nil {
		if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
			return ioerr
		}
		return err
	}

	// Read in the message bytes from the body
	if _, err := rw.Discard(int(resHeader.TotalBodyLength)); err != nil {
		return err
	}

	return nil
}
예제 #3
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
}
예제 #4
0
파일: localComm.go 프로젝트: hardiku/rend
func getLocal(rw *bufio.ReadWriter) (data []byte, flags uint32, err error) {
	if err := rw.Flush(); err != nil {
		return nil, 0, err
	}

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

	err = binprot.DecodeError(resHeader)
	if err != nil {
		if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
			return nil, 0, ioerr
		}
		return nil, 0, err
	}

	var serverFlags uint32
	binary.Read(rw, binary.BigEndian, &serverFlags)

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

	// Read in value
	if _, err := io.ReadFull(rw, buf); err != nil {
		return nil, 0, err
	}

	return buf, serverFlags, nil
}
예제 #5
0
파일: localComm.go 프로젝트: mbrukman/rend
func getLocalIntoBuf(rw *bufio.ReadWriter, cmd []byte, tokenBuf []byte, buf []byte, totalDataLength int) error {
	if _, err := rw.Write(cmd); err != nil {
		return err
	}

	if err := rw.Flush(); err != nil {
		return err
	}

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

	err = binprot.DecodeError(resHeader)
	if err != nil {
		if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
			return ioerr
		}
		return err
	}

	serverFlags := make([]byte, 4)
	binary.Read(rw, binary.BigEndian, &serverFlags)

	// Read in token if requested
	if tokenBuf != nil {
		if _, err := io.ReadFull(rw, tokenBuf); err != nil {
			return err
		}
	}

	// Read in value
	if _, err := io.ReadFull(rw, buf); err != nil {
		return err
	}

	// consume padding at end of chunk if needed
	if len(buf) < totalDataLength {
		if _, ioerr := rw.Discard(totalDataLength - len(buf)); ioerr != nil {
			return ioerr
		}
	}

	return nil
}
예제 #6
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
}
예제 #7
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
}
예제 #8
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)
}
예제 #9
0
func HandleSet(cmd common.SetRequest, src *bufio.Reader, rw *bufio.ReadWriter) error {
	// For writing chunks, the specialized chunked reader is appropriate.
	// for unchunked, a limited reader will be needed since the text protocol
	// includes a /r/n at the end and there's no EOF to be had with a long-l`ived
	// connection.
	limChunkReader := stream.NewChunkLimitedReader(src, int64(CHUNK_SIZE), int64(cmd.Length))
	numChunks := int(math.Ceil(float64(cmd.Length) / float64(CHUNK_SIZE)))
	token := <-tokens

	metaKey := metaKey(cmd.Key)
	metaData := common.Metadata{
		Length:    cmd.Length,
		OrigFlags: cmd.Flags,
		NumChunks: uint32(numChunks),
		ChunkSize: CHUNK_SIZE,
		Token:     token,
	}

	metaDataBuf := new(bytes.Buffer)
	binary.Write(metaDataBuf, binary.BigEndian, metaData)

	// Write metadata key
	// TODO: should there be a unique flags value for chunked data?
	localCmd := binprot.SetCmd(metaKey, cmd.Flags, cmd.Exptime, common.METADATA_SIZE)
	if err := setLocal(rw.Writer, localCmd, metaDataBuf); err != nil {
		return err
	}

	// Read server's response
	resHeader, err := readResponseHeader(rw.Reader)
	if err != nil {
		// Discard request body
		if _, ioerr := src.Discard(int(cmd.Length)); ioerr != nil {
			return ioerr
		}

		// Discard response body
		if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
			return ioerr
		}

		return err
	}

	// Write all the data chunks
	// TODO: Clean up if a data chunk write fails
	// Failure can mean the write failing at the I/O level
	// or at the memcached level, e.g. response == ERROR
	chunkNum := 0
	for limChunkReader.More() {
		// Build this chunk's key
		key := chunkKey(cmd.Key, chunkNum)

		// Write the key
		localCmd = binprot.SetCmd(key, cmd.Flags, cmd.Exptime, FULL_DATA_SIZE)
		if err = setLocalWithToken(rw.Writer, localCmd, token, limChunkReader); err != nil {
			return err
		}

		// Read server's response
		resHeader, err = readResponseHeader(rw.Reader)
		if err != nil {
			// Discard request body
			for limChunkReader.More() {
				if _, ioerr := io.Copy(ioutil.Discard, limChunkReader); ioerr != nil {
					return ioerr
				}

				limChunkReader.NextChunk()
			}

			// Discard repsonse body
			if _, ioerr := rw.Discard(int(resHeader.TotalBodyLength)); ioerr != nil {
				return ioerr
			}

			return err
		}

		// Reset for next iteration
		limChunkReader.NextChunk()
		chunkNum++
	}

	return nil
}