Domanda

Ho un set di file. L'insieme di file è di sola lettura da una condivisione NTFS, quindi può avere molti lettori. Ogni file viene aggiornato occasionalmente da un autore che ha accesso in scrittura.

Come posso assicurarmi che:

  1. Se la scrittura non riesce, il file precedente è ancora leggibile
  2. I lettori non possono sostenere il singolo autore

Sto usando Java e la mia soluzione attuale è che lo scrittore scriva su un file temporaneo, quindi lo cambi con il file esistente usando File.renameTo () . Il problema è su NTFS, renameTo non riesce se il file di destinazione esiste già, quindi è necessario eliminarlo da soli. Ma se lo scrittore cancella il file di destinazione e poi fallisce (crash del computer), non ho un file leggibile.

FileLock di nio funziona solo con la stessa JVM, quindi è inutile per me.

Come posso aggiornare in sicurezza un file con molti lettori usando Java?

È stato utile?

Soluzione

Secondo JavaDoc :

  

Questa API per il blocco dei file è pensata per   mappare direttamente al blocco nativo   facilità di funzionamento sottostante   sistema. Pertanto, i blocchi mantenuti su un file   dovrebbe essere visibile a tutti i programmi che   avere accesso al file, indipendentemente da   la lingua in cui tali programmi   sono scritti.

Altri suggerimenti

Non so se questo è applicabile, ma se si esegue una soluzione Vista / Windows Server 2008 pura, utilizzare TxF (NTFS transazionale) e quindi assicurarsi di aprire l'handle del file ed eseguire le operazioni sui file chiamando le API dei file appropriate tramite JNI.

Se questa non è un'opzione, penso che dovresti avere una sorta di servizio a cui accedono tutti i clienti che è responsabile del coordinamento della lettura / scrittura del file.

Su un sistema Unix, rimuoverei il file e lo apro per la scrittura. Chiunque lo aprisse per la lettura vedrebbe ancora quello vecchio e una volta chiuso lo svanirebbe dal file system. Non so se NTFS abbia una semantica simile, anche se ho sentito che è basato sul file system di BSD, quindi forse lo fa.

Qualcosa che dovrebbe sempre funzionare, indipendentemente dal sistema operativo ecc., sta cambiando il software client.

Se questa è un'opzione, allora potresti avere un file " settings1.ini " e se vuoi cambiarlo, crei un file " settings2.ini.wait " ;, quindi scrivi i tuoi contenuti e rinominalo in " settings2.ini " quindi elimina " settings1.ini " ;.

Il software client modificato verificherebbe semplicemente sempre settings2.ini se ha letto settings1.ini per ultimo e viceversa.

In questo modo hai sempre una copia funzionante.

Potrebbe non essere necessario il blocco. Non ho familiarità con l'API di FS su Windows, ma poiché NTFS supporta sia i collegamenti fisici che i collegamenti software, AFAIK, puoi provare questo se la tua configurazione lo consente:

Utilizzare un collegamento hard o soft per puntare al file effettivo e denominare il file in modo diverso. Consenti a tutti di accedere al file usando il nome del link.

Scrivi il nuovo file con un nome diverso, nella stessa cartella.

Al termine, fare in modo che il file punti al nuovo file. In modo ottimale, Windows consentirebbe di creare il nuovo collegamento con la sostituzione del collegamento esistente in un'operazione atomica. Quindi avresti effettivamente il link per identificare sempre un file valido, sia quello vecchio che quello nuovo. Nel peggiore dei casi, dovresti prima eliminare quello vecchio, quindi creare il collegamento al nuovo file. In tal caso, ci sarebbe un breve lasso di tempo in cui un programma non sarebbe in grado di individuare il file. (Inoltre, Mac OS X offre una funzione "ExchangeObjects" che ti consente di scambiare due elementi atomicamente - forse Windows offre qualcosa di simile).

In questo modo, qualsiasi programma che ha già aperto il vecchio file continuerà ad accedere a quello vecchio e non riuscirai a crearne uno nuovo. Solo se un'app nota l'esistenza della nuova versione, potrebbe quindi chiudere la corrente e riaprirla, in questo modo ottenendo l'accesso alla nuova versione.

Non so, tuttavia, come creare collegamenti in Java. Forse devi usare alcune API native per questo.

Spero che questo aiuti comunque.

Di recente ho avuto a che fare con qualcosa di simile. Se stai eseguendo Java 5, forse potresti prendere in considerazione l'utilizzo dei blocchi di file NIO insieme a ReentrantReadWriteLock? Assicurarsi che tutto il codice che fa riferimento all'oggetto FileChannel faccia riferimento ANCHE a ReentrantReadWriteLock. In questo modo NIO lo blocca a livello di VM, mentre il blocco rientrante lo blocca a livello di thread.

FileLock fileLock = filechannel.lock(position, size, shared);
reentrantReadWriteLock.lock();

// do stuff

fileLock.release();
reentrantReadWriteLock.unlock();

Naturalmente, sarebbe necessaria una certa gestione delle eccezioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top