public static async Task PutAsync(SerialSDS serial, bool forceReplace) { if (SDSStore == null) { return; //tests } try { Log.Minor("Storing serial SDS in DB: g" + serial.Generation); if (sdsPoller != null) { var latest = sdsPoller.Latest; if (latestPut != null && latestPut.Generation > latest.Generation) { latest = latestPut; } if (serial.Generation <= latest.Generation) { Log.Minor("Newer already online. Rejecting update"); return; //nothing to do } serial._rev = latest._rev; } await PutAsync(SDSStore, serial, forceReplace, null); latestPut = serial; Log.Minor("Stored serial SDS in DB: g" + serial.Generation); } catch (Exception ex) { Log.Error(ex); Log.Error("Failed to store serial SDS in DB: g" + serial.Generation); } }
public static void PutNow(SerialSDS serial, bool forceReplace) { if (OnPutSDS != null) { OnPutSDS(serial); } Try(() => { PutAsync(SDSStore, serial, forceReplace, null).Wait(); return(true); }, 3); }
public static Tuple <SerialSDS, SerialCCS> Begin(Int3 myID, Action <SerialSDS> fetchSDS, Action <SerialCCS> fetchCCS) { sdsPoller = new DBType.ContinuousPoller <SerialSDS>(null, (collection) => { SerialSDS latest = null; foreach (var candidate in collection) { if (latest == null || latest.Generation < candidate.Generation) { latest = candidate; } else if (latest.Generation == candidate.Generation) { //weird, but let's check if (!candidate.IC.IsEmpty) { throw new IntegrityViolation("SDS candidate at g=" + candidate.Generation + " is not consistent"); } if (candidate.Generation != latest.Generation) { throw new IntegrityViolation("SDS candidate at g=" + candidate.Generation + " mismatch with favorite at g=" + latest.Generation); } var comp = new Helper.Comparator() .Append(candidate.SerialEntities, latest.SerialEntities) .Finish(); if (comp != 0) { Log.Error("Persistent SDS data mismatch at g=" + candidate.Generation); if (comp < 0) { latest = candidate; } } } } if (!latest.IC.IsEmpty) { throw new IntegrityViolation("Chosen persistent SDS candidate at g=" + latest.Generation + " is not consistent"); } return(latest); }); sdsPoller.Start(SDSStore, myID.Encoded); sdsPoller.OnChange = serial => fetchSDS(serial); ccsPoller = new DBType.ContinuousPoller <SerialCCS>(null, (collection) => { SerialCCS latest = null; foreach (var candidate in collection) { if (latest == null || latest.Generation < candidate.Generation) { latest = candidate; } else if (latest.Generation == candidate.Generation) { //weird, but let's check if (candidate.Generation != latest.Generation) { throw new IntegrityViolation("CCS candidate at g=" + candidate.Generation + " mismatch with favorite at g=" + latest.Generation); } var comp = new Helper.Comparator() .Append(candidate.Data, latest.Data) .Finish(); if (comp != 0) { Log.Error("Persistent CCS data mismatch at g=" + candidate.Generation); if (comp < 0) { latest = candidate; } } } } return(latest); }); ccsPoller.Start(CCSStore, myID.Encoded); ccsPoller.OnChange = serial => fetchCCS(serial); return(new Tuple <SerialSDS, SerialCCS>(sdsPoller.Latest, ccsPoller.Latest)); }
private static void CheckIncoming(int currentTLG, SimulationContext ctx) { Tuple <Link, object> pair; while (incoming.TryTake(out pair)) { object obj = pair.Item2; Link lnk = pair.Item1; if (obj is ClientMessage) { Log.Error("Received client message via peer socket"); return; } if (obj is OldestGeneration) { int gen = ((OldestGeneration)obj).Generation; if (gen == lnk.OldestGeneration) { if (siblings.AllResponsive && siblings.OldestGeneration >= gen) { DB.RemoveInboundRCSsAsync(neighbors.Select(sibling => sibling.InboundRCSStackID), gen).Wait(); //maybe only now responsive } Log.Minor("OldestGen update from sibling " + lnk + ": Warning: Already moved to generation " + gen); return; } if (gen > lnk.OldestGeneration) { lnk.SetOldestGeneration(gen, currentTLG); lnk.Filter((id, o) => { SerialSDS sds = o as SerialSDS; if (sds != null) { return(sds.Generation >= gen); } RCS.Serial rcs = o as RCS.Serial; if (rcs != null) { return(rcs.Generation >= gen); } return(true); }); if (siblings.AllResponsive && siblings.OldestGeneration >= gen) { DB.RemoveInboundRCSsAsync(neighbors.Select(sibling => sibling.InboundRCSStackID), gen).Wait(); } } return; } if (obj is Tuple <int, RCS> ) { var rcs = (Tuple <int, RCS>)obj; if (rcs.Item1 <= stack.NewestConsistentSDSGeneration) { Log.Error("RCS update from sibling " + lnk + ": Rejected. Already moved past generation " + rcs.Item1); return; } FetchNeighborUpdate(stack.AllocateGeneration(rcs.Item1), lnk, rcs.Item2); return; } if (obj is RCS.Serial) { RCS.Serial rcs = (RCS.Serial)obj; if (rcs.Generation <= stack.NewestConsistentSDSGeneration) { Log.Error("RCS update from sibling " + lnk + ": Rejected. Already moved past generation " + rcs.Generation); return; } FetchNeighborUpdate(stack.AllocateGeneration(rcs.Generation), lnk, rcs.Data); return; } if (obj is SerialSDS) { //Debug.Assert(HaveSibling(lnk)); SerialSDS raw = (SerialSDS)obj; if (raw.Generation <= stack.OldestSDSGeneration) { Log.Minor("SDS update from sibling or DB: Rejected. Already moved past generation " + raw.Generation); return; } var existing = stack.FindGeneration(raw.Generation); if (existing != null && existing.IsFullyConsistent) { Log.Minor("SDS update from sibling or DB: Rejected. Generation already consistent: " + raw.Generation); return; } SDS sds = raw.Deserialize(); if (existing != null && existing.SDS.ICMessagesAndEntitiesAreEqual(sds)) { Log.Minor("SDS update from sibling or DB: Equal. Ignoring"); return; } if (sds.IsFullyConsistent) { Log.Minor("SDS update from sibling or DB: Accepted generation " + raw.Generation); stack.Insert(sds); return; } SDS merged = existing.SDS.MergeWith(sds, SDS.MergeStrategy.ExclusiveWithPositionCorrection, ctx); Log.Minor("SDS update from sibling " + lnk + ": Merged generation " + raw.Generation); if (merged.Inconsistency < existing.SDS.Inconsistency) { stack.Insert(merged); } if (merged.Inconsistency < sds.Inconsistency) { lnk.Set(new SDS.ID(ID.XYZ, raw.Generation).P2PKey, new SerialSDS(merged, Simulation.ID.XYZ)); } return; } if (obj is Tuple <int, MessagePack> ) { //Debug.Assert(HaveSibling(lnk)); var m = (Tuple <int, MessagePack>)obj; if (m.Item1 <= stack.OldestSDSGeneration) { Log.Minor("CCS update from sibling or DB: Rejected. Already moved past generation " + m.Item1); return; } Messages.Insert(m.Item1, m.Item2); return; } Log.Error("Unsupported update from sibling " + lnk + ": " + obj.GetType()); } }