Esempio n. 1
0
        public unsafe void PartionKeyTest()
        {
            byte appId   = 1;
            uint tableId = (uint)(Consts.SYS_EMPLOEE_MODEL_ID & 0xFFFFFF);

            int   partionKeySize = 0;
            byte  typeFlag       = 0; //TODO:根据是否分区设置
            byte *pkPtr          = stackalloc byte[5 + partionKeySize];

            pkPtr[0] = appId;
            byte *tiPtr = (byte *)&tableId;

            pkPtr[1] = tiPtr[2];
            pkPtr[2] = tiPtr[1];
            pkPtr[3] = tiPtr[0];
            pkPtr[4] = typeFlag;

            var key1  = new BytesKey(new IntPtr(pkPtr), 5 + partionKeySize);
            var cache = new LRUCache <BytesKey, ulong>(8, BytesKeyEqualityComparer.Default);

            cache.TryAdd(key1.CopyToManaged(), 12345);
            Assert.Equal(1, cache.Count);

            ulong value1 = 0;
            bool  getOk1 = cache.TryGet(key1, out value1);

            Assert.True(getOk1);
            Assert.Equal <ulong>(12345, value1);
        }
Esempio n. 2
0
        public unsafe void BytesKeyTest()
        {
            byte *data1 = stackalloc byte[5];

            for (int i = 0; i < 5; i++)
            {
                data1[i] = (byte)(i + 1);
            }
            var data2 = new byte[] { 1, 2, 3, 4, 5 };
            var key1  = new BytesKey(new IntPtr(data1), 5);
            var key2  = new BytesKey(data2);

            var hash1 = BytesKeyEqualityComparer.Default.GetHashCode(key1);
            var hash2 = BytesKeyEqualityComparer.Default.GetHashCode(key2);

            var cache = new LRUCache <BytesKey, int>(8, BytesKeyEqualityComparer.Default);

            cache.TryAdd(key1.CopyToManaged(), 12345);
            Assert.Equal(1, cache.Count);

            int  value1 = 0;
            bool getOk1 = cache.TryGet(key1, out value1);

            Assert.True(getOk1);
            Assert.Equal(12345, value1);

            int  value2 = 0;
            bool getOk2 = cache.TryGet(key2, out value2);

            Assert.True(getOk2);
            Assert.Equal(12345, value2);
        }
Esempio n. 3
0
            public bool Equals(BytesKey other)
            {
                if (other == null)
                {
                    return(false);
                }

                if (this == other)
                {
                    return(true);
                }

                return(NameComparer.Equals(this.UniqueName, other.UniqueName));
            }
            public bool Equals(BytesKey other)
            {
                if (other == null)
                {
                    return false;
                }

                if (this == other)
                {
                    return true;
                }

                return NameComparer.Equals(this.UniqueName, other.UniqueName);
            }
Esempio n. 5
0
        /// <summary>
        /// 处理Native委托Clr执行过滤扫描
        /// </summary>
        internal static unsafe void ScanByClr(IntPtr msgPtr)
        {
            NativeMessage *msg    = (NativeMessage *)msgPtr;
            var            shard  = msg->Shard;
            var            handle = msg->Handle;
            var            it     = msg->Data1;
            var            req    = msg->Data2;
            var            res    = msg->Data3;

            var queueOk = ThreadPool.UnsafeQueueUserWorkItem(s =>
            {
                //注意:需要处理异常
                //TODO:全局索引过滤特殊处理,本地索引可以通过Api直接读目标数据,但全局索引可考虑按批加载目标后再过滤

                IteratorKV itkv = new IteratorKV();
                var itkvPtr     = new IntPtr(&itkv);
                var reqInfo     = new ScanReqInfo();
                NativeApi.ScanGetReqInfo(req, new IntPtr(&reqInfo), it, itkvPtr); //注意同时填充第一条IteratorKV

                //处理过滤条件,注意:暂使用缓存方案,防止反复Expression.Compile(性能损耗太大)
                Debug.Assert(reqInfo.FilterPtr != IntPtr.Zero && reqInfo.FilterSize != IntPtr.Zero);
                BytesKey key = new BytesKey(reqInfo.FilterPtr, reqInfo.FilterSize.ToInt32());
                if (!filters.TryGet(key, out KVFilterFunc filterFunc))
                {
                    try
                    {
                        var filter = (Expressions.Expression)ModelStore.DeserializeModel(reqInfo.FilterPtr, reqInfo.FilterSize.ToInt32());
                        var body   = filter.ToLinqExpression(KVScanExpressionContext.Default); //TODO:参考FastExpressionCompiler直接编译
                        var exp    = Expression.Lambda <KVFilterFunc>(body,
                                                                      KVScanExpressionContext.Default.GetParameter("vp"),
                                                                      KVScanExpressionContext.Default.GetParameter("vs"),
                                                                      KVScanExpressionContext.Default.GetParameter("mv"),
                                                                      KVScanExpressionContext.Default.GetParameter("ts")
                                                                      );
                        //Expression<Func<KVTuple, bool>> exp = t => t.StringEquals(Consts.EMPLOEE_NAME_ID, testData); //测试过滤器2
                        //Expression<KVFilterFunc> exp = (vp, vs, mvcc, ts) => false;

                        filterFunc = exp.Compile(); //TODO:待进一步研究 exp.CompileFast();
                        filters.TryAdd(key.CopyToManaged(), filterFunc);
                    }
                    catch (Exception ex)
                    {
                        Log.Warn($"Compile filter expression error: Type: {ex.GetType()}\nMessage:{ex.Message}\nStack:{ex.StackTrace}");
                        NativeApi.ScanFinished(shard, handle, it, res, (uint)KVCommandError.ClrCompileFilterFailed);
                        return;
                    }
                }

                //int count = 0;
                //var sw = new Stopwatch();
                //long times = 0;
                //sw.Start();

                uint skipped = 0;
                uint taken   = 0;
                int itStatus = 0;
                while (true) //TODO:迭代过程异常处理
                {
                    //打印KV调试信息
                    //count++;
                    //var keyString = StringHelper.ToHexString(itkv.KeyPtr, itkv.KeySize.ToInt32());
                    //var valueString = StringHelper.ToHexString(itkv.ValuePtr, itkv.ValueSize.ToInt32());
                    //Log.Debug($"Key={keyString} Value={valueString}");

                    //开始过滤表达式判断
                    if (filterFunc(itkv.ValuePtr, itkv.ValueSize.ToInt32(), reqInfo.IsMvcc, reqInfo.Timestamp)) //50-60 -> 20
                    {
                        if (skipped < reqInfo.Skip)
                        {
                            skipped++;
                        }
                        else
                        {
                            NativeApi.ScanResponseAddKV(res, it, reqInfo.IsMvcc, reqInfo.Timestamp);
                            taken++;
                            if (taken >= reqInfo.Take)
                            {
                                break;
                            }
                        }
                    }

                    itStatus = NativeApi.ScanNextValidIterator(it, req, itkvPtr); //未优化前350-400 -> 95
                    if (itStatus == -1)                                           //读到已被GC的记录
                    {
                        NativeApi.ScanFinished(shard, handle, it, res, (uint)KVCommandError.ReadGCData);
                        return;
                    }
                    if (itStatus == 0)
                    {
                        break;
                    }
                } //end while

                //sw.Stop();
                //times += sw.ElapsedTicks;
                //Console.WriteLine($"Thread:{Thread.CurrentThread.ManagedThreadId} Scan:{count} 耗时:{sw.ElapsedMilliseconds}");
                //Console.WriteLine($"Scan:{count} 步骤耗时:{times / TimeSpan.TicksPerMillisecond}");
                NativeApi.ScanResponseSetSkipped(res, skipped); //TODO:移至ScanFinished参数
                NativeApi.ScanFinished(shard, handle, it, res, 0);
            }, null);

            if (!queueOk)
            {
                Log.Warn("Cannot queue scan task");
                NativeApi.ScanFinished(shard, handle, it, res, (uint)KVCommandError.ClrEnqueueTaskFailed);
            }
        }