package org.openslx.imagemaster.serverconnection; import java.sql.Timestamp; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.db.DbImage; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.UploadInfos; import org.openslx.imagemaster.util.RandomString; public class ImageProcessor { private static final Logger log = Logger.getLogger( ImageProcessor.class ); /** * The amount of blocks that is return in UploadInfos (after request of satellite) */ private static final int AMOUNT = 20; /** * The uploading images. * Key: imageUUID, * Value: imageInfos */ private static HashMap uploadingImages = new HashMap<>(); /** * Checks if this image is already uploading and returns a new list with missing blocks if so. * Puts the new image into processing list else. * @param serverSessionId The uploading server * @param imageData The data of the image * @return */ public static UploadInfos getUploadInfos( String serverSessionId, ImageData imageData ) { // check image data // TODO: do security checks String uuid = imageData.uuid; // check if image is already uploading TODO: what if two clients call this at the same time? if ( uploadingImages.containsKey( uuid ) ) { List missing = getMissingBlocks( uuid, AMOUNT ); if ( missing.isEmpty() ) { String token = uploadingImages.get( uuid ).getToken(); uploadDone( uuid ); return new UploadInfos( token, missing ); } // 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.get( uuid ).setLastSentBlocks( missing ); return new UploadInfos( uploadingImages.get( uuid ).getToken(), missing ); } // insert new image and generate token synchronized (uploadingImages) { int nBlocks = (int)Math.ceil(imageData.fileSize / Globals.blockSize); List allBlocks = new LinkedList<>(); for (int i = 0; i < nBlocks; i++) { // fill empty list with all block numbers allBlocks.add( i ); } String token = RandomString.generate( 100, false ); // TODO: init updownloader class uploadingImages.put( uuid, new ImageInfos(token, allBlocks, serverSessionId, new Timestamp(System.currentTimeMillis())) ); DbImage.insert( imageData, System.currentTimeMillis(), token, allBlocks, serverSessionId ); List missing = getMissingBlocks( uuid, AMOUNT ); if ( missing.isEmpty() ) { // TODO: if this is empty, check if there are pendig blocks and if so, request them again uploadDone( uuid ); } uploadingImages.get( uuid ).setLastSentBlocks( missing ); return new UploadInfos( token, missing ); } } /** * Returns a specified number of missing blocks. * @param imageUUID The image of which you want to get the missing blocks from * @param amount The amount of blocks that you want to get * @return The missing blocksht */ private static List getMissingBlocks( String imageUUID, int amount ) { List list = uploadingImages.get( imageUUID ).getMissingBlocks(); List result = new LinkedList<>(); if ( amount > list.size() ) amount = list.size(); for ( int i = 0; i < amount; i++ ) { result.add( list.get( i ) ); } return result; } /** * Is triggered when an upload of an image is done. * Removes image from process list, updates db entry and moves file on hard drive. * @param uuid */ private static void uploadDone( String uuid ) { synchronized(uploadingImages) { uploadingImages.remove( uuid ); DbImage.updateMissingBlocks( uuid, null ); } // file was already downloaded in the right location by the updownloader class. } /** * Checks pending uploads in database and adds them to process list again. */ static { List list = DbImage.getUploadingImages(); for (DbImage image : list) { // TODO: init updownloader class String token = RandomString.generate( 100, false ); ImageInfos infos = new ImageInfos(token, image.missingBlocks, image.serverSessionId, image.timestamp); uploadingImages.put( image.UUID, infos); } log.info("Added " + list.size() + " pending upload(s) to process list again."); } }