internal void Discard() { try { _persisting = true; _removedGraphs.Clear(); // Read-Only managers have no persistence if (_manager.IsReadOnly) { return; } // No actions mean no persistence necessary if (_actions.Count == 0) { return; } // Important - For discard we reverse the list of actions so that we // rollback the actions in appropriate order _actions.Reverse(); if (_manager.UpdateSupported) { // Persist based on Triple level actions // First group Triple together based on Graph URI while (_actions.Count > 0) { TripleStorePersistenceAction action = _actions[0]; if (action.IsTripleAction) { Queue <TriplePersistenceAction> actions = new Queue <TriplePersistenceAction>(); Uri currUri = _actions[0].TripleAction.Triple.GraphUri; actions.Enqueue(_actions[0].TripleAction); _actions.RemoveAt(0); // Find all the Triple actions related to this Graph up to the next non-Triple action for (int i = 0; i < _actions.Count && _actions[i].IsTripleAction; i++) { if (EqualityHelper.AreUrisEqual(currUri, _actions[i].TripleAction.Triple.GraphUri)) { actions.Enqueue(_actions[i].TripleAction); _actions.RemoveAt(i); i--; } } // Split the Triples for this Graph into batches of adds and deletes to ensure // accurate persistence of the actions bool toDelete = false; List <Triple> batch = new List <Triple>(); while (actions.Count > 0) { TriplePersistenceAction next = actions.Dequeue(); if (next.IsDelete != toDelete) { if (batch.Count > 0) { // Process a batch whenever we find a switch between additions and removals // This ensures that regardless of the logic in UpdateGraph() we force // additions and removals to happen in the order we care about // Important - For discard we flip the actions in order to reverse them // i.e. additions become removals and vice versa // Also for discard we only need to alter the in-memory state not actually // do any persistence since the actions will never have been persisted if (toDelete) { this[currUri].Assert(batch); } else { this[currUri].Retract(batch); } batch.Clear(); } toDelete = next.IsDelete; } batch.Add(next.Triple); } // Ensure the final batch (if any) gets processed if (batch.Count > 0) { // Important - For discard we flip the actions in order to reverse them // i.e. additions become removals and vice versa // Also for discard we only need to alter the in-memory state not actually // do any persistence since the actions will never have been persisted if (toDelete) { this[currUri].Assert(batch); } else { this[currUri].Retract(batch); } } } else { switch (action.GraphAction.Action) { case GraphPersistenceActionType.Added: // Need to remove from being in-memory Remove(action.GraphAction.Graph.BaseUri); break; case GraphPersistenceActionType.Deleted: // Need to add back into memory Add(action.GraphAction.Graph, false); break; } _actions.RemoveAt(0); } } } else { // Persist based on Graph level actions foreach (TripleStorePersistenceAction action in _actions) { // Important - For discard we flip the actions in order to reverse them // i.e. additions become removals and vice versa if (action.IsGraphAction) { if (action.GraphAction.Action == GraphPersistenceActionType.Added) { Remove(action.GraphAction.Graph.BaseUri); } else if (action.GraphAction.Action == GraphPersistenceActionType.Deleted) { Add(action.GraphAction.Graph, false); } } } } } finally { _persisting = false; } }
internal void Flush() { try { _persisting = true; _removedGraphs.Clear(); // Read-Only managers have no persistence if (_manager.IsReadOnly) { return; } // No actions means no persistence necessary if (_actions.Count == 0) { return; } if (_manager.UpdateSupported) { // Persist based on Triple level actions // First group Triple together based on Graph URI while (_actions.Count > 0) { TripleStorePersistenceAction action = _actions[0]; if (action.IsTripleAction) { Queue <TriplePersistenceAction> actions = new Queue <TriplePersistenceAction>(); Uri currUri = action.TripleAction.Triple.GraphUri; actions.Enqueue(_actions[0].TripleAction); _actions.RemoveAt(0); // Find all the Triple actions related to this Graph up to the next non-Triple action for (int i = 0; i < _actions.Count && _actions[i].IsTripleAction; i++) { if (EqualityHelper.AreUrisEqual(currUri, _actions[i].TripleAction.Triple.GraphUri)) { actions.Enqueue(_actions[i].TripleAction); _actions.RemoveAt(i); i--; } } // Split the Triple Actions for this Graph into batches of adds and deletes to ensure // accurate persistence of the actions bool toDelete = false; List <Triple> batch = new List <Triple>(); while (actions.Count > 0) { TriplePersistenceAction next = actions.Dequeue(); if (next.IsDelete != toDelete) { if (batch.Count > 0) { // Process a batch whenever we find a switch between additions and removals // This ensures that regardless of the logic in UpdateGraph() we force // additions and removals to happen in the order we care about if (toDelete) { _manager.UpdateGraph(currUri, null, batch); } else { _manager.UpdateGraph(currUri, batch, null); } batch.Clear(); } toDelete = next.IsDelete; } batch.Add(next.Triple); } // Ensure the final batch (if any) gets processed if (batch.Count > 0) { if (toDelete) { _manager.UpdateGraph(currUri, null, batch); } else { _manager.UpdateGraph(currUri, batch, null); } } } else { switch (action.GraphAction.Action) { case GraphPersistenceActionType.Added: // No need to do anything in-memory as will be in the graph collection // Call SaveGraph() with an empty graph to create the relevant graph // If Triples were added these will be persisted separately with // TriplePersistenceActions Graph g = new Graph(); g.BaseUri = action.GraphAction.Graph.BaseUri; _manager.SaveGraph(g); break; case GraphPersistenceActionType.Deleted: // No need to do anything in-memory as won't be in the graph collection // If DeleteGraph() is supported call it to delete the relevant graph if (_manager.DeleteSupported) { _manager.DeleteGraph(action.GraphAction.Graph.BaseUri); } break; } _actions.RemoveAt(0); } } } else { // Persist based on Graph level actions foreach (TripleStorePersistenceAction action in _actions) { if (action.IsGraphAction) { if (action.GraphAction.Action == GraphPersistenceActionType.Added) { _manager.SaveGraph(action.GraphAction.Graph); } else if (action.GraphAction.Action == GraphPersistenceActionType.Deleted && _manager.DeleteSupported) { // Can only delete graphs if deletion is supported _manager.DeleteGraph(action.GraphAction.Graph.BaseUri); } } } } } finally { _persisting = false; } }