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); }
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); }
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); }
/// <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); } }