2016-05-10 3 views
1

私の春バッチ統合アプリケーションでは、ファイルポーリングは各ファイルのbatchjobを呼び出し、このアプリケーションは複数のサーバー(ノード)で実行されている可能性がありますが、それらはすべて共通のディレクトリを読み込むことになっています。他のインスタンスが同じファイルを処理できないようにファイルをロックします。コードとして以下のSpringバッチ統合でファイルロックを使用するには?

public class MyFileLocker extends AbstractFileLockerFilter{ 

private final ConcurrentMap<File, FileLock> lockCache = new ConcurrentHashMap<File, FileLock>(); 
private final ConcurrentMap<File, FileChannel> ChannelCache = new ConcurrentHashMap<File, FileChannel>(); 

@Override 
public boolean lock(File fileToLock) { 
    FileChannel channel; 
    FileLock lock; 
    try { 
     channel = new RandomAccessFile(fileToLock, "rw").getChannel(); 
     lock = channel.tryLock(); 

     if (lock == null || !lock.isValid()) { 
      System.out.println(" Problem in acquiring lock!!" + fileToLock); 
      return false; 
     } 
     lockCache.put(fileToLock, lock); 
     ChannelCache.put(fileToLock, channel); 

    } catch (FileNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return true; 
} 

@Override 
public boolean isLockable(File file) { 

    return file.canWrite(); 
} 

@Override 
public void unlock(File fileToUnlock) { 
    FileLock lock = lockCache.get(fileToUnlock); 
    try { 
    if(lock!=null){ 
     lock.release(); 
     ChannelCache.get(fileToUnlock).close(); 
    } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

}今

、私は私の春のバッチを起動し、私はそれが私に

org.springframework.batch.item.fileを与えるflatfileitemreader使用してそのファイルを読み込むしようとすると、 .NonTransientFlatFileException

私はbeacuseファイルがロックされていると信じています。私はいくつかのグーグルをして、NIOLockerが現在のスレッドでも読むことができないようにファイルをロックすることを発見しました。私はlinkを見つけました。ロックされたファイルの読み方を示していますが、バッファを使用しています。 私のファイルをFlatfileItemReaderがアクセスできるようにするにはどうすればいいですか?

お勧めします。

答えて

1

はい、あなたは本当にのみByteBufferオーバーロックされたファイルのコンテンツへのアクセスを得ることができます

FileChannel fileChannel = channelCache.get(lockedFile); 
ByteBuffer byteBuffer = ByteBuffer.allocate((int) fileChannel.size()); 
fileChannel.read(byteBuffer); 
System.out.println("Read File " + lockedFile.getName() + " with content: " + new String(byteBuffer.array())); 

ああ!うん。あなたは本当に私のレポを指摘しました:-)。

new BufferedReader(new CharArrayReader(byteBuffer.asCharBuffer().array())); 
:コピー/ FlatfileItemReader前にファイル byte[]そのように貼り付けたり、単に適切な BufferedReaderにロックされたファイルを変換し、同じ FlatfileItemReader、にいくつかのカスタム BufferedReaderFactoryを注入しない限り、

ので、lockerであなたは選択肢を持っていません

+0

のロックを解除し、削除するために私のロッカークラスのメソッドを作成して、私が読んでいるファイルのサイズがGB単位件まで行くことができますし、そのようなファイルの数千人が存在することができます。このような大きなバッファを作成することをお勧めしますか? –

+0

えええええええええええええええええええええええええええええええええええええええええええええええええええええええええ投稿者:私はまた、ロックされたファイルを読み取るための方法を見つけることができました。おそらく人々はロックを何らかの方法で行い、この 'FileChannel'アプローチを有用なものとして見つけられないかもしれません。ロックされたファイルから一時ファイルにデータを転送することを検討できます。また、 'FlatfileItemReader'の行ごとに最後の行を読み込みます。 'FileChannel.transferTo()'はその目的のためのものです。 –

1

あなたが共有したlinkに基づいて、次のようなことができるようです。

//This is from your link (except the size variable) 
FileChannel fileChannel = channelCache.get(lockedFile); 
int size = (int) fileChannel.size(); 
ByteBuffer byteBuffer = ByteBuffer.allocate(size); 
fileChannel.read(byteBuffer); 

//Additional code that you could try 
byte[] bArray = new byte[size]; 

//Write data to the byte array 
byteBuffer.get(bArray); 

FlatFileItemReader flatFileItemReader = new FlatFileItemReader(); 
flatFileItemReader.setResource(new ByteArrayResource(bArray)); 

//Next you can try reading from your flatFileItemReader as usual 
... 

問題が解決しない場合は教えてください。

+0

あなたのprodの実装には複数のGBまでのファイルが含まれている可能性があるので、ロックされたファイルを別のスレッドで読み取ってバッファに書き出しておいてください。最後に 'FlatFileItemReader'によって読み込まれます。 InputStreamResource' –

+0

これについての回答を掲載しました。私は世話をしなければならない問題を見ますか? –

+0

@VarunMaurya、私はそこにコメントすることができないので、ここにコメントを書いてください。あなたのソリューションは大丈夫ですが、巨大なデータの問題を解決しますか?すべてのデータをメモリに読み込むのではなく、出力に書き込むためにデータをストリーミングする場合は問題ありません。それ以外の場合は、BufferedInputStreamのような他のストリーミングメカニズムを採用する必要があります。あなたはそれをテストする機会を得ましたか? –

0

解決方法:ロックされたファイルの内容を含む一時ファイルを作成して処理しています。処理が完了すると、そのファイルをアーカイブし、ロックされた両方の一時ファイルを削除します。ここで重要なのは、ロックされたファイルの内容で新しいファイルを作成することです。次のように以下のコードは次のとおりです。ここで


File tmpFile = new File(inputFile.getAbsolutePath() + ".lck");  
FileChannel fileChannel = MyFileLocker.getChannelCache().get(new File(inputFile.getAbsolutePath())); 
InputStream inputStream = Channels.newInputStream(fileChannel); 
ByteStreams.copy(inputStream, Files.newOutputStreamSupplier(tmpFile)); 

 

で、inputFile私のロックされたファイルとtmpファイルがロックされたファイルの内容を新しいファイルです。私も実際にprodシナリオで

public void unlockAndDelete(File fileToUnlockandDelete) { 
    FileLock lock = lockCache.get(fileToUnlockandDelete); 
    String fileName = fileToUnlockandDelete.getName(); 
    try { 
    if(lock!=null){ 
     lock.release(); 
     channelCache.get(fileToUnlockandDelete).close(); 
     //remove from cache 
     lockCache.remove(fileToUnlockandDelete); 
     channelCache.remove(fileToUnlockandDelete); 
     boolean isFiledeleted = fileToUnlockandDelete.delete(); 
     if(isFiledeleted){ 
      System.out.println("File deleted successfully" + fileName); 
     }else{ 
      System.out.println("File is not deleted."+fileName); 
     } 
    } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
+0

@Artem Bilanここでは、私は心配する必要がある問題を参照してください。 –

+0

M-m-m。すべてがよさそうだ。ロックされたファイルのチャンネルでバイトをコピーするようにアドバイスしていない限り。だから、私の答えはまだ受け入れられます:-)。 OTOHちょうど 'Channels.newInputStream(fileChannel);'に頼ってみたことはありませんか?ソースコードを見ると、それは良い方法だと言えるでしょう。それは同じ 'ByteBuffer'を使いますが、' InputStream .read() 'の間に小さなものを使います。だから、あなたはまだ 'FlatfileItemReader'でうまくいますが、ロックされたファイルの周りにあなたのロジックを行うためにカスタム' BufferedReaderFactory'が必要です! –

+0

なぜ私は 'BufferedReaderFactory'が必要でしょうか?私のFlatfileItemReaderでは、リソースとして 'tmpFile'を提供します。ここに何かがないのですか? –

関連する問題