summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java
diff options
context:
space:
mode:
authorNils Schwabe2014-07-10 16:08:36 +0200
committerNils Schwabe2014-07-10 16:08:36 +0200
commitc89abbfa830876b7298eb96896a642bc74589651 (patch)
treeee3b0707be612d9147d23632713c61c52c6d27be /src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java
parentRemove unintentionally added f3 docs (diff)
downloadmasterserver-c89abbfa830876b7298eb96896a642bc74589651.tar.gz
masterserver-c89abbfa830876b7298eb96896a642bc74589651.tar.xz
masterserver-c89abbfa830876b7298eb96896a642bc74589651.zip
Add some better thread synchonization
Restructure some classes Fix small connection issues
Diffstat (limited to 'src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java')
-rw-r--r--src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java150
1 files changed, 77 insertions, 73 deletions
diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java
index ec043fa..8306280 100644
--- a/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java
+++ b/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java
@@ -2,10 +2,13 @@ package org.openslx.imagemaster.serverconnection;
import java.io.IOException;
import java.sql.Timestamp;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.openslx.imagemaster.Globals;
@@ -34,8 +37,8 @@ public class ImageProcessor
* Key: imageUUID,
* Value: uploadingImageInfos
*/
- private static HashMap<String, UploadingImageInfos> uploadingImages = new HashMap<>();
-
+ private static Map<String, UploadingImage> uploadingImages = new ConcurrentHashMap<>();
+
/**
* The UUIDs of the images that need to be checked by the crc checker.
*/
@@ -46,7 +49,7 @@ public class ImageProcessor
* Key: serverSessionId
* Value: downloadingClientInfos
*/
- private static HashMap<String, DownloadingClientInfos> downloadingClients = new HashMap<>();
+ private static HashMap<String, DownloadingClient> downloadingClients = new HashMap<>();
/**
* Checks if this image is already uploading and returns a new list with missing blocks if so.
@@ -56,63 +59,67 @@ public class ImageProcessor
* @param imageData The data of the image
* @return
*/
- public static UploadInfos getUploadInfos( String serverSessionId, ImageData imageData, List<Integer> crcSums)
+ public static UploadInfos getUploadInfos( String serverSessionId, ImageData imageData, List<Integer> crcSums )
{
// check image data
// TODO: do security checks
- String uuid = imageData.uuid;
+ log.debug( "Trying to answer request:" + serverSessionId + ", " + imageData + ", " + crcSums );
- // check if image is already uploading TODO: what if two clients call this at the same time? -> Good question.. (Thought about not sending the last requested. But then the upload will never finish...)
- if ( uploadingImages.containsKey( uuid ) ) {
- List<Integer> missing = getMissingBlocks( uuid, AMOUNT );
- if ( missing.isEmpty() ) {
- uploadDone( uuid );
- return new UploadInfos( null, 0, missing );
- }
- uploadingImages.get( uuid ).addNotCheckedBlocks( missing );
- UploadingImageInfos image = uploadingImages.get( uuid );
- return new UploadInfos( image.getToken(), image.getPort(), missing );
- }
+ String uuid = imageData.uuid;
+ String token;
+ String filepath;
+ String crcPath;
+
+ List<Integer> allBlocks;
+ UploadingImage image;
- // insert new image and start listener
synchronized ( uploadingImages ) {
- String crcPath = Globals.getImageDir() + "/" + uuid + ".crc";
- try {
- CRCFile crcFile = new CRCFile( crcSums, crcPath);
- } catch (IOException e) {
- return null; // TODO: what to do if we can not write the crc file to disk?
+ // check if image is already uploading TODO: what if two clients call this at the same time? -> Good question.. (Thought about not sending the last requested. But then the upload will never finish...)
+ if ( ( image = uploadingImages.get( uuid ) ) != null ) {
+ log.debug( "Image is already uploading" );
+ List<Integer> missing = getNMissingBlocks( image, AMOUNT );
+ if ( missing.isEmpty() ) {
+ uploadDone( uuid );
+ return new UploadInfos( null, 0, missing );
+ }
+ return new UploadInfos( image.getToken(), Globals.getSslSocketPort(), missing );
}
+
+ // insert new image
+ log.debug( "Inserting new download" );
+ filepath = Globals.getImageDir() + "/" + uuid + ".vmdk";
+ token = RandomString.generate( 100, false );
+ crcPath = Globals.getImageDir() + "/" + uuid + ".crc";
int nBlocks = (int)Math.ceil( imageData.fileSize / Globals.blockSize );
- List<Integer> allBlocks = new LinkedList<>();
- for ( int i = 0; i < nBlocks; i++ ) { // fill empty list with all block numbers
+ allBlocks = new ArrayList<>( nBlocks );
+ for ( int i = nBlocks - 1; i >= 0; i-- ) { // fill empty list with all block numbers
allBlocks.add( i );
}
- String token = RandomString.generate( 100, false );
- String filepath = Globals.getImageDir() + "/" + uuid + ".vmdk";
- int port = ConnectionHandler.addConnection( token, filepath, ConnectionData.UPLOADING );
- // TODO: proper synchronization, interface is multi threaded.
- // should synchronize operations on the map (use concurrent map) and then synchronize on the uploading image
- // when handing the missing blocks etc...
- uploadingImages.put( uuid, new UploadingImageInfos( token, port, allBlocks, serverSessionId, new Timestamp( System.currentTimeMillis() ), uuid, filepath, crcPath ) );
- DbImage.insert( imageData, System.currentTimeMillis(), token, allBlocks, serverSessionId, filepath );
- imagesToCheck.add( uuid );
-
- List<Integer> missing = getMissingBlocks( uuid, AMOUNT );
- if ( missing.isEmpty() ) {
- // TODO: if this is empty, check if there are pending blocks and if so, request them again
- uploadDone( uuid );
- }
- uploadingImages.get( uuid ).addNotCheckedBlocks( missing );
- return new UploadInfos( token, port, missing );
+ image = new UploadingImage( token, allBlocks, new Timestamp( System.currentTimeMillis() ), uuid, filepath, crcPath );
+ uploadingImages.put( uuid, image );
}
+
+ try {
+ new CRCFile( crcSums, crcPath);
+ } catch (IOException e) {
+ log.debug( "Could not create crc file" );
+ return null; // TODO: what to do if we can not write the crc file to disk? Give object to crcscheduler?
+ }
+
+ ConnectionHandler.addConnection( token, filepath, Connection.UPLOADING ).image = image;
+ DbImage.insert( imageData, System.currentTimeMillis(), token, allBlocks, serverSessionId, filepath );
+ imagesToCheck.add( uuid );
+
+ log.debug( "Returning UploadInfos" );
+ return new UploadInfos( token, Globals.getSslSocketPort(), getNMissingBlocks( image, AMOUNT ) );
}
public static DownloadInfos getDownloadInfos( String serverSessionId, String uuid, List<Integer> requestedBlocks )
{
// check if server is already downloading
if ( downloadingClients.containsKey( serverSessionId ) ) {
- DownloadingClientInfos client = downloadingClients.get( serverSessionId );
+ DownloadingClient client = downloadingClients.get( serverSessionId );
// remove download if done
if ( requestedBlocks.isEmpty() )
@@ -126,36 +133,36 @@ public class ImageProcessor
// client was downloading this image
// update the requested blocks
client.requestBlocks( uuid, requestedBlocks );
- return new DownloadInfos( client.getToken( uuid ), client.getPort( uuid ) );
+ return new DownloadInfos( client.getToken( uuid ), Globals.getSslSocketPort() );
}
// server was downloading another image and now gets a new connection for this new download
String token = RandomString.generate( 100, false );
String filepath = DbImage.getImageByUUID( uuid ).imagePath;
- int port = ConnectionHandler.addConnection( token, filepath, ConnectionData.DOWNLOADING );
+ ConnectionHandler.addConnection( token, filepath, Connection.DOWNLOADING );
- client.addDownload( uuid, port, requestedBlocks, token );
+ client.addDownload( uuid, requestedBlocks, token );
downloadingClients.put( serverSessionId, client );
- return new DownloadInfos( token, port );
+ return new DownloadInfos( token, Globals.getSslSocketPort() );
}
// insert new client and start listener
synchronized ( downloadingClients ) {
- DownloadingClientInfos client = new DownloadingClientInfos();
+ DownloadingClient client = new DownloadingClient();
String token = RandomString.generate( 100, false );
String filepath = DbImage.getImageByUUID( uuid ).imagePath;
- int port = ConnectionHandler.addConnection( token, filepath, ConnectionData.DOWNLOADING );
+ ConnectionHandler.addConnection( token, filepath, Connection.DOWNLOADING );
- client.addDownload( uuid, port, requestedBlocks, token );
+ client.addDownload( uuid, requestedBlocks, token );
downloadingClients.put( serverSessionId, client );
- return new DownloadInfos( token, port );
+ return new DownloadInfos( token, Globals.getSslSocketPort() );
}
}
private static void downloadDone( String serverSessionId, String uuid )
{
synchronized ( downloadingClients ) {
- DownloadingClientInfos client = downloadingClients.get( serverSessionId );
+ DownloadingClient client = downloadingClients.get( serverSessionId );
client.removeDownload( uuid );
ConnectionHandler.removeConnection( client.getToken( uuid ) );
if ( !client.hasDownloads() ) {
@@ -171,23 +178,18 @@ public class ImageProcessor
* @param amount The amount of blocks that you want to get
* @return The missing blocks
*/
- private static List<Integer> getMissingBlocks( String imageUUID, int amount )
+ private static List<Integer> getNMissingBlocks( UploadingImage image, int amount )
{
- UploadingImageInfos image = uploadingImages.get( imageUUID );
- List<Integer> list = image.getMissingBlocks();
- List<Integer> result = new LinkedList<>();
+ int size = image.amountOfMissingBlocks();
+ if ( amount > size )
+ amount = size;
- if ( amount > list.size() )
- amount = list.size();
+ List<Integer> result = new ArrayList<>( amount );
- for ( int i = 0; i < amount; i++ ) {
- result.add( list.get( i ) );
+ for ( int i = 1; i <= amount; i++ ) {
+ result.add( image.removeMissingBlock( size - i ) );
}
-
- synchronized ( image ) {
- image.addNotCheckedBlocks( result );
- }
-
+
return result;
}
@@ -199,10 +201,11 @@ public class ImageProcessor
*/
private static void uploadDone( String uuid )
{
- synchronized (imagesToCheck) {
+ synchronized ( imagesToCheck ) {
imagesToCheck.remove( uuid );
}
- UploadingImageInfos image;
+
+ UploadingImage image;
synchronized ( uploadingImages ) {
image = uploadingImages.remove( uuid );
}
@@ -211,18 +214,18 @@ public class ImageProcessor
// remove the connection so that it can be used by a new client
ConnectionHandler.removeConnection( image.getToken() );
}
-
- public static List<UploadingImageInfos> getImagesToCheck()
+
+ public static List<UploadingImage> getImagesToCheck()
{
- List<UploadingImageInfos> result = new LinkedList<>();
+ List<UploadingImage> result = new LinkedList<>();
Iterator<String> iter = imagesToCheck.iterator();
while ( iter.hasNext() ) {
result.add( uploadingImages.get( iter.next() ) );
}
-
+
return result;
}
-
+
/**
* Checks pending uploads in database and adds them to process list again.
*/
@@ -231,8 +234,9 @@ public class ImageProcessor
List<DbImage> list = DbImage.getUploadingImages();
for ( DbImage image : list ) {
String token = image.token;
- int port = ConnectionHandler.addConnection( token, image.imagePath, ConnectionData.UPLOADING );
- UploadingImageInfos infos = new UploadingImageInfos( token, port, image.missingBlocks, image.serverSessionId, image.timestamp, image.uuid, image.imagePath, Globals.getImageDir() + "/" + image.uuid + ".crc" );
+ ConnectionHandler.addConnection( token, image.imagePath, Connection.UPLOADING );
+ UploadingImage infos = new UploadingImage( token, image.missingBlocks, image.timestamp,
+ image.uuid, image.imagePath, Globals.getImageDir() + "/" + image.uuid + ".crc" );
uploadingImages.put( image.uuid, infos );
}
log.info( "Added " + list.size() + " pending upload(s) to process list again." );