private void UpdatePacketFromPlan(PacketPlan plan, Packet <T> packet) { foreach (var item in plan.Records) { if (this.updateEventHandler != null) { var old = packet.Get(item.Key); if (old != null) { /* * Changing indexed fields is not allowed, because * that would require an additional read/write pass, * because then the record belongs to a different * packet. (It would be inefficient to do a second pass.) */ var updatedRecord = updateEventHandler(old, item.Value); if (updatedRecord == null) { /* * If the event handler returns NULL, then it * wants to avoid the update. */ continue; } var newIndexPath = String.Join('\0', table.GetIndexPath(plan.Index, updatedRecord)); if (newIndexPath != plan.IndexPathStr) { throw new FatCatException($"An update event handler has changed indexed fields in " + $"a record for table '{table.Annotation.Name}'. Changing indexed fields inside OnUpdate functions is not allowed."); } /* * If the unique key has changed, * then remove the entry under the old key, * before setting the new. */ var newUnique = table.GetUnique(updatedRecord); if (newUnique != item.Key) { packet.Remove(item.Key); } packet.Set(newUnique, updatedRecord); continue; } } packet.Set(item.Key, item.Value); } foreach (var key in plan.Removed) { packet.Remove(key); } }
/// <summary> /// Removes a record by its unique key. /// </summary> public Transaction <T> Remove(T record) { foreach (var index in indices) { var indexPath = table.GetIndexPath(index, record); var indexPathStr = String.Join('\0', indexPath); if (!packetPlans.ContainsKey(indexPathStr)) { packetPlans[indexPathStr] = new PacketPlan(table, index, indexPath, indexPathStr); } packetPlans[indexPathStr].Remove(record); } return(this); }
/// <summary> /// Entry point for a worker thread /// </summary> /// <param name="packetPlan">Payload</param> private void CommitThread(PacketPlan packetPlan) { if (this.exception != null) { return; } try { var packet = new Packet <T>(this.table, packetPlan.Index, packetPlan.IndexPath); using (Locking.GetMutex(packet.FullPath).Lock()) { packet.Load(); packet.DeserializeDecompress(); this.UpdatePacketFromPlan(packetPlan, packet); packet.SerializeCompress(); packet.Save(); } } catch (Exception ex) { this.exception = ex; } }