/// <summary> /// Adds a new child. /// </summary> /// <param name="persistenceInformation">The persistence information that describes the dataset that should be copied.</param> /// <returns> /// The newly created dataset. /// </returns> public DatasetFacade AddChild(IPersistenceInformation persistenceInformation) { { Enforce.Argument(() => persistenceInformation); } // For user created datasets we have some default settings: // - We don't ever allow nodes to be adopted, it just creates too much of a hassle with // updating the node links etc. // - We always allow user created datasets to become parents, they may need to split // of their calculations // - We allow all user created datasets to be copied // - User created datasets can always be deleted var creationInformation = new DatasetCreationInformation { CanBeAdopted = false, CanBecomeParent = true, CanBeCopied = true, CanBeDeleted = true, CreatedOnRequestOf = DatasetCreator.User, LoadFrom = persistenceInformation, }; var child = m_Dataset.CreateNewChild(creationInformation); return(new DatasetFacade(child)); }
public void AddChildWithPersistenceInformation() { DatasetCreationInformation creationInformation = null; var storage = new Mock <IPersistenceInformation>(); var child = CreateMockDataset(); var dataset = new Mock <IProxyDataset>(); { dataset.Setup(d => d.StoredAt) .Returns(new Mock <IPersistenceInformation>().Object); dataset.Setup(d => d.CreateNewChild(It.IsAny <DatasetCreationInformation>())) .Callback <DatasetCreationInformation>(d => creationInformation = d) .Returns(child); } var facade = new DatasetFacade(dataset.Object); var childFacade = facade.AddChild(storage.Object); Assert.AreEqual(new DatasetFacade(child), childFacade); Assert.IsFalse(creationInformation.CanBeAdopted); Assert.IsTrue(creationInformation.CanBecomeParent); Assert.IsTrue(creationInformation.CanBeCopied); Assert.IsTrue(creationInformation.CanBeDeleted); Assert.AreEqual(DatasetCreator.User, creationInformation.CreatedOnRequestOf); Assert.AreEqual(storage.Object, creationInformation.LoadFrom); }
private DatasetProxy CreateNewDatasetProxy(DatasetCreationInformation newChild) { var id = new DatasetId(); Action <DatasetId> cleanupAction = localId => DeleteDatasetAndChildren(localId, d => { }); var parameters = new DatasetConstructionParameters { Id = id, Owner = this, DistributionPlanGenerator = m_DatasetDistributor, CreatedOnRequestOf = newChild.CreatedOnRequestOf, CanBecomeParent = newChild.CanBecomeParent, CanBeAdopted = newChild.CanBeAdopted, CanBeCopied = newChild.CanBeCopied, CanBeDeleted = newChild.CanBeDeleted, IsRoot = newChild.IsRoot, LoadFrom = newChild.LoadFrom, OnRemoval = cleanupAction, }; var newDataset = m_Timeline.AddToTimeline( DatasetProxy.CreateInstance, parameters, m_DataStorageProxyBuilder, m_Notifications, m_Diagnostics); return(newDataset); }
/// <summary> /// Creates a new child dataset and returns the ID number of the child. /// </summary> /// <param name="newChild">The information required to create the new child.</param> /// <returns> /// The ID number of the child. /// </returns> /// <exception cref="ArgumentException"> /// Thrown when the owning project has been closed. /// </exception> /// <exception cref="DatasetCannotBecomeParentException"> /// Thrown when the current dataset cannot become a parent. /// </exception> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="newChild"/> is <see langword="null" />. /// </exception> public IProxyDataset CreateNewChild(DatasetCreationInformation newChild) { { Lokad.Enforce.With <ArgumentException>( !Owner.IsClosed, Resources.Exceptions_Messages_CannotUseProjectAfterClosingIt); Lokad.Enforce.With <DatasetCannotBecomeParentException>( CanBecomeParent, Resources.Exceptions_Messages_DatasetCannotBecomeParent_WithId, Id); Lokad.Enforce.Argument(() => newChild); } return(Owner.CreateDataset(Id, newChild)); }
/// <summary> /// Creates a new dataset as child of the given parent dataset. /// </summary> /// <param name="parent">The parent.</param> /// <param name="newChild">The information required to create the new child.</param> /// <returns>The new child.</returns> public IProxyDataset CreateDataset(DatasetId parent, DatasetCreationInformation newChild) { { Debug.Assert(!IsClosed, "The project should not be closed if we want to create a new dataset."); Debug.Assert( (parent == null) || ((parent != null) && m_Datasets.Datasets.ContainsKey(parent)), "The provided parent node does not exist."); Debug.Assert( (parent == null) || ((parent != null) && m_Datasets.Datasets[parent].CanBecomeParent), "The given parent is not allowed to have children."); } m_Diagnostics.Log( LevelToLog.Trace, HostConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, Resources.Project_LogMessage_CreatingDataset_WithInformation, parent)); var dataset = CreateNewDatasetProxy(newChild); // When adding a new dataset there is no way we can create cycles because // we can only add new children to parents, there is no way to link an // existing node to the parent. lock (m_Lock) { m_Datasets.Datasets.Add(dataset.Id, dataset); m_Datasets.Graph.AddVertex(dataset.Id); } if (parent != null) { // Find the actual ID object that we have stored, the caller may have a copy // of ID. Using a copy of the real ID might cause issues when connecting the // graph so we only use the ID numbers that we have stored. var realParent = m_Datasets.Datasets[parent].Id; lock (m_Lock) { m_Datasets.Graph.AddEdge(new Edge <DatasetId>(realParent, dataset.Id)); } } RaiseOnDatasetCreated(); return(dataset); }
public void RollForwardWithDeletesOnly() { ITimeline timeline = null; timeline = new Timeline(t => BuildStorage(timeline, t)); var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null); var offline = new Mock <IDatasetOfflineInformation>(); var plan = new DistributionPlan( (p, t, r) => Task <DatasetOnlineInformation> .Factory.StartNew( () => new DatasetOnlineInformation( new DatasetId(), new EndpointId("id"), new NetworkIdentifier("machine"), new Mock <ISendCommandsToRemoteEndpoints>().Object, new Mock <INotifyOfRemoteEndpointEvents>().Object, systemDiagnostics), t, TaskCreationOptions.None, new CurrentThreadTaskScheduler()), offline.Object, new NetworkIdentifier("mymachine"), new DatasetActivationProposal()); Func <DatasetActivationRequest, CancellationToken, IEnumerable <DistributionPlan> > distributor = (r, c) => new List <DistributionPlan> { plan }; var proxyLayer = new Mock <IProxyCompositionLayer>(); var project = new Project( timeline, distributor, d => new DatasetStorageProxy( d, new GroupSelector( new Mock <IConnectGroups>().Object, proxyLayer.Object), proxyLayer.Object), new Mock <ICollectNotifications>().Object, systemDiagnostics); // Create a 'binary' tree of datasets. This should create the following tree: // X // / \ // / \ // / \ // / \ // / \ // X X // / \ / \ // / \ / \ // / \ / \ // X X X X // / \ / \ // X X X X var children = new List <DatasetId>(); var datasets = new Queue <IProxyDataset>(); var root = project.BaseDataset(); datasets.Enqueue(root); int count = 0; while (count < 10) { var creationInformation = new DatasetCreationInformation() { CreatedOnRequestOf = DatasetCreator.User, CanBecomeParent = true, CanBeAdopted = false, CanBeCopied = false, CanBeDeleted = true, LoadFrom = new Mock <IPersistenceInformation>().Object, }; var parent = datasets.Dequeue(); var newChildren = parent.CreateNewChildren(new DatasetCreationInformation[] { creationInformation, creationInformation }); foreach (var child in newChildren) { datasets.Enqueue(child); children.Add(child.Id); count++; } } var marks = new List <TimeMarker>(); marks.Add(project.History.Mark()); for (int i = children.Count - 1; i > -1; i--) { var child = project.Dataset(children[i]); child.Delete(); marks.Add(project.History.Mark()); } project.History.RollBackTo(marks[0]); for (int i = 1; i < marks.Count; i++) { project.History.RollForwardTo(marks[i]); Assert.AreEqual(children.Count - i + 1, project.NumberOfDatasets); for (int j = 0; j < children.Count; j++) { var child = project.Dataset(children[j]); if (j < children.Count - i) { Assert.IsTrue(child.IsValid); } else { Assert.IsNull(child); } } } }