/// <summary> /// Tags a folder path to a tag with name same as the tag name that is passed as parameter /// </summary> /// <param name="path">The string value that represents the path of the folder to be tagged</param> /// <param name="tagname">The string value that represents the name of the tag the folder path is /// to be tagged to</param> /// <returns>the tag where the folder path is tagged to</returns> /// <exception cref="PathAlreadyExistsException">thrown if the folder path that is passed as /// parameter is already tagged to the tag</exception> /// <exception cref="RecursiveDirectoryException">thrown if the folder path that is passed as /// parameter is a parent path or a child path of another path that is already tagged to /// the tag</exception> public Tag TagFolder(string path, string tagname) { CurrentTime current = new CurrentTime(); Tag toTag = FindTag(tagname); if (toTag == null) { Tag tag = new Tag(tagname, current.CurrentTimeLong); tag.AddPath(path, current.CurrentTimeLong); lock (TagList) { _tagList.Add(tag); } _lastUpdatedDate = current.CurrentTimeLong; return tag; } else { if (toTag.IsDeleted) { lock (TagList) { _tagList.Remove(toTag); } Tag tag = new Tag(tagname, current.CurrentTimeLong); tag.AddPath(path, current.CurrentTimeLong); lock (TagList) { _tagList.Add(tag); } _lastUpdatedDate = current.CurrentTimeLong; return tag; } else { if (toTag.Contains(path)) { throw new PathAlreadyExistsException(path); } else if (TaggingHelper.CheckRecursiveDirectory(toTag, path)) { throw new RecursiveDirectoryException(path, tagname); } else { toTag.AddPath(path, current.CurrentTimeLong); _lastUpdatedDate = current.CurrentTimeLong; return toTag; } } } }
private void DeleteTagClean(Tag t) { //For each path in the path, convert it to physical path and if it exist, Clean the meta data. foreach (TaggedPath path in t.UnfilteredPathList) { string convertedPath = ProfilingLayer.Instance.ConvertLogicalToPhysical(path.PathName); if (Directory.Exists(convertedPath)) { CleanMetaData(new DirectoryInfo(convertedPath)); } } }
/// <summary> /// Add a Tag ( Notify from Merging ) /// </summary> /// <param name="tag">Tag that was added</param> internal void AddTag(Tag tag) { //if tag is deleted, nothing needs to be done. if (tag.IsDeleted) { return; } //If the tag is seamless, re-set the mode to seamless if (tag.IsSeamless) { SwitchMode(tag.TagName, TagMode.Manual); SwitchMode(tag.TagName, TagMode.Seamless); } else //set the mode to manual { SwitchMode(tag.TagName, TagMode.Manual); } }
private bool ManualSync(Tag tag, bool switchSeamless) { //Try and cleanup the deletepaths first before syncing. //This is the find all the folder that is deleted but still tagged. //This will ensure that if the folder does not exist, no files will be propagated over. FindAndCleanDeletedPaths(); //If the Tag is already synchronzing or is already queued , return false. if (CompareAndSyncController.Instance.IsQueuedOrSyncing(tag.TagName)) { return false; } //Retrieve the list of paths that are not deleted. List<string> paths = tag.FilteredPathListString; //Convert the path to physical address. List<string>[] filterPaths = ProfilingLayer.Instance.ConvertAndFilter(paths); //If the number of path is less than 2, does not sync and return a true //If switch Seamless is true , set the mode of the tag to seamless. if (filterPaths[0].Count < 2) { if (switchSeamless) { SetTagMode(tag, true); } return true; } //Create the manual Sync request and send it to CompareAndSyncController. ManualSyncRequest syncRequest = new ManualSyncRequest(filterPaths[0].ToArray(), tag.Filters, SyncConfig.Copy, tag.TagName, switchSeamless); CompareAndSyncController.Instance.Sync(syncRequest); return true; }
/// <summary> /// Switch the tag to the mode. Do the respective work. /// </summary> /// <param name="tag">Tag to switch</param> /// <param name="mode">true for seamless, false for manual</param> private void SwitchMonitorTag(Tag tag, bool mode) { // If the tag is deleted or the tag is queued or syncing, cannot switch. if (tag.IsDeleted || CompareAndSyncController.Instance.IsQueuedOrSyncing(tag.TagName)) { return; } //Try to get the state of the tag. TagState state; _switchingTable.TryGetValue(tag.TagName, out state); //If the state is undefined, switch the state and add it to the switching table. if (state == TagState.Undefined) { _switchingTable.Add(tag.TagName, mode ? TagState.ManualToSeamless : TagState.SeamlessToManual); } //call the internal method. if (mode) { StartMonitorTag(tag); } else { SetTagMode(tag, false); } }
/// <summary> /// Determines whether the logical ID exists in any tagged path in the tag that is passed as parameter /// </summary> /// <param name="tag">The <see cref="Tag"/> object that represents the tag to be checked</param> /// <param name="ID">The string value that represents the logical ID</param> /// <returns>true if the logical ID exists in any tagged path in the tag; otherwise, false</returns> private bool CheckID(Tag tag, string ID) { foreach (TaggedPath path in tag.FilteredPathList) { if (path.LogicalDriveId.Equals(ID)) { return true; } } return false; }
private void AddTag(Tag tag) { _taglist.Add(tag); }
/// <summary> /// Creates a tag Xml element from the tag that is passed as parameter /// </summary> /// <param name="xmlDoc">The Xmldocument object that represents the Xml document that the /// Xml element to be created belongs to</param> /// <param name="tag">The <see cref="Tag">Tag</see> object that /// represents the tag to be used to create the Xml element</param> /// <returns>the tag Xml element that is created</returns> private static XmlElement CreateTagElement(XmlDocument xmlDoc, Tag tag) { XmlElement tagElement = xmlDoc.CreateElement(ELE_TAG_ROOT); tagElement.SetAttribute(ATTR_TAG_NAME, tag.TagName); tagElement.SetAttribute(ATTR_TAG_CREATEDDATE, tag.CreatedDate.ToString()); tagElement.SetAttribute(ATTR_TAG_LASTUPDATEDDATE, tag.LastUpdatedDate.ToString()); tagElement.SetAttribute(ATTR_TAG_ISDELETED, tag.IsDeleted.ToString()); tagElement.SetAttribute(ATTR_TAG_DELETEDDATE, tag.DeletedDate.ToString()); tagElement.AppendChild(CreateFoldersElement(xmlDoc, tag)); tagElement.AppendChild(CreateFilterElementList(xmlDoc, tag)); tagElement.AppendChild(CreateConfigElement(xmlDoc, tag)); return tagElement; }
/// <summary> /// Creates a folder list Xml element from the tag that is passed as parameter /// </summary> /// <param name="xmlDoc">The Xmldocument object that represents the Xml document that the /// Xml element to be created belongs to</param> /// <param name="tag">The <see cref="Tag">Tag</see> object that /// represents the tag to be used to create the Xml element</param> /// <returns>the folder list Xml element that is created</returns> private static XmlElement CreateFoldersElement(XmlDocument xmlDoc, Tag tag) { List<TaggedPath> pathList = tag.UnfilteredPathList; XmlElement foldersElement = xmlDoc.CreateElement(ELE_FOLDER_ROOT); foreach (TaggedPath path in pathList) { XmlElement taggedFolderElement = CreateTaggedFolderElement(xmlDoc, path); foldersElement.AppendChild(taggedFolderElement); } return foldersElement; }
/// <summary> /// Creates a tag removed notification /// </summary> /// <param name="tag">The <see cref="Tag">Tag</see> object that represents the tag that is /// removed</param> /// <returns>the <see cref="RemoveTagNotification">RemoveTagNotification</see> object</returns> public static AbstractNotification CreateRemoveTagNotification(Tag tag) { return new RemoveTagNotification(tag); }
/// <summary> /// Creates a tag from the Xml element that is passed as parameter /// </summary> /// <param name="tagElement">The XmlElement object that represents the Xml element that is to /// be used to create the tag</param> /// <returns>the tag that is created if there is no FormatException thrown or the attributes /// of tag are not null; otherwise, null</returns> private static Tag CreateTagFromXml(XmlElement tagElement) { try { string tagname = tagElement.GetAttribute(ATTR_TAG_NAME); if (tagname.Equals(string.Empty)) { return null; } long created = long.Parse(tagElement.GetAttribute(ATTR_TAG_CREATEDDATE)); long lastupdated = long.Parse(tagElement.GetAttribute(ATTR_TAG_LASTUPDATEDDATE)); bool isdeleted = bool.Parse(tagElement.GetAttribute(ATTR_TAG_ISDELETED)); long deleteddate = long.Parse(tagElement.GetAttribute(ATTR_TAG_DELETEDDATE)); Tag tag = new Tag(tagname, created); tag.LastUpdatedDate = lastupdated; tag.IsDeleted = isdeleted; tag.DeletedDate = deleteddate; XmlNodeList tagChildren = tagElement.ChildNodes; foreach (XmlElement tagChild in tagChildren) { if (tagChild.Name.Equals(ELE_FOLDER_ROOT)) { List<TaggedPath> pathList = CreateFolders(tagChild); if (pathList == null) { return null; } else { tag.FilteredPathList = pathList; } } else if (tagChild.Name.Equals(ELE_FILTER_ROOT)) { List<Filter> filterList = LoadFilterList(tagChild); if (filterList == null) { return null; } else { tag.Filters = filterList; try { tag.FiltersUpdatedDate = long.Parse(tagChild.GetAttribute(ATTR_FILTER_LASTUPDATEDDATE)); } catch (FormatException) { return null; } } } else if (tagChild.Name.Equals(ELE_CONFIG_ROOT)) { TagConfig tagConfig = CreateTagConfig(tagChild); if (tagConfig == null) { return null; } else { tag.Config = tagConfig; } } } return tag; } catch (FormatException) { return null; } catch (XmlException) { return null; } }
/// <summary> /// Creates a monitor path notification /// </summary> /// <param name="tag">The <see cref="Tag">Tag</see> object that represents the tag</param> /// <param name="path">The string value that represents the path that is monitored</param> /// <returns>the <see cref="MonitorPathNotification">MonitorPathNotification</see> object</returns> public static AbstractNotification CreateMonitorPathNotification(Tag tag, TaggedPath path) { return new MonitorPathNotification(tag, path); }
/// <summary> /// Creates a tag added notification /// </summary> /// <param name="tag">The <see cref="Tag">Tag</see> object that represents the tag that is added</param> /// <returns>the <see cref="AddTagNotification">AddTagNotification</see> object</returns> public static AbstractNotification CreateAddTagNotification(Tag tag) { return new AddTagNotification(tag); }
/// <summary> /// Initalize the MonitorPathNotificaiton /// </summary> /// <param name="tag">The target <see cref="Tag"/></param> /// <param name="path">The target <see cref="TaggedPath"/></param> public MonitorPathNotification(Tag tag, TaggedPath path):base("Monitor Path Notification" , Syncless.Notification.NotificationCode.MonitorPathNotification) { TargetTag = tag; TargetPath = path; }
/// <summary> /// Gets the tag with name that is same as the tag name that is passed as parameter /// </summary> /// <param name="tagname">The string value that represents the tag name of the tag /// to be retrieved</param> /// <param name="create">The boolean value that indicates whether to create the tag if /// it does not exist</param> /// <param name="getdeleted">The boolean value that indicates whether to retrieve tag /// which is set as deleted</param> /// <param name="lastupdated">The long value that represents the current date time to be /// assigned to the tag if it is newly created</param> /// <returns>the tag if it is found or created; otherwise, null</returns> private Tag RetrieveTag(string tagname, bool create, bool getdeleted, long lastupdated) { Tag tag = GetTag(tagname); if (tag != null) { if (tag.IsDeleted) { if (getdeleted) { return tag; } else { return null; } } else { return tag; } } else { if (create) { tag = new Tag(tagname, lastupdated); } return tag; } }
/// <summary> /// Creates a filter list Xml element from the tag that is passed as parameter /// </summary> /// <param name="xmlDoc">The Xmldocument object that represents the Xml document that the /// Xml element to be created belongs to</param> /// <param name="tag">The <see cref="Tag">Tag</see> object that /// represents the tag to be used to create the Xml element</param> /// <returns>the filter list Xml element that is created</returns> private static XmlElement CreateFilterElementList(XmlDocument xmlDoc, Tag tag) { List<Filter> filters = tag.Filters; XmlElement filterRoot = xmlDoc.CreateElement(ELE_FILTER_ROOT); filterRoot.SetAttribute(ATTR_FILTER_LASTUPDATEDDATE, tag.FiltersUpdatedDate.ToString()); foreach (Filter f in filters) { XmlElement filterEle = CreateFilterElement(xmlDoc, f); filterRoot.AppendChild(filterEle); } return filterRoot; }
/// <summary> /// Gets the tag with name that is same as the tag name that is passed as parameter /// </summary> /// <param name="tagname">The string value that represents the tag name of the tag /// to be retrieved</param> /// <param name="create">The boolean value that indicates whether to create the tag if /// it does not exist</param> /// <param name="lastupdated">The long value that represents the current date time to be /// assigned to the tag if it is newly created</param> /// <returns>the tag if it is found or created; otherwise, null</returns> private Tag RetrieveTag(string tagname, bool create, long lastupdated) { Tag tag = GetTag(tagname); if (tag == null) { if (create) { tag = new Tag(tagname, lastupdated); } } return tag; }
/// <summary> /// Creates a tag config Xml element from the tag that is passed as parameter /// </summary> /// <param name="xmlDoc">The Xmldocument object that represents the Xml document that the /// Xml element to be created belongs to</param> /// <param name="tag">The <see cref="Tag">Tag</see> object that /// represents the tag to be used to create the Xml element</param> /// <returns>the tag config Xml element that is created</returns> private static XmlElement CreateConfigElement(XmlDocument xmlDoc, Tag tag) { TagConfig config = tag.Config; XmlElement configElement = xmlDoc.CreateElement(ELE_CONFIG_ROOT); XmlElement seamlessElement = xmlDoc.CreateElement(ELE_CONFIG_SEAMLESS); seamlessElement.InnerText = tag.IsSeamless.ToString(); configElement.AppendChild(seamlessElement); return configElement; }
private void TestCreateTag(TestCase testcase) { string tagname = testcase.Parameters; Tag tag = new Tag(tagname, DateTime.Now.Ticks); _taglist.Add(tag); testcase.Actual = _taglist.Count.ToString(); testcase.Passed = (testcase.Expected.Equals(testcase.Actual)); }
/// <summary> /// Merges two tags with the same tag name by merging the tagged paths in each tag /// </summary> /// <param name="current">The <see cref="Tag">Tag</see> object that represents the current tag</param> /// <param name="newTag">The <see cref="Tag">Tag</see> object that represents the new tag</param> /// <returns>true if the tags are merged, false if the tags have different tag name or /// same last updated date or different last updated date</returns> private static bool MergeTag(Tag current, Tag newTag) { if (!newTag.TagName.ToLower().Equals(current.TagName.ToLower())) { //Since Tag name is different , do not merge. //Should not Happen. return false; } if (newTag.LastUpdatedDate == current.LastUpdatedDate) { //Since Tag updated time is same , shall not do anything return false; } else {//Since time different , merge. //if new Tag is deleted and current is not if (newTag.IsDeleted && !current.IsDeleted) { //delete only if deleted date is more than created date. if (newTag.DeletedDate > current.CreatedDate) { ServiceLocator.LogicLayerNotificationQueue().Enqueue(new RemoveTagNotification(newTag)); return true; } //do nothing return false; } //for each taggedPath found in the new Tag. //if the path is not found , just create //if the path is found , attempt to merge. if (current.IsDeleted && !newTag.IsDeleted) { if (newTag.CreatedDate > current.DeletedDate) { TaggingLayer.Instance.AddTag(newTag); ServiceLocator.LogicLayerNotificationQueue().Enqueue(new AddTagNotification(newTag)); return true; } } foreach (TaggedPath newPath in newTag.UnfilteredPathList) { TaggedPath currentPath = current.FindPath(newPath.PathName, false); if (currentPath == null) { ServiceLocator.LogicLayerNotificationQueue().Enqueue(new MonitorPathNotification(current,newPath)); current.AddPath(newPath); } else { //update only if the new path is more updated than the current path if (currentPath.LastUpdatedDate <= newPath.LastUpdatedDate) { //if the path is delete in the new tag but not in the old tag if (newPath.IsDeleted && !currentPath.IsDeleted) { if (newPath.DeletedDate > currentPath.CreatedDate) { current.RemovePath(newPath); ServiceLocator.LogicLayerNotificationQueue().Enqueue(new UnMonitorPathNotification(current,newPath)); } } else if (!newPath.IsDeleted && currentPath.IsDeleted) { if (newPath.CreatedDate > currentPath.DeletedDate) { //a new path is created in the new tag but is deleted in the old tag. current.AddPath(newPath); ServiceLocator.LogicLayerNotificationQueue().Enqueue(new MonitorPathNotification(current,newPath)); } } } } } } return true; }
/// <summary> /// Set the mode of the tag to the mode. /// <remarks> /// This is a direct set method. Should only be call by the notification after a Sync is complete or if switching from seamless to manual. /// If a tag is switch from manual to seamless without doing a manual sync, the tag may not be in sync and seamless mode may not work in a proper way. /// </remarks> /// </summary> /// <param name="tag">The <see cref="Tag"/> to set the mode.</param> /// <param name="mode">true if the mode is seamless, false if the mode is manual</param> private void SetTagMode(Tag tag, bool mode) { //set the tag to the mode. tag.IsSeamless = mode; //Initiate a Save. InitiateSave(); //Retrieve all the Path string from the list of path that are not deleted from the tag. List<string> pathList = new List<string>(); //Convert all the paths to physical path. //if mode is seamless, start monitoring all of them. //if mode is manual, unmonitor all of them. if (mode) { foreach (TaggedPath path in tag.FilteredPathList) { pathList.Add(path.PathName); } List<string> convertedPath = ProfilingLayer.Instance.ConvertAndFilterToPhysical(pathList); foreach (string path in convertedPath) { try { MonitorLayer.Instance.MonitorPath(PathHelper.RemoveTrailingSlash(path)); } catch (MonitorPathNotFoundException) { } } } else { foreach (TaggedPath path in tag.FilteredPathList) { List<Tag> tagList = TaggingLayer.Instance.RetrieveTagByPath(path.PathName); bool found = false; foreach (Tag tempTag in tagList) { if (tempTag.TagName != tag.TagName && tempTag.IsSeamless) { found = true; break; } } if (found) { continue; } pathList.Add(path.PathName); } List<string> convertedPath = ProfilingLayer.Instance.ConvertAndFilterToPhysical(pathList); foreach (string path in convertedPath) { try { MonitorLayer.Instance.UnMonitorPath(PathHelper.RemoveTrailingSlash(path)); } catch (MonitorPathNotFoundException) { } } } //try to remove the tag from the switching table //this will ensure that the ui can update the current state of the tag. try { if (_switchingTable.ContainsKey(tag.TagName)) { _switchingTable.Remove(tag.TagName); } } catch (Exception e) { //this should not happen but record it down just in case. //This should not affect the flow of the application so shall not report. ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e); } }
/// <summary> /// Initialize the RemoveTagNotification /// </summary> /// <param name="tag"></param> public RemoveTagNotification(Tag tag) : base("Remove Tag Notification", NotificationCode.DeleteTagNotification) { Tag = tag; }
/// <summary> /// Sync the tag then monitor the tag. /// </summary> /// <param name="tag">The Tag to Start Monitor</param> private void StartMonitorTag(Tag tag) { ManualSync(tag, true); }
/// <summary> /// Initialize UnMonitorPathNotification /// </summary> /// <param name="tag">the related <see cref="Tag"/></param> /// <param name="path">the related <see cref="TaggedPath"/></param> public UnMonitorPathNotification(Tag tag, TaggedPath path):base("UnMonitor Path Notification" , NotificationCode.UnmonitorPathNotification) { TargetTag = tag; _targetPath = path; }
/// <summary> /// Convert a <see cref="Tag"/> to a <see cref="TagView"/> for UI. /// </summary> /// <param name="t">The tag to convert</param> /// <returns>return the <see cref="TagView"/> representing the Tag.</returns> private TagView ConvertToTagView(Tag t) { //Find and clean all the deleted folder that are still tag. FindAndCleanDeletedPaths(); //Create the Tag View //Convert the path. List<string>[] pathList = ProfilingLayer.Instance.ConvertAndFilter(t.FilteredPathListString); //a list of available path PathGroupView availGrpView = new PathGroupView("Available"); List<PathView> pathViewList = new List<PathView>(); foreach (string path in pathList[0]) { PathView p = new PathView(path); if (!Directory.Exists(path)) { p.IsMissing = false; } pathViewList.Add(p); } availGrpView.PathList = pathViewList; TagView view = new TagView(t.TagName, t.LastUpdatedDate); view.GroupList.Add(availGrpView); view.Created = t.CreatedDate; view.IsQueued = CompareAndSyncController.Instance.IsQueued(t.TagName); view.IsSyncing = CompareAndSyncController.Instance.IsSyncing(t.TagName); view.TagState = GetTagState(view.TagName); return view; }
/// <summary> /// Initialize the AddTagNotification /// </summary> /// <param name="tag"></param> public AddTagNotification(Tag tag) : base("Add Tag Notification", NotificationCode.AddTagNotification) { Tag = tag; }
/// <summary> /// Remove a Tag Path ( Notify from Merging ) /// </summary> /// <param name="tag">Tag that the path was removed from</param> /// <param name="path">Path that is added</param> internal void RemoveTagPath(Tag tag, TaggedPath path) { //At the moment nothing needs to be done , just switch the tag to manual and back to seamless will do. if (tag.IsSeamless) { SwitchMode(tag.TagName, TagMode.Manual); SwitchMode(tag.TagName, TagMode.Seamless); } }
/// <summary> /// Adds a tag to the current tagging profile /// </summary> /// <param name="tag">The <see cref="Tag"/> object that represents the tag to be added</param> /// <remarks>Used for merging tag objects from several tagging profiles.</remarks> public void AddTag(Tag tag) { _taggingProfile.AddTag(tag); }
/// <summary> /// Remove a Tag ( Notify from Merging ) /// </summary> /// <param name="tag">Tag that is removed.</param> internal void RemoveTag(Tag tag) { try { //Unmonitor the tag first then delete the tag. SwitchMode(tag.TagName, TagMode.Manual); TaggingLayer.Instance.DeleteTag(tag.TagName); _userInterface.TagsChanged(); _userInterface.TagChanged(tag.TagName); } catch (TagNotFoundException te) { ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(te); } catch (Exception e)// Handle Unexpected Exception { ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e); } }
/// <summary> /// Removes the tag that is passed as parameter from the list of tags /// </summary> /// <param name="tag">The <see cref="Tag">Tag</see> object that represents the tag to be removed</param> /// <returns>the tag that is deleted if it is deleted; otherwise, null</returns> public Tag DeleteTag(Tag tag) { Tag toRemove = FindTag(tag.TagName); if (toRemove != null) { if (toRemove.IsDeleted) { return null; } else { CurrentTime updated = new CurrentTime(); toRemove.Remove(updated.CurrentTimeLong); _lastUpdatedDate = updated.CurrentTimeLong; return toRemove; } } else { return null; } }