示例#1
0
// GetResponse looks up a response matching the specified cmdID. If the
// response is found, it is returned along with its associated error.
// If the response is not found, nil is returned for both the response
// and its error. In all cases, the third return value is the error
// returned from the engine when reading the on-disk cache.
func (rc *ResponseCache) GetResponse(e engine.Engine, cmdID proto.ClientCmdID) (proto.ResponseWithError, error) {
	// Do nothing if command ID is empty.
	if cmdID.IsEmpty() {
		return proto.ResponseWithError{}, nil
	}

	// Pull response from the cache and read into reply if available.
	var rcEntry proto.ResponseCacheEntry
	key := keys.ResponseCacheKey(rc.rangeID, &cmdID)
	ok, err := engine.MVCCGetProto(e, key, proto.ZeroTimestamp, true, nil, &rcEntry)
	if err != nil {
		return proto.ResponseWithError{}, err
	}
	if ok {
		resp := rcEntry.GetValue().(proto.Response)
		header := resp.Header()
		defer func() { header.Error = nil }()
		return proto.ResponseWithError{Reply: resp, Err: header.GoError()}, nil
	}
	return proto.ResponseWithError{}, nil
}
示例#2
0
// PutResponse writes a response and an error associated with it to the
// cache for the specified cmdID.
func (rc *ResponseCache) PutResponse(e engine.Engine, cmdID proto.ClientCmdID, replyWithErr proto.ResponseWithError) error {
	// Do nothing if command ID is empty.
	if cmdID.IsEmpty() {
		return nil
	}

	// Write the response value to the engine.
	if rc.shouldCacheResponse(replyWithErr) {
		// Write the error into the reply before caching.
		header := replyWithErr.Reply.Header()
		header.SetGoError(replyWithErr.Err)
		// Be sure to clear it when you're done!
		defer func() { header.Error = nil }()

		key := keys.ResponseCacheKey(rc.rangeID, &cmdID)
		var rcEntry proto.ResponseCacheEntry
		if !rcEntry.SetValue(replyWithErr.Reply) {
			panic(fmt.Sprintf("response %T not supported by response cache", replyWithErr.Reply))
		}
		return engine.MVCCPutProto(e, nil, key, proto.ZeroTimestamp, nil, &rcEntry)
	}

	return nil
}