public static DeleteSet Read(IDSDecoder decoder) { var ds = new DeleteSet(); var numClients = (int)decoder.Reader.ReadVarUint(); Debug.Assert(numClients >= 0); for (int i = 0; i < numClients; i++) { decoder.ResetDsCurVal(); var client = (int)decoder.Reader.ReadVarUint(); var numberOfDeletes = (int)decoder.Reader.ReadVarUint(); if (numberOfDeletes > 0) { if (!ds.Clients.TryGetValue(client, out var dsField)) { dsField = new List <DeleteItem>(numberOfDeletes); ds.Clients[client] = dsField; } for (int j = 0; j < numberOfDeletes; j++) { var deleteItem = new DeleteItem(decoder.ReadDsClock(), decoder.ReadDsLength()); dsField.Add(deleteItem); } } } return(ds); }
internal StackItem(DeleteSet ds, IDictionary <int, int> beforeState, IDictionary <int, int> afterState) { DeleteSet = ds; BeforeState = beforeState; AfterState = afterState; // TODO: [alekseyk] Always needed? Meta = new Dictionary <string, object>(); }
internal Transaction(YDoc doc, object origin, bool local) { Doc = doc; DeleteSet = new DeleteSet(); BeforeState = Doc.Store.GetStateVector(); AfterState = new Dictionary <int, int>(); Changed = new Dictionary <AbstractType, ISet <string> >(); ChangedParentTypes = new Dictionary <AbstractType, IList <YEvent> >(); _mergeStructs = new List <AbstractStruct>(); Origin = origin; Meta = new Dictionary <string, object>(); Local = local; SubdocsAdded = new HashSet <YDoc>(); SubdocsRemoved = new HashSet <YDoc>(); SubdocsLoaded = new HashSet <YDoc>(); }
internal void CompareDS(DeleteSet ds1, DeleteSet ds2) { Assert.AreEqual(ds1.Clients.Count, ds2.Clients.Count); foreach (var kvp in ds1.Clients) { var client = kvp.Key; var deleteItems1 = kvp.Value; Assert.IsTrue(ds2.Clients.TryGetValue(client, out var deleteItems2)); Assert.AreEqual(deleteItems1.Count, deleteItems2.Count); for (int i = 0; i < deleteItems1.Count; i++) { var di1 = deleteItems1[i]; var di2 = deleteItems2[i]; if (di1.Clock != di2.Clock || di1.Length != di2.Length) { Assert.Fail("DeleteSets don't match"); } } } }
public void ReadAndApplyDeleteSet(IDSDecoder decoder, Transaction transaction) { var unappliedDs = new DeleteSet(); var numClients = decoder.Reader.ReadVarUint(); for (int i = 0; i < numClients; i++) { decoder.ResetDsCurVal(); var client = (int)decoder.Reader.ReadVarUint(); var numberOfDeletes = decoder.Reader.ReadVarUint(); if (!Clients.TryGetValue(client, out var structs)) { structs = new List <AbstractStruct>(); // NOTE: Clients map is not updated. } var state = GetState(client); for (int deleteIndex = 0; deleteIndex < numberOfDeletes; deleteIndex++) { var clock = decoder.ReadDsClock(); var clockEnd = clock + decoder.ReadDsLength(); if (clock < state) { if (state < clockEnd) { unappliedDs.Add(client, state, clockEnd - state); } var index = StructStore.FindIndexSS(structs, clock); // We can ignore the case of GC and Delete structs, because we are going to skip them. var str = structs[index]; // Split the first item if necessary. if (!str.Deleted && str.Id.Clock < clock) { var splitItem = (str as Item).SplitItem(transaction, clock - str.Id.Clock); structs.Insert(index + 1, splitItem); // Increase, we now want to use the next struct. index++; } while (index < structs.Count) { str = structs[index++]; if (str.Id.Clock < clockEnd) { if (!str.Deleted) { if (clockEnd < str.Id.Clock + str.Length) { var splitItem = (str as Item).SplitItem(transaction, clockEnd - str.Id.Clock); structs.Insert(index, splitItem); } str.Delete(transaction); } } else { break; } } } else { unappliedDs.Add(client, clock, clockEnd - clock); } } } if (unappliedDs.Clients.Count > 0) { // @TODO: No need for encoding+decoding ds anymore. using var unappliedDsEncoder = new DSEncoderV2(); unappliedDs.Write(unappliedDsEncoder); _pendingDeleteReaders.Add(new DSDecoderV2(new MemoryStream(unappliedDsEncoder.ToArray()))); } }
internal Snapshot(DeleteSet ds, IDictionary <int, int> stateMap) { DeleteSet = ds; StateVector = stateMap; }