2013-05-30 21 views
5

Sto provando a scrivere un'applicazione Java in esecuzione su un ambiente Linux su un filesystem NFS.Il modo migliore per distinguere tra ESTALE e ENOENT in Java

Ho notato che quando chiamo java.io.File.exists(), restituisce false sia per ESTALE (maniglia Stale NFS file) e ENOENT (Nessun file o directory). Per la mia applicazione, ho bisogno di essere in grado di distinguere tra i due.

Attualmente sto considerando l'implementazione della chiamata stat() utilizzando JNA, ma sembra essere eccessivo, con la necessità di implementare l'intera struttura stat e tutte le cose __xstat64 che sembrano così dipendenti dalla piattaforma.

C'è un modo semplice per ottenere semplicemente il errno sottostante dopo una chiamata Java come File.exists() o altre idee per risolvere questo problema?

risposta

2

Con JNA, non è necessario implementare la struttura stat; è sufficiente allocare memoria sufficientemente grande per rappresentare la struttura nativa.

È quindi possibile chiamare Native.getLastError() per recuperare il valore errno.

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

Mi piace questo suggerimento. Ho anche considerato l'implementazione di 'access (file, F_OK)', che era molto più semplice, ma anche i risultati non differenziano 'ESTALE' e' ENOENT'. Alla fine, tuttavia, abbiamo trovato una soluzione che non richiedeva questa differenziazione. –

1

Se i requisiti di prestazione sono bassi, implementerei semplicemente un piccolo programma C che chiama stat per un determinato nome di file e stampa il valore di errno sullo stdout. Quindi chiamalo da 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"); 
    } 
} 

Dalla riga di comando, questo richiede 4 ms. Nel tuo caso, forse hai solo bisogno di chiamarlo, se un precedente exists() ha restituito false.

Altre possibilità: Considerare il wrapping in un piccolo server TCP e lasciare che Java comunichi con esso tramite socket. O usalo come script CGI in apache e lascia che Java usi HTTP.

Se questo è ancora troppo lento, probabilmente devi andare in modo JNI/JNA.