private void WriteLocked(string relativePath, byte[] data, FileMutex fileMutex)
        {
            if (Exists(GetFullPath(relativePath)))
            {
                File.WriteAllBytes(GetFullPath(relativePath), data);
            }
            else
            {
                fileMutex.Unlock();

                using (CreateDirectoriesLockParent(GetParentPath(relativePath)))
                {
                    if (!fileMutex.TryLock())
                    {
                        throw new InvalidOperationException("auth cannot lock file for write"); // todo: exception
                    }

                    File.WriteAllBytes(GetFullPath(relativePath), data);
                }
            }
        }
        public FileMutex CreateDirectoriesLockParent(string relativePath)
        {
            FileMutex parentFileMutex = null;

            if (!string.IsNullOrWhiteSpace(relativePath))
            {
                // Debug.WriteLine($"Getting parentFileMutex: ({Thread.CurrentThread.ManagedThreadId}) {key}");
                parentFileMutex = CreateDirectoriesLockParent(GetParentPath(relativePath));
            }

            try
            {
                var fileMutex = LockFile(relativePath);
                try
                {
                    string fullPath = GetFullPath(relativePath);
                    if (!Exists(fullPath))
                    {
                        Directory.CreateDirectory(fullPath);
                    }

                    return(fileMutex);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Exception caught: ({Thread.CurrentThread.ManagedThreadId}) {relativePath} --> {ex}");
                    fileMutex.Dispose();
                    throw;
                }
            }
            finally
            {
                // Debug.WriteLine($"Releasing parentFileMutex: ({Thread.CurrentThread.ManagedThreadId}) {key}");
                if (parentFileMutex != null)
                {
                    parentFileMutex.Dispose();
                    parentFileMutex = null;
                }
            }
        }