2009-01-06 8 views
11

Ceci est peut-être similaire aux messages précédents, mais je veux être précis sur l'utilisation du verrouillage sur un réseau, plutôt que localement. Je veux écrire un fichier à un emplacement partagé, donc il peut très bien aller sur un réseau (certainement un réseau Windows, peut-être Mac). Je veux empêcher d'autres personnes de lire n'importe quelle partie de ce fichier pendant son écriture. Ce ne sera pas un processus hautement concurrent, et les fichiers seront généralement moins de 10 Mo.Verrouillage de fichier Java sur un réseau

J'ai lu la documentation FileLock et la documentation File et je suis un peu confus quant à ce qui est sûr et ce qui ne l'est pas. Je veux verrouiller le fichier entier, plutôt que des parties de celui-ci. Puis-je utiliser FileChannel.tryLock(), et est-ce que c'est sécurisé sur un réseau, ou cela dépend-il du type de réseau? Cela fonctionnera-t-il sur un réseau Windows standard (s'il y a une telle chose).

Si cela ne fonctionne pas, il est préférable de créer un fichier ou un répertoire de zéro octet comme fichier de verrouillage, puis d'écrire le fichier principal. Pourquoi cette documentation File.createNewFile() ne l'utilise-t-elle pas pour le verrouillage de fichier? J'apprécie que cela soit sujet aux conditions de course, et n'est pas idéal.

Répondre

5

Cela ne peut pas être effectué de manière fiable sur un système de fichiers réseau. Tant que votre application est la seule application qui accède au fichier, il est préférable d'implémenter une sorte de processus de verrouillage coopératif (en écrivant peut-être un fichier de verrouillage sur le système de fichiers réseau lorsque vous ouvrez le fichier). La raison qui n'est pas recommandée, cependant, est que si votre processus se bloque ou que le réseau tombe en panne ou que d'autres problèmes surviennent, votre application est dans un état désagréable et sale.

3

Vous pouvez avoir un fichier vide qui se trouve sur le serveur que vous voulez écrire. Lorsque vous voulez écrire sur le serveur, vous pouvez capturer le jeton. Ce n'est que lorsque vous avez le jeton que vous devez écrire dans un fichier qui se trouve sur le serveur.

Lorsque vous êtes prêt avec vos opérations de fichier ou qu'une exception a été levée, vous devez libérer le jeton.

La classe d'aide peut ressembler à

private FileLock lock; 

private File tokenFile; 

public SLTokenLock(String serverDirectory) { 
    String tokenFilePath = serverDirectory + File.separator + TOKEN_FILE; 
    tokenFile = new File(tokenFilePath); 
} 

public void catchCommitToken() throws TokenException { 
    RandomAccessFile raf; 
    try { 
     raf = new RandomAccessFile(tokenFile, "rw"); //$NON-NLS-1$ 
     FileChannel channel = raf.getChannel(); 
     lock = channel.tryLock(); 

     if (lock == null) { 
      throw new TokenException(CANT_CATCH_TOKEN); 
     } 
    } catch (Exception e) { 
     throw new TokenException(CANT_CATCH_TOKEN, e); 
    } 
} 

public void releaseCommitToken() throws TokenException { 
    try { 
     if (lock != null && lock.isValid()) { 
      lock.release(); 
     } 
    } catch (Exception e) { 
     throw new TokenException(CANT_RELEASE_TOKEN, e); 
    } 
} 

Vos opérations devrait alors ressembler à

try { 
     token.catchCommitToken(); 

     // WRITE or READ to files inside the directory 
    } finally { 
     token.releaseCommitToken(); 
    } 
1

Plutôt que de mettre en œuvre une stratégie de verrouillage qui, selon toute vraisemblance, compter sur les lecteurs à adhérer à votre mais vous ne pouvez pas les forcer à le faire, vous pouvez peut-être écrire le fichier dans un fichier caché ou obscurément nommé où il sera effectivement invisible aux lecteurs. Lorsque l'opération d'écriture est terminée, renommez le fichier en le nom public attendu. L'inconvénient est que le masquage et/ou le renommage sans E/S supplémentaires peuvent nécessiter l'utilisation de commandes OS natives, mais la procédure à suivre doit être assez simple et déterministe.

4

J'ai trouvé ce rapport de bogue qui décrit pourquoi la note sur le verrouillage de fichier a été ajoutée à la documentation File.createNewFile.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4676183

Il déclare:

Si vous marquez le fichier comme deleteOnExit avant invoquer CreateNewFile mais le fichier existe déjà, vous courez le risque de supprimer un fichier que vous n'avez pas créé et tomber quelqu'un elses lock! D'autre part, si vous marquez le fichier après en le créant, vous perdez l'atomicité: si le programme se termine avant que le fichier ne soit marqué, il ne sera pas supprimé et le verrou sera "coincé".

Il semble donc que la principale raison de verrouillage est déconseillée avec File.createNewFile() est que vous pouvez vous retrouver avec des fichiers de verrouillage orphelins si la machine virtuelle Java de façon inattendue avant met fin à avoir une chance de le supprimer. Si vous pouvez traiter des fichiers de verrous orphelins, il pourrait être utilisé comme un simple mécanisme de verrouillage. Cependant, je ne recommanderais pas la méthode suggérée dans les commentaires du rapport de bogue car elle a des conditions de course autour de la lecture/écriture de la valeur d'horodatage et de la récupération du verrou expiré.

Questions connexes