private int ProcessAcquireRequest(Zeze.Net.Protocol p) { Acquire rpc = (Acquire)p; if (rpc.Sender.UserState == null) { rpc.SendResultCode(AcquireNotLogin); return(0); } switch (rpc.Argument.State) { case StateInvalid: // realease Release(rpc.Sender.UserState as CacheHolder, rpc.Argument.GlobalTableKey); rpc.Result = rpc.Argument; rpc.SendResult(); return(0); case StateShare: return(AcquireShare(rpc)); case StateModify: return(AcquireModify(rpc)); default: rpc.Result = rpc.Argument; rpc.SendResultCode(AcquireErrorState); return(0); } }
private int AcquireModify(Acquire rpc) { CacheHolder sender = (CacheHolder)rpc.Sender.UserState; rpc.Result = rpc.Argument; while (true) { CacheState cs = global.GetOrAdd(rpc.Argument.GlobalTableKey, (tabkeKeyNotUsed) => new CacheState()); lock (cs) { if (cs.AcquireStatePending == StateRemoved) { continue; } while (cs.AcquireStatePending != StateInvalid) { switch (cs.AcquireStatePending) { case StateShare: if (cs.Modify == sender) { logger.Debug("1 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireModifyDeadLockFound); return(0); } break; case StateModify: if (cs.Modify == sender || cs.Share.Contains(sender)) { logger.Debug("2 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireModifyDeadLockFound); return(0); } break; } logger.Debug("3 {0} {1} {2}", sender, rpc.Argument.State, cs); Monitor.Wait(cs); } cs.AcquireStatePending = StateModify; if (cs.Modify != null) { if (cs.Modify == sender) { logger.Debug("4 {0} {1} {2}", sender, rpc.Argument.State, cs); // 已经是Modify又申请,可能是sender异常关闭,又重启连上。 // 更新一下。应该是不需要的。 sender.Acquired[rpc.Argument.GlobalTableKey] = StateModify; rpc.SendResultCode(AcquireModifyAlreadyIsModify); cs.AcquireStatePending = StateInvalid; return(0); } int stateReduceResult = StateReduceException; Zeze.Util.Task.Run( () => { stateReduceResult = cs.Modify.Reduce(rpc.Argument.GlobalTableKey, StateInvalid); lock (cs) { Monitor.PulseAll(cs); } }, "GlobalCacheManager.AcquireModify.Reduce"); logger.Debug("5 {0} {1} {2}", sender, rpc.Argument.State, cs); Monitor.Wait(cs); switch (stateReduceResult) { case StateInvalid: cs.Modify.Acquired.TryRemove(rpc.Argument.GlobalTableKey, out var _); break; // reduce success default: // case StateReduceRpcTimeout: // case StateReduceException: // case StateReduceNetError: cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); logger.Error("XXX 9 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireModifyFaild); return(0); } cs.Modify = sender; sender.Acquired[rpc.Argument.GlobalTableKey] = StateModify; cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); logger.Debug("6 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.SendResult(); return(0); } List <Util.KV <CacheHolder, Reduce> > reducePending = new List <Util.KV <CacheHolder, Reduce> >(); HashSet <CacheHolder> reduceSuccessed = new HashSet <CacheHolder>(); bool senderIsShare = false; // 先把降级请求全部发送给出去。 foreach (CacheHolder c in cs.Share) { if (c == sender) { senderIsShare = true; reduceSuccessed.Add(sender); continue; } Reduce reduce = c.ReduceWaitLater(rpc.Argument.GlobalTableKey, StateInvalid); if (null != reduce) { reducePending.Add(Util.KV.Create(c, reduce)); } else { // 网络错误不再认为成功。整个降级失败,要中断降级。 // 已经发出去的降级请求要等待并处理结果。后面处理。 break; } } Zeze.Util.Task.Run( () => { // 一个个等待是否成功。WaitAll 碰到错误不知道怎么处理的, // 应该也会等待所有任务结束(包括错误)。 foreach (var reduce in reducePending) { try { reduce.Value.Future.Task.Wait(); if (reduce.Value.Result.State == StateInvalid) { // 后面还有个成功的处理循环,但是那里可能包含sender, // 在这里更新吧。 reduce.Key.Acquired.TryRemove(rpc.Argument.GlobalTableKey, out var _); reduceSuccessed.Add(reduce.Key); } else { reduce.Key.SetError(); } } catch (Exception ex) { reduce.Key.SetError(); // 等待失败不再看作成功。 logger.Error(ex, "Reduce {0} {1} {2} {3}", sender, rpc.Argument.State, cs, reduce.Value.Argument); } } lock (cs) { // 需要唤醒等待任务结束的,但没法指定,只能全部唤醒。 Monitor.PulseAll(cs); } }, "GlobalCacheManager.AcquireModify.WaitReduce"); logger.Debug("7 {0} {1} {2}", sender, rpc.Argument.State, cs); Monitor.Wait(cs); // 移除成功的。 foreach (CacheHolder successed in reduceSuccessed) { cs.Share.Remove(successed); } // 如果前面降级发生中断(break),这里就不会为0。 if (cs.Share.Count == 0) { cs.Modify = sender; sender.Acquired[rpc.Argument.GlobalTableKey] = StateModify; cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); // Pending 结束,唤醒一个进来就可以了。 logger.Debug("8 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.SendResult(); } else { // senderIsShare 在失败的时候,Acquired 没有变化,不需要更新。 // 失败了,要把原来是share的sender恢复。先这样吧。 if (senderIsShare) { cs.Share.Add(sender); } cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); // Pending 结束,唤醒一个进来就可以了。 logger.Error("XXX 10 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireModifyFaild); } // 很好,网络失败不再看成成功,发现除了加break, // 其他处理已经能包容这个改动,都不用动。 return(0); } } }
private int AcquireShare(Acquire rpc) { CacheHolder sender = (CacheHolder)rpc.Sender.UserState; rpc.Result = rpc.Argument; while (true) { CacheState cs = global.GetOrAdd(rpc.Argument.GlobalTableKey, (tabkeKeyNotUsed) => new CacheState()); lock (cs) { if (cs.AcquireStatePending == StateRemoved) { continue; } while (cs.AcquireStatePending != StateInvalid) { switch (cs.AcquireStatePending) { case StateShare: if (cs.Modify == sender) { logger.Debug("1 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireShareDeadLockFound); return(0); } break; case StateModify: if (cs.Modify == sender || cs.Share.Contains(sender)) { logger.Debug("2 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireShareDeadLockFound); return(0); } break; } logger.Debug("3 {0} {1} {2}", sender, rpc.Argument.State, cs); Monitor.Wait(cs); } cs.AcquireStatePending = StateShare; if (cs.Modify != null) { if (cs.Modify == sender) { cs.AcquireStatePending = StateInvalid; logger.Debug("4 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateModify; // 已经是Modify又申请,可能是sender异常关闭, // 又重启连上。更新一下。应该是不需要的。 sender.Acquired[rpc.Argument.GlobalTableKey] = StateModify; rpc.SendResultCode(AcquireShareAlreadyIsModify); return(0); } int stateReduceResult = StateReduceException; Zeze.Util.Task.Run( () => { stateReduceResult = cs.Modify.Reduce(rpc.Argument.GlobalTableKey, StateShare); lock (cs) { Monitor.PulseAll(cs); } }, "GlobalCacheManager.AcquireShare.Reduce"); logger.Debug("5 {0} {1} {2}", sender, rpc.Argument.State, cs); Monitor.Wait(cs); switch (stateReduceResult) { case StateShare: cs.Modify.Acquired[rpc.Argument.GlobalTableKey] = StateShare; cs.Share.Add(cs.Modify); // 降级成功,有可能降到 Invalid,此时就不需要加入 Share 了。 break; default: // 包含协议返回错误的值的情况。 // case StateReduceRpcTimeout: // case StateReduceException: // case StateReduceNetError: cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); logger.Error("XXX 8 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.Result.State = StateInvalid; rpc.SendResultCode(AcquireShareFaild); return(0); } cs.Modify = null; sender.Acquired[rpc.Argument.GlobalTableKey] = StateShare; cs.Share.Add(sender); cs.AcquireStatePending = StateInvalid; Monitor.Pulse(cs); logger.Debug("6 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.SendResult(); return(0); } sender.Acquired[rpc.Argument.GlobalTableKey] = StateShare; cs.Share.Add(sender); cs.AcquireStatePending = StateInvalid; logger.Debug("7 {0} {1} {2}", sender, rpc.Argument.State, cs); rpc.SendResult(); return(0); } } }