You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2016/12/03 11:06:01 UTC
[5/8] zest-java git commit: file-entitystore: simplify and fix
possible race condition
file-entitystore: simplify and fix possible race condition
Simplify using nio, remove quite a bunch of code.
Write temp files in a temporary directory to prevent a possible race
with entityStates() and backup() that list the slices directories.
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/5fee8a2b
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/5fee8a2b
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/5fee8a2b
Branch: refs/heads/develop
Commit: 5fee8a2b8ea06fa75b9d1b798ce9638eae10a1cc
Parents: d8a76c0
Author: Paul Merlin <pa...@apache.org>
Authored: Fri Dec 2 18:29:18 2016 +0100
Committer: Paul Merlin <pa...@apache.org>
Committed: Fri Dec 2 18:33:12 2016 +0100
----------------------------------------------------------------------
.../entitystore/file/FileEntityStoreMixin.java | 204 +++++--------------
1 file changed, 55 insertions(+), 149 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-java/blob/5fee8a2b/extensions/entitystore-file/src/main/java/org/apache/zest/entitystore/file/FileEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-file/src/main/java/org/apache/zest/entitystore/file/FileEntityStoreMixin.java b/extensions/entitystore-file/src/main/java/org/apache/zest/entitystore/file/FileEntityStoreMixin.java
index 14eccad..1ab1c53 100644
--- a/extensions/entitystore-file/src/main/java/org/apache/zest/entitystore/file/FileEntityStoreMixin.java
+++ b/extensions/entitystore-file/src/main/java/org/apache/zest/entitystore/file/FileEntityStoreMixin.java
@@ -19,29 +19,22 @@
*/
package org.apache.zest.entitystore.file;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import org.apache.zest.api.common.Optional;
import org.apache.zest.api.configuration.Configuration;
import org.apache.zest.api.entity.EntityDescriptor;
import org.apache.zest.api.entity.EntityReference;
import org.apache.zest.api.injection.scope.Service;
import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.io.Files;
import org.apache.zest.io.Input;
import org.apache.zest.io.Output;
import org.apache.zest.io.Receiver;
@@ -53,6 +46,8 @@ import org.apache.zest.spi.entitystore.EntityNotFoundException;
import org.apache.zest.spi.entitystore.EntityStoreException;
import org.apache.zest.spi.entitystore.helpers.MapEntityStore;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
/**
* FileEntityStore implementation of MapEntityStore.
*/
@@ -66,19 +61,22 @@ public class FileEntityStoreMixin
@This
private Configuration<FileEntityStoreConfiguration> config;
+ private String storeId;
private File dataDirectory;
+ private File tempDirectory;
private int slices;
@Override
public void initialize()
throws Exception
{
+ config.refresh();
+ storeId = config.get().identity().get().toString();
String pathName = config.get().directory().get();
if( pathName == null )
{
if( fileConfiguration != null )
{
- String storeId = config.get().identity().get().toString();
pathName = new File( fileConfiguration.dataDirectory(), storeId ).getAbsolutePath();
}
else
@@ -89,10 +87,14 @@ public class FileEntityStoreMixin
dataDirectory = new File( pathName ).getAbsoluteFile();
if( !dataDirectory.exists() )
{
- if( !dataDirectory.mkdirs() )
- {
- throw new IOException( "Unable to create directory " + dataDirectory );
- }
+ Files.createDirectories( dataDirectory.toPath() );
+ }
+ tempDirectory = fileConfiguration != null
+ ? new File( fileConfiguration.temporaryDirectory(), storeId )
+ : new File( new File( System.getProperty( "java.io.tmpdir" ) ), storeId );
+ if( !tempDirectory.exists() )
+ {
+ Files.createDirectories( tempDirectory.toPath() );
}
File slicesFile = new File( dataDirectory, "slices" );
if( slicesFile.exists() )
@@ -117,50 +119,13 @@ public class FileEntityStoreMixin
private void writeIntegerToFile( File file, int value )
throws IOException
{
- FileWriter fw = null;
- BufferedWriter bw = null;
- try
- {
- fw = new FileWriter( file );
- bw = new BufferedWriter( fw );
- bw.write( "" + value );
- bw.flush();
- }
- finally
- {
- if( bw != null )
- {
- bw.close();
- }
- if( fw != null )
- {
- fw.close();
- }
- }
+ Files.write( file.toPath(), String.valueOf( value ).getBytes( UTF_8 ) );
}
private int readIntegerInFile( File file )
throws IOException
{
- FileReader fis = null;
- BufferedReader br = null;
- try
- {
- fis = new FileReader( file );
- br = new BufferedReader( fis );
- return Integer.parseInt( br.readLine() );
- }
- finally
- {
- if( br != null )
- {
- br.close();
- }
- if( fis != null )
- {
- fis.close();
- }
- }
+ return Integer.parseInt( new String( Files.readAllBytes( file.toPath() ), UTF_8 ) );
}
@Override
@@ -176,10 +141,11 @@ public class FileEntityStoreMixin
throw new EntityNotFoundException( entityReference );
}
- byte[] serializedState = fetch( f );
- return new StringReader( new String( serializedState, "UTF-8" ) );
+ String serializedState = fetch( f );
+ return new StringReader( serializedState );
}
- catch( FileNotFoundException e ){
+ catch( FileNotFoundException e )
+ {
// Can't happen, but it does happen.
throw new EntityNotFoundException( entityReference );
}
@@ -189,19 +155,6 @@ public class FileEntityStoreMixin
}
}
- private byte[] readDataFromStream( BufferedInputStream in, byte[] buf )
- throws IOException
- {
- int size = in.read( buf );
- ByteArrayOutputStream baos = new ByteArrayOutputStream( 2000 );
- while( size > 0 )
- {
- baos.write( buf, 0, size );
- size = in.read( buf );
- }
- return baos.toByteArray();
- }
-
@Override
public void applyChanges( MapChanges changes )
throws IOException
@@ -221,13 +174,13 @@ public class FileEntityStoreMixin
throws IOException
{
super.close();
- byte[] stateArray = this.toString().getBytes( "UTF-8" );
+ String state = this.toString();
File dataFile = getDataFile( ref );
if( dataFile.exists() )
{
throw new EntityAlreadyExistsException( ref );
}
- store( dataFile, stateArray );
+ store( dataFile, state );
}
};
}
@@ -243,9 +196,9 @@ public class FileEntityStoreMixin
throws IOException
{
super.close();
- byte[] stateArray = this.toString().getBytes( "UTF-8" );
+ String state = this.toString();
File dataFile = getDataFile( ref );
- store( dataFile, stateArray );
+ store( dataFile, state );
}
};
}
@@ -296,8 +249,7 @@ public class FileEntityStoreMixin
{
for( File file : sliceDirectory.listFiles() )
{
- byte[] stateArray = fetch( file );
- receiver.receive( new String( stateArray, "UTF-8" ) );
+ receiver.receive( fetch( file ) );
}
}
}
@@ -323,8 +275,7 @@ public class FileEntityStoreMixin
{
String id = item.substring( "{\"reference\":\"".length() );
id = id.substring( 0, id.indexOf( '"' ) );
- byte[] stateArray = item.getBytes( "UTF-8" );
- store( getDataFile( id ), stateArray );
+ store( getDataFile( id ), item );
}
} );
}
@@ -350,8 +301,8 @@ public class FileEntityStoreMixin
{
for( File file : sliceDirectory.listFiles() )
{
- byte[] serializedState = fetch( file );
- receiver.receive( new StringReader( new String( serializedState, "UTF-8" ) ) );
+ String state = fetch( file );
+ receiver.receive( new StringReader( state ) );
}
}
}
@@ -402,7 +353,6 @@ public class FileEntityStoreMixin
b.append( '~' );
b.append( toHex( value ) );
}
-
}
return b.toString();
}
@@ -418,89 +368,45 @@ public class FileEntityStoreMixin
return getDataFile( ref.identity().toString() );
}
- private byte[] fetch( File dataFile )
- throws IOException
+ private String uncheckedFetch( File dataFile )
{
- byte[] buf = new byte[1000];
- BufferedInputStream in = null;
- FileInputStream fis = null;
try
{
- fis = new FileInputStream( dataFile );
- in = new BufferedInputStream( fis );
- return readDataFromStream( in, buf );
+ return fetch( dataFile );
}
- finally
+ catch( IOException e )
{
- if( in != null )
- {
- try
- {
- in.close();
- }
- catch( IOException e )
- {
- // Ignore ??
- }
- }
- if( fis != null )
- {
- try
- {
- fis.close();
- }
- catch( IOException e )
- {
- // ignore??
- }
- }
+ throw new EntityStoreException( e );
}
}
- private void store( File dataFile, byte[] stateArray )
- throws IOException
+ private void uncheckedStore( File dataFile, String state )
{
- FileOutputStream fos = null;
- BufferedOutputStream bos = null;
-
- // Write to tempfile first
- File tempFile = Files.createTemporayFileOf( dataFile );
- tempFile.deleteOnExit();
-
try
{
- fos = new FileOutputStream( tempFile, false );
- bos = new BufferedOutputStream( fos );
- bos.write( stateArray );
+ store( dataFile, state );
}
- finally
+ catch( IOException e )
{
- if( bos != null )
- {
- try
- {
- bos.close();
- }
- catch( IOException e )
- {
- // ignore??
- }
- }
- if( fos != null )
- {
- try
- {
- fos.close();
- }
- catch( IOException e )
- {
- // ignore??
- }
- }
+ throw new EntityStoreException( e );
}
+ }
+
+ private String fetch( File dataFile )
+ throws IOException
+ {
+ return new String( Files.readAllBytes( dataFile.toPath() ), UTF_8 );
+ }
+
+ private void store( File dataFile, String state )
+ throws IOException
+ {
+ // Write to temporary file first
+ Path tempFile = Files.createTempFile( tempDirectory.toPath(), storeId, "write" );
+ tempFile.toFile().deleteOnExit();
+ Files.write( tempFile, state.getBytes( UTF_8 ) );
// Replace old file
- dataFile.delete();
- tempFile.renameTo( dataFile );
+ Files.move( tempFile, dataFile.toPath(), StandardCopyOption.REPLACE_EXISTING );
}
}
\ No newline at end of file