Date im Netzwerk manchmal angeblich nicht vorhanden



  • Hallo!

    Ich habe ein C#-Programm, das mittels MSSQL Lib auf einen Datenbankserver zugreift und dann den Befehl zum Erstellen eines Backups an den Server sendet. Der Server erstellt dann das Backup und mein Programm greift über eine Netzwerkfreigabe auf die Datei zu, um die Datei wo anders hin zu kopieren. Manchmal fliegt an dieser Stelle eine FileNotFoundException, die besagt, dass die Datei, die gerade ja durch das Backup erstellt wurde und auf jeden Fall existiert, nicht existiert. Wie gesagt tritt das nur manchmal auf. Die Chance, dass es klappt, liegt gefühlt bei 50/50. Jetzt denke ich mir, dass Windows den Netzwerkpfad noch nicht aktualisiert hat und deswegen die Datei nicht kennt. Wie kann ich denn vor dem Zugriff auf die Netzwerkfreigabe eine Aktualisierung durchführen, sodass auch die gerade erstellte Datei gefunden wird? Oder bin ich auf einem falschen Dampfer?



  • Sorry, der Fehler lag in meinem Programm. Ich habe eine Variable falsch befüllt, die die Uhrzeit in Sekunden beinhaltet hat. Es hat also nichts mit der Freigabe zu tun!



  • Es lag doch nicht an meinem Programm. Mein Problem taucht deswegen auf, weil Microsoft in neueren Windows-Versionen beim SMB Client Redirector (die Komponente, die laut diesem Artikel für die Zugriffe auf Netzwerkpfade über das SMB-Protokoll zuständig ist, also auch bei UNC-Pfaden) einen Cache eingebaut hat. Informationen über existierende und nicht existierende Dateien werden 5 Sekunden lang gespeichert.

    Mein Programm macht nun Folgendes:

    • Prüfen, ob die Datei \\server\datei schon existiert
    • Falls ja: Datei löschen
    • Dem Server den Befehl senden, die Datei wieder zu erstellen (SQL-Datenbank-Backup). Hiervon bekommt natürlich der Cache nichts mit, weil das auf dem Server passiert
    • Datei \\server\datei nach \\server2\datei kopieren. Hier knallt es, weil laut Cache die Datei nicht vorhanden ist

    Wenn ich die erste Prüfung weg lassen, klappt es. Es liegt also am Cache. Nun gibt es laut oben genanntem Artikel die Möglichkeit, die Cache-Zeit mittels Registry-Schlüssel anzupassen und auch auf 0 zu setzen. Mache ich das, kommt kein Fehler mehr. Allerdings ist das keine Option, da mehrere Personen die Applikation verwenden und es nicht tragbar ist, nur dafür die Cache-Zeit anzupassen, die ja dann auch alle anderen Applikationen betrifft und das Netzwerk evtl. verlangsamt.

    Die Prüfung wegzulassen wäre auch ein Workaround, aber ich möchte zumindest wissen, ob die Detei vorhanden ist, da ich sie entweder löschen oder dem Benutzer eine Meldung ausgeben will, dass sie bereits vorhanden ist. Eine Anmerkung noch: meine Prüfung auf die Existenz der Datei mache ich mittels File.Exists("\\\server\\datei").
    Ich dachte mir dann, dass es so funktionieren könnte, da ich selber keine Existenz-Prüfung mache:

    try
    {
        File.Delete("\\\\server\datei");
    }
    catch (FileNotFoundException)
    {
        // OK, keine Aktion noetig
    }
    

    Aber das hat die gleiche Auswirkung, was ja auch Sinn macht.

    Dann hatte ich noch die Idee, die Datei nach dem Löschen wieder leer zu erstellen. Dann hat der Cache ja wieder die Information, dass sie existiert. Aber dann hat der Server aufgrund von Berechtigungen keinen Zugriff auf die Datei. Und ob es der richtige Weg ist, jetzt da noch was mit Berechtigungen reinzupopeln, weiß ich nicht. Was meint ihr? Wie löse ich das Problem am besten?



  • Ich greife in solchen Fällen einfach per FTP auf den Server zu statt via SMB - Das scheint bislang deutlich sorgenloser zu funktionieren 😉



  • Das geht in meinem Fall leider nicht, weil es auf den entsprechenden Maschinen kein FTP-Server läuft.



  • Nachdem du die Sache ziemlich weit einschränkst ("will ich nicht"/"kann ich nicht"), bleibt wohl nur noch ein Retry-Loop nach Erstellen des Backup.

    ps:

    Möglichkeit 2:
    Du lässt das Backup gleich auf \\server2\ schreiben.

    Möglichkeit 3:
    Du verwendest ein SQL Script um das Backup File zu kopieren (mit xp_cmdshell oder was auch immer).



  • hustbaer schrieb:

    Möglichkeit 2:
    Du lässt das Backup gleich auf \\server2\ schreiben.

    Gute Idee, aber Server1 sieht die Freigabe von Server2 wegen Sicherheit leider nicht.

    hustbaer schrieb:

    Möglichkeit 3:
    Du verwendest ein SQL Script um das Backup File zu kopieren (mit xp_cmdshell oder was auch immer).

    Kopieren über die Freigabe? Geht dann auch nicht, siehe oben 😞

    Dann bleibt mir wohl wirklich nur der Loop. Schade, dass Microsoft dem Programmierer nicht die Möglichkeit bietet, die Cache-Zeit in der Applikation nochmal anzupassen.



  • Ja das ist doof.
    Ich wusste gar nicht mal dass Windows das überhaupt macht. Ist ja schon ne reichlich fragwürdige Sache...

    Was du noch versuchen könntest: in dem Programm das das Backup kopiert nen CreateFile machen mit CREATE_NEW. Das sollte dann fehlschlagen mit ERROR_FILE_EXISTS. Falls Windows schlau genug ist auf einen unerwarteten ERROR_FILE_EXISTS hin den Cache zu invalidieren, dann müsste das Kopieren danach funktionieren.
    Würde mir aber keine all zu grossen Hoffnungen machen.

    ps: Eine weitere Möglichkeit was du probieren könntest wäre nen FileSystemWatcher auf das Verzeichnis zu erzeugen (und natürlich mit EnableRaisingEvents = true zu aktivieren) bevor du das Backup erstellen lässt. Vielleicht bekommt Windows dadurch schneller mit dass das File erstellt wurde.


Log in to reply