CachedResponse ICachedClient.Execute(CachedRequest request) { var batch = new CachedRequest[1] { request }; var result = new CachedResponse[1] { new CachedResponse(request) }; ExecuteBatch(batch, result); return result[0]; }
CachedResponse[] ExecuteBatch(CachedRequest[] batch) { var response = new CachedResponse[batch.Length]; for (int i = 0; i < batch.Length; i++) response[i] = new CachedResponse(batch[i]); ExecuteBatch(batch, response); return response; }
private void Decode(CachedResponse rsp) { var cas = _packet.Cas; if (cas != 0) rsp.Cas = cas; switch ((Opcode)_packet.Command) { case Opcode.Get: case Opcode.GetQ: case Opcode.GetK: case Opcode.GetKq: rsp.Flags = _source.GetB32BE(); var szk = _packet.KeyLength; // skip key bytes, returned when GetK was issued. if (szk != 0) _source.Skip((int)szk); szk = _packet.TotalBody - szk - 4; rsp.Data = ExtractBytes((int)szk); break; case Opcode.Set: case Opcode.SetQ: case Opcode.Add: case Opcode.AddQ: case Opcode.Replace: case Opcode.ReplaceQ: break; case Opcode.Inc: case Opcode.IncQ: case Opcode.Dec: case Opcode.DecQ: rsp.Counter = _source.GetB64BE(); break; case Opcode.Noop: case Opcode.Delete: case Opcode.DeleteQ: case Opcode.Flush: break; case Opcode.Version: case Opcode.Stat: rsp.Data = ExtractBytes((int)_packet.TotalBody); break; case Opcode.Append: case Opcode.AppendQ: case Opcode.Prepend: case Opcode.PrependQ: break; default: throw new NotImplementedException(); } }
void IChannelSync.Dispatch(Message request, Message response) { var batch = new CachedRequest[1] { request as CachedRequest }; var result = new CachedResponse[1] { response as CachedResponse }; ExecuteBatch(batch, result); }
public void ExecuteBatch(CachedRequest[] batch, CachedResponse[] result) { if (batch == null || batch.Length == 0) return; // calculate transient memory space requirements. var bsize = CalcStackStize(batch); uint opaque = 1; DataKey* dataKey = null, last = null; var db = stackalloc byte[bsize]; var cp = db; // copy requests data into memcached protocol format. foreach(var request in batch) { var dk = (DataKey*)cp; _init_dk(dk, request.Opcode); var key = request.Key; if (key != null) { _set_key(dk, key, key.Length); cp += _align8(sizeof(DataKey) + key.Length); } else cp += sizeof(DataKey); dk->opaque = opaque++; dk = SetDataKey(dk, request); // append new request to dataKey list if (last == null) dataKey = dk; else last->next = dk; last = dk; } // execute built-up request chain against cache. ExecuteBatch(dataKey, 0); // move cached results into responses fields. foreach(var response in result) { // copy response data from datakey into message. var status = dataKey->status; response.Status = 0; switch (status) { case 0: response.Cas = dataKey->cas; response.Flags = Pbs.SwapBytes(dataKey->flags); var dtsize = dataKey->ValSize; if (dtsize > 0) { response.Data = new byte[dtsize]; _memcopy(response.Data, dataKey->val_addr, dtsize); } break; case iSpecialCommand: if (IncDecOps.Has(dataKey->opcode)) { response.Cas = dataKey->cas; response.Counter = (ulong)dataKey->longval; } else { //todo: support for more stats. if (dataKey->opcode == (byte)Opcode.Version) response.Data = sLocalVersion; } break; default: response.Status = status; break; } // advance datakey in sync with responses list. dataKey = dataKey->next; } }