Ejemplo n.º 1
0
 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];
 }
Ejemplo n.º 2
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;
 }
Ejemplo n.º 3
0
 private int CalcStackStize(CachedRequest[] batch)
 {
     var bsize = 0;
     foreach(var request in batch)
     {
         var key = request.Key;
         bsize += _align8(sizeof(DataKey) + (key == null ? 0 : key.Length));
     }
     return bsize;
 }
 private void Encode(CachedRequest request, int opaque)
 {
     if (request == null) 
         throw new ArgumentNullException();
     var opc = opaque == 0 ? request.Opcode : (int)QuietMap[request.Opcode];
     _packet.Reset(opc);
     if (opaque != 0) _packet.Opaque = (uint)opaque;
     var key = request.Key;
     switch ((Opcode)request.Opcode)
     {
         case Opcode.Get:
         case Opcode.GetQ:
         case Opcode.GetK:
         case Opcode.GetKq:
         case Opcode.Delete:
         case Opcode.DeleteQ:
             _packet.KeyLength = _packet.TotalBody = (uint)key.Length;
             _packet.WriteTo(_output);
             _output.WriteBytes(key, 0, key.Length);
             break;
         case Opcode.Set:
         case Opcode.SetQ:
         case Opcode.Add:
         case Opcode.AddQ:
         case Opcode.Replace:
         case Opcode.ReplaceQ:
             _packet.KeyLength = (uint)key.Length;
             _packet.ExtLength = 8;
             var data = request.Data;
             var vsz = data != null ? data.Length : 0;
             _packet.TotalBody = (uint)(key.Length + vsz + 8);
             if (request.Cas != 0) _packet.Cas = request.Cas;
             _packet.WriteTo(_output);
             _output.WriteB32BE((uint)request.Flags);
             _output.WriteB32BE(request.Expires);
             _output.WriteBytes(key, 0, key.Length);
             if (vsz > 0) _output.WriteBytes(data, 0, vsz);
             break;
         case Opcode.Noop:
         case Opcode.Version:
         case Opcode.Quit:
         case Opcode.QuitQ:
             _packet.WriteTo(_output);
             break;
         case Opcode.Flush:
         case Opcode.FlushQ:
             var expires = request.HasExpires;
             if (expires) _packet.ExtLength = _packet.TotalBody = 4;
             _packet.WriteTo(_output);
             if (expires) _output.WriteB32BE(request.Expires);
             break;
         case Opcode.Inc:
         case Opcode.IncQ:
         case Opcode.Dec:
         case Opcode.DecQ:
             _packet.ExtLength = 20;
             _packet.KeyLength = (uint)key.Length;
             _packet.TotalBody = (uint)(20 + key.Length);
             if (request.HasCas) _packet.Cas = request.Cas;
             _packet.WriteTo(_output);
             _output.WriteB64BE(request.Delta);
             _output.WriteB64BE(request.Flags);
             _output.WriteB32BE(request.Expires);
             _output.WriteBytes(key, 0, key.Length);
             break;
         case Opcode.Append:
         case Opcode.AppendQ:
         case Opcode.Prepend:
         case Opcode.PrependQ:
             _packet.KeyLength = (uint)key.Length;
             var pdata = request.Data;
             _packet.TotalBody = (uint)(key.Length + pdata.Length);
             if (request.Cas != 0) _packet.Cas = request.Cas;
             _packet.WriteTo(_output);
             _output.WriteBytes(key, 0, key.Length);
             _output.WriteBytes(pdata, 0, pdata.Length);
             break;
         default:
             throw new NotSupportedException();
     }
 }
Ejemplo n.º 5
0
 public CachedResponse(CachedRequest request)
 {
     Request = request;
 }
Ejemplo n.º 6
0
 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);
 }
Ejemplo n.º 7
0
        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;
            }
        }
Ejemplo n.º 8
0
 private DataKey* SetDataKey(DataKey* dk, CachedRequest rqs)
 {
     dk->cas = rqs.Cas;
     dk->etime = rqs.Expires;
     dk->flags = Pbs.SwapBytes((uint)rqs.Flags);
     if (!IncDecOps.Has(dk->opcode))
     {
         var data = rqs.Data;
         var size = rqs.DataCount;
         if (size > 0)
         {
             dk->ValSize = size;
             dk->val_addr = AllocValueMem(size);
             fixed (byte* ds = data)
                 dk->AppendValue(ds + rqs.DataOffset, size, 0);
         }
     }
     else
     {
         dk->longval = (long)rqs.Delta;
         dk->def_val = (long)rqs.Flags;
     }
     return dk;
 }