public static extern int DispatchMessage(NativeMessage *lpMsg);
public static extern int PeekMessage(NativeMessage *lpMsg, void *hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);
public static extern int TranslateMessage(NativeMessage *lpMsg);
/// <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); } }