azure - [kernel32.dll]RavenDb 嵌入式备份期间 Azure 网站上的 CreateHardLink 失败并显示 "Cannot create a file when that file already exists"

标签 azure ravendb azure-web-app-service kernel32 hardlink

我正在 Azure 网站内运行 RavenDb.Embedded v2.0.2370。

除了备份之外,所有这些都按预期工作。使用 EmbeddableDocumentStore.DocumentDatabase.StartBackup(...) 启动的备份例程过去工作得很好,直到我注意到最后一次成功的备份是在 1 月 30 日左右(不要问:-) )下午 6 点(UTC0)左右,并且在 2 月 11 日上午 8 点(UTC0)左右启动的下一次备份失败,之后到现在为止启动的所有其他备份也失败了。

因此,Azure 方面的这两个日期之间肯定发生了某些更改,因为自 2013 年 5 月以来,Web 应用程序没有发生任何更改或部署

所以我做了一些调查,以下是我的发现:

  • RavenDb 备份状态在每次启动备份后显示以下消息:

    Failed to complete backup because: Cannot create a file when that file already exists

  • enabling logging for RavenDb 之后,日志文件在运行备份时显示以下错误

    2014-04-12 10:38:20.5797,Raven.Storage.Esent.Backup.BackupOperation,Error,Failed to complete backup,"System.ComponentModel.Win32Exception (0x80004005): Cannot create a file when that file already exists at Raven.Database.Backup.DirectoryBackup.Prepare() at Raven.Storage.Esent.Backup.BackupOperation.Execute(Object ignored)

  • 根据 Azure Web Sites forum,在上次成功备份和第一次失败备份之间的时间段内没有对 Azure 网站进行计划维护。 2013年12月9日至15日和2014年3月10日至14日期间

  • 我确实在 Azure Service Dashboard 上注意到西欧地区的网站于 1 月 31 日出现问题,但该网站托管在北欧地区

  • 当 RavenDb 代码出现故障时 looking (even the last version) Raven.Database.Backup.DirectoryBackup.Prepare 时,似乎是在调用 CreateHardLink 时引发了异常 这是一个定义为

    的外部方法
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
    

    奇怪的是,代码实际上检查了上面显示的特定异常(0x80004005),但异常仍然抛出......

    if (Marshal.GetLastWin32Error() != 0x80004005)
      throw new Win32Exception();
    
  • 为了将 RavenDb 排除在等式之外,我创建了以下小程序,该程序模拟 RavenDb 在备份例程期间以及部署可执行文件并执行它之后实际执行的操作(通过 new azure portal 上找到的控制台功能)在 Azure 网站上它也失败了:

    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.InteropServices;
    
    namespace HardLinkCreationTester
    {
        public class Program
        {
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
    
            static void Main()
            {
                const string sourcePath = "TestSource";
                const string targetPath = "TestTarget";
                const string tempPath = "TestTemp";
    
                try
                {
                    Directory.CreateDirectory(sourcePath);
                    Directory.CreateDirectory(targetPath);
                    Directory.CreateDirectory(tempPath);
                    File.WriteAllText(Path.Combine(sourcePath, "testfile.txt"), "Test content");
    
                    string[] sourceFilesSnapshot = Directory.GetFiles(sourcePath);
                    for (int index = 0; index < sourceFilesSnapshot.Length; index++)
                    {
                        var sourceFile = sourceFilesSnapshot[index];
                        var destFileName = Path.Combine(tempPath, Path.GetFileName(sourceFile));
    
                        if (!CreateHardLink(destFileName, sourceFile, IntPtr.Zero))
                        {
                            // 'The system cannot find the file specified' is explicitly ignored here
                            if (Marshal.GetLastWin32Error() != 0x80004005)
                                throw new Win32Exception();
                        }
                    }
                }
                finally
                {
                    Directory.Delete(sourcePath);
                    Directory.Delete(targetPath);
                    Directory.Delete(tempPath);
                }
            }
        }
    }
    
  • 为了将我的特定 Web 应用程序也排除在等式之外,我创建了一个新的 Azure 网站并部署了上述相同的可执行文件,它也失败了

    <
  • 可以公平地假设它们尚未在 ReFS (which does not support hard links) 上运行但仍在使用 NTFS?

tl;博士

  • Azure 网站上发生了什么变化,导致以前可以正常工作的 [kernel32.dll]CreateHardLink 调用失败?

  • 如何在 RavenDb 代码外部或 RavenDb 代码内部修复此问题...?

最佳答案

更新:此问题现已修复。 CreateHardLink应该与 D:\home 一起使用路径。

我认为这是 Azure 网站的问题。基本上,当您尝试创建相对路径时,它默认为 D:\home\ 。该文件夹实际上并不存在于计算机上,但 Azure 网站为了方便起见伪造了它。然而,这里似乎导致了 CreateHardLink 的问题。功能。

如果您只是更改上面示例中的这一行

const string tempPath = "TestTemp";

到此

const string tempPath = @"C:\DWASFiles\Sites\<sitename>\VirtualDirectory0\site\TestTemp";

替换 <sitename>与您的网站名称

它会起作用的。

我对 RavenDb 并不是很熟悉,但作为一种解决方法,您可以尝试将这些目录更改为与上面类似的完整路径。我会同时报告该错误。让我知道这是否适合您

关于azure - [kernel32.dll]RavenDb 嵌入式备份期间 Azure 网站上的 CreateHardLink 失败并显示 "Cannot create a file when that file already exists",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23041289/

相关文章:

RavenDB 通过游标分页

c# - "pre-computed"map-reduce 索引(RavenDB/CouchDB)可以用于这种算法吗?

azure - Visual Studio 应用程序部署正在删除 Azure 网站上的额外文件

azure - 迭代数据工厂中的文件

sql-server - 将 Active Directory 管理员添加到 Azure SQL 服务器是否会影响管理员帐户

enums - 在 RavenDB 中将枚举存储为整数

azure - Azure 流量管理器的故障转移可靠吗?我还应该担心哪些其他问题?

visual-studio - 如何阻止.net-core在构建时不断添加文件夹

Azure 表存储 - 表扫描的速度有多快?

azure - 如何在 Jenkins Docker 容器中挂载 Azure 应用服务存储?