[kernel32.dll]CreateHardLink falha com “Não é possível criar um arquivo quando esse arquivo já existe” no site do Azure durante o backup incorporado do RavenDb

StackOverflow https://stackoverflow.com//questions/23041289

Pergunta

Estou executando o RavenDb.Embedded v2.0.2370 dentro de um site do Azure.

Tudo isso está funcionando conforme o esperado, exceto o backup.A rotina de backup iniciada com EmbeddableDocumentStore.DocumentDatabase.StartBackup(...) costumava funcionar perfeitamente até que percebi que o último backup bem-sucedido data de 30 de janeiro (não pergunte :-)) por volta das 18h UTC0 e que o próximo backup iniciado em 11 de fevereiro por volta das 8h UTC0 falhou, assim como todos os outros iniciados posteriormente até agora.

Então parece que algo deve ter mudado entre essas duas datas do lado do Azure, já que não houve alterações ou implantações da aplicação web desde maio de 2013

Então fiz algumas investigações e aqui estão minhas descobertas:

  • O status do backup RavenDb mostra a seguinte mensagem após cada backup iniciado:

    Falha ao concluir o backup porque:Não é possível criar um arquivo quando esse arquivo já existe

  • Depois habilitando o log para RavenDb o arquivo de log mostra o seguinte erro ao executar o backup

    12/04/2014 10:38:20.5797,Raven.Storage.Esent.Backup.BackupOperation,Erro,Falha ao concluir o backup,"System.ComponentModel.Win32Exception (0x80004005):Não é possível criar um arquivo quando esse arquivo já existe em Raven.database.backup.directorybackup.Prepare () em Raven.Storage.Estor.Backup.BackuPoperation.execute (Objeto ignorado)

  • De acordo com Fórum de Sites do Azure não houve nenhuma manutenção planejada dos Sites do Azure no período entre o último backup bem-sucedido e o primeiro com falha.Houve entre 9 e 15 de dezembro de 2013 e entre 10 e 14 de março de 2014

  • eu notei no Painel de serviço do Azure um problema com os sites em 31 de janeiro na região da Europa Ocidental, mas o site está hospedado na região do Norte da Europa

  • Quando olhando (até mesmo a última versão) no falhando Código RavenDb Raven.Database.Backup.DirectoryBackup.Prepare parece que a exceção está sendo lançada ao chamar CreateHardLink que é um método externo definido como

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

    O estranho é que o código realmente verifica a exceção específica mostrada acima (0x80004005), mas a exceção ainda é lançada...

    if (Marshal.GetLastWin32Error() != 0x80004005)
      throw new Win32Exception();
    
  • Então, para excluir o RavenDb da equação, criei o seguinte pequeno programa que simula o que o RavenDb está realmente fazendo durante sua rotina de backup e após implantar o executável e executá-lo (através do recurso Console encontrado no novo portal azul) no site do Azure também falha:

    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);
                }
            }
        }
    }
    
  • Para excluir também meu aplicativo Web específico da equação, criei um novo site do Azure e implantei o mesmo executável mencionado acima e também falha

  • É justo assumir que eles ainda não estão rodando no ReFS (que não suporta links físicos), mas ainda está usando NTFS?

dr.

  • O que mudou nos sites do Azure que fazem uma chamada para [kernel32.dll]CreateHardLink falhar enquanto funcionava antes?

  • Como isso pode ser corrigido fora do código RavenDb ou dentro do código RavenDb...?

Foi útil?

Solução

Atualizar: esse problema foi corrigido agora. CreateHardLink deveria trabalhar com D:\home caminhos.

Acho que é um problema com os sites do Azure.Basicamente, quando você tenta criar um caminho relativo, o padrão é D:\home\.Na verdade, essa pasta não existe na máquina, mas os sites do Azure a falsificam por conveniência.No entanto, aqui parece estar causando o problema com CreateHardLink função.

se você apenas alterar esta linha no seu exemplo acima

const string tempPath = "TestTemp";

para isso

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

substituir <sitename> com o nome do seu site

vai funcionar.

Não estou muito familiarizado com o RavenDb, mas como solução alternativa, você pode tentar alterar esses diretórios para caminhos completos semelhantes ao mostrado acima.Enquanto isso, reportarei o bug.Deixe-me saber se isso funciona para você

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top