/// <summary> /// Not thread safe /// </summary> private DirectSingleFolderWriter GetExistingWriterByFolderKey(string folderKey) { DirectSingleFolderWriter retval = null; _directWritersByFolderKey.TryGetValue(folderKey, out retval); return(retval); }
/// <summary> /// Not thread safe /// </summary> private DirectSingleFolderWriter GetExistingWriterByRelativePath(string relativePath) { DirectSingleFolderWriter retval = null; _directWritersByRelativePath.TryGetValue(relativePath, out retval); return(retval); }
/// <summary> /// Check whether the writer is accessing data in the <paramref name="folder"/> or any of its descendants. /// Descandants include <paramref name="folder" /> itself. /// </summary> /// <param name="folder"> /// <see cref="IRepositoryFolder"/> instance representing the subtree (the folder and all its descendants) root /// </param> /// <param name="subtree"> /// <code>bool</code> indicating whether to check access to any of the descendants of <paramref name="folder"/> (<see langword="true"/>) /// or just <paramref name="folder"/> itself. /// </param> /// <returns> /// <see langword="true"/> if the accessor is accessing data in the specified folder or folders /// <see langword="false"/> otherwise /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="folder"/> is <see langword="null"/> /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="folder"/> is not attached to the same <see cref="IRepositoryManager"/> instance (<see cref="Repository"/>) /// </exception> /// <remarks> /// If <paramref name="folder"/> is the same as <see cref="Folder"/> the method returns <see langword="true"/>, even before acceppting /// any data. /// </remarks> public bool IsAccessing(IRepositoryFolder folder, bool subtree) { Check.DoRequireArgumentNotNull(folder, "folder"); if (!IsOpen) { return(false); } Exceptions.DifferentRepositoriesExceptionHelper.Check(folder.Repository, _repoFolder.Repository); bool retval = object.ReferenceEquals(folder, this.Folder); if (!retval) { lock (_directWritersByRelativePath) { if (subtree) { for ( var e = _directWritersByRelativePath.Values.GetEnumerator(); !retval && e.MoveNext(); retval = e.Current.Folder.IsDescendantOf(folder)) { } } else { DirectSingleFolderWriter writer = GetExistingWriterByFolderKey(folder.FolderKey); retval = writer != null && object.ReferenceEquals(folder, writer.Folder); } } } return(retval); }
/// <summary> /// Create single folder writer and add it to the collection of writers. /// </summary> /// <param name="targetFolder"> /// Target folder for writer /// </param> /// <returns> /// New initialised instance. If the method succeeds (does not throw exception) /// </returns> /// <remarks> /// Locking sequence: target folder lock start, then repo manager's registry lock/release, then direct writers collection lock/release, /// then target folder released. /// </remarks> private DirectSingleFolderWriter CreateWriter(IRepositoryFolder targetFolder, string normalisedRelativePath) { Check.RequireArgumentNotNull(targetFolder, "targetFolder"); RepositoryFolder.CheckNotDetached(targetFolder); IFolder folder = RepositoryFolder.CastFolder(targetFolder); Exceptions.DifferentRepositoriesExceptionHelper.Check(Folder.Repository, targetFolder.Repository); DirectSingleFolderWriter writer = null; ICoder compressor = GetCompressor(targetFolder: targetFolder); ICoder encryptor = GetEncryptor(targetFolder: targetFolder); lock (targetFolder) { Check.DoAssertLambda( object.ReferenceEquals(targetFolder, _repoFolder) || // this writer has already seized this folder as target !Folder.Repository.IsDataBeingWrittenTo(targetFolder, false), () => new InvalidOperationException(string.Format(StorageResources.WriterAlreadyExistsForFolder, targetFolder.LogicalPath))); writer = new DirectSingleFolderWriter(folder, compressor, encryptor); writer.EqualTimestampedItemsComparer = this.EqualTimestampedItemsComparer; lock (_directWritersByRelativePath) { _directWritersByRelativePath.Add(normalisedRelativePath, writer); _directWritersByFolderKey.Add(targetFolder.FolderKey, writer); } } writer.TrackUnsavedItems = TrackUnsavedItems; Check.Ensure(Repository.IsDataBeingWrittenTo(targetFolder, false)); return(writer); }