[kernel32.dll]在 RavenDb 嵌入式备份期间,Azure 网站上的 CreateHardLink 失败并显示“当该文件已存在时无法创建文件”
-
21-12-2019 - |
题
我正在 Azure 网站内运行 RavenDb.Embedded v2.0.2370。
除了备份之外,所有这些都按预期工作。备份例程启动于 EmbeddableDocumentStore.DocumentDatabase.StartBackup(...)
曾经工作得很好,直到我注意到最后一次成功的备份是在 1 月 30 日左右(不要问:-))下午 6 点(UTC0)左右,而下一次备份在 2 月 11 日上午 8 点(UTC0)左右失败,就像后来发起的所有其他项目一样。
因此,在 Azure 方面,这两个日期之间肯定发生了某些更改,因为自 2013 年 5 月以来,Web 应用程序没有发生任何更改或部署
所以我做了一些调查,以下是我的发现:
每次启动备份后,RavenDb 备份状态都会显示以下消息:
无法完成备份,因为:当文件已存在时无法创建该文件
后 为 RavenDb 启用日志记录 运行备份时日志文件显示以下错误
2014-04-12 10:38:20.5797,Raven.Storage.Esent.Backup.BackupOperation,错误,无法完成备份,“System.ComponentModel.Win32Exception (0x80004005):当该文件已经存在于raven.database.backup.directorybackup.prepare()上时,无法创建文件。
根据 Azure 网站论坛 在上次成功备份和第一次失败备份之间的时间段内,没有计划对 Azure 网站进行维护。2013年12月9日至15日以及2014年3月10日至14日
我确实注意到了 Azure 服务仪表板 西欧地区的网站于 1 月 31 日出现问题,但该网站托管在北欧地区
什么时候 寻找(即使是最后一个版本) 在 断层 RavenDb代码
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 在其备份例程期间以及在部署可执行文件并执行它之后(通过在 新的天蓝色门户)在 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 上运行(不支持硬链接)但仍在使用 NTFS?
太长了;博士
调用以下内容的 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 并不是很熟悉,但作为一种解决方法,您可以尝试将这些目录更改为与上面类似的完整路径。我会同时报告该错误。让我知道这是否适合你