2013-05-30 22 views
5

Próbuję napisać aplikację Java działającą w środowisku Linux na systemie plików NFS.Najlepszy sposób na rozróżnienie ESTALE i ENOENT w Javie

Zauważyłem, że po wywołaniu java.io.File.exists(), zwraca false zarówno dla ESTALE (Stale uchwyt pliku NFS) i ENOENT (Brak takiego pliku lub katalogu). Do mojej aplikacji potrzebuję możliwości rozróżnienia tych dwóch elementów.

Obecnie rozważam wdrożenie połączenia stat() przy użyciu JNA, ale to wydaje się być przesadą, co z koniecznością zaimplementowania całej struktury statystyk i wszystkich rzeczy, które wydają się być zależne od platformy.

Czy istnieje prosty sposób na proste uzyskanie podstawowej errno po wywołaniu Java, takim jak File.exists() lub innym pomysłu na rozwiązanie tego problemu?

Odpowiedz

2

W przypadku JNA faktycznie nie trzeba implementować struktury stat; wystarczy przydzielić pamięć dostatecznie dużą, aby reprezentować natywną strukturę.

Następnie można wywołać Native.getLastError(), aby pobrać wartość errno.

Pointer fake_stat = new Memory(2048); // big enough 
if (clib.stat(filename, fake_stat) != 0) { 
    int errno = Native.getLastError(); 
    ... 
} 
+0

Podoba mi się ta sugestia. Zastanawiałem się też nad implementacją 'access (file, F_OK)', co było dużo prostsze, ale okazuje się również nie różnicuje 'ESTALE' i' ENOENT'. W końcu jednak znaleźliśmy rozwiązanie, które nie wymagało tego zróżnicowania. –

1

Jeśli twoje wymagania wydajnościowe są niskie, po prostu zaimplementuję mały program w języku C, który wywoła stat dla podanej nazwy pliku i wypisze wartość errno na standardowe wyjście. Następnie wywołaj go z Java:

#include <stdio.h> 
#include <sys/stat.h> 
#include <errno.h> 

int main(int argc, char * argv[]) { 
    struct stat buf; 
    char const * const fileName = argv[1]; 
    int const ret = stat(fileName, &buf); 
    printf("File %s: Return %d, errno %d\n", fileName, ret, errno); 
    if (errno) { 
    perror("Error"); 
    } 
} 

Z linii poleceń wymaga to 4 ms. W twoim przypadku prawdopodobnie musisz go wywołać, jeśli poprzedni exists() zwrócił false.

Inne możliwości: Rozważ umieszczenie go na małym serwerze TCP i pozwól, aby Java komunikuje się z nim przy użyciu gniazd. Lub użyj go jako skrypt CGI w Apache i pozwól, aby Java korzystała z HTTP.

Jeśli jest to zbyt wolno, prawdopodobnie musisz przejść przez JNI/JNA.