From 8b87677709624a56a7557104dc31ee8cc2ece748 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 25 Sep 2014 14:50:56 +0200 Subject: Adapt to changed Thrift RPC --- src/main/java/org/openslx/imagemaster/App.java | 2 - .../java/org/openslx/imagemaster/db/DbImage.java | 88 +++--- .../java/org/openslx/imagemaster/db/DbUser.java | 63 +++-- .../org/openslx/imagemaster/server/ApiServer.java | 14 +- .../imagemaster/serverconnection/Connection.java | 36 --- .../serverconnection/ConnectionHandler.java | 194 ++++++-------- .../imagemaster/serverconnection/CrcScheduler.java | 2 +- .../serverconnection/DownloadingClient.java | 71 ----- .../serverconnection/ImageProcessor.java | 297 ++++----------------- .../serverconnection/UploadingImage.java | 172 ++++++------ .../openslx/imagemaster/session/Authenticator.java | 6 +- .../java/org/openslx/imagemaster/session/User.java | 9 +- .../thrift/server/ImageServerHandler.java | 8 +- .../java/org/openslx/imagemaster/util/Util.java | 22 +- src/test/java/org/openslx/imagemaster/AppTest.java | 5 - 15 files changed, 356 insertions(+), 633 deletions(-) delete mode 100644 src/main/java/org/openslx/imagemaster/serverconnection/Connection.java delete mode 100644 src/main/java/org/openslx/imagemaster/serverconnection/DownloadingClient.java diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java index 34b50f8..5a325ba 100644 --- a/src/main/java/org/openslx/imagemaster/App.java +++ b/src/main/java/org/openslx/imagemaster/App.java @@ -5,7 +5,6 @@ import java.util.List; import org.apache.log4j.Logger; import org.openslx.imagemaster.serverconnection.CrcScheduler; -import org.openslx.imagemaster.serverconnection.ImageProcessor; import org.openslx.imagemaster.thrift.server.BinaryListener; import org.slf4j.LoggerFactory; @@ -32,7 +31,6 @@ public class App // Init the properties and load uploading images from database Globals.init(); - ImageProcessor.init(); // Create binary listener Thread t; diff --git a/src/main/java/org/openslx/imagemaster/db/DbImage.java b/src/main/java/org/openslx/imagemaster/db/DbImage.java index dc2ab34..a7a2adb 100644 --- a/src/main/java/org/openslx/imagemaster/db/DbImage.java +++ b/src/main/java/org/openslx/imagemaster/db/DbImage.java @@ -1,8 +1,6 @@ package org.openslx.imagemaster.db; import java.sql.Timestamp; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; import org.openslx.imagemaster.Globals; @@ -20,22 +18,22 @@ public class DbImage public final String uuid; public final int imageVersion; public final String imageName; + /** + * Relative path of image file (relative to Globals.getImageDir()) + */ public final String imagePath; public final Timestamp imageCreateTime; public final Timestamp imageUpdateTime; - public final String imageOwner; + public final int imageOwnerId; public final String contentOperatingSystem; public final boolean isValid; public final boolean isDeleted; public final String shortDescription; public final String longDescription; - public final Timestamp timestamp; public final long fileSize; - public final String token; public final int[] blockStatus; - public final String serverSessionId; - public DbImage(String uuid) + public DbImage( String uuid ) { this.uuid = uuid; this.imageVersion = 0; @@ -43,23 +41,20 @@ public class DbImage this.imagePath = null; this.imageCreateTime = null; this.imageUpdateTime = null; - this.imageOwner = null; + this.imageOwnerId = 0; this.contentOperatingSystem = null; this.isValid = false; this.isDeleted = false; this.shortDescription = null; this.longDescription = null; - this.timestamp = new Timestamp( 0 ); this.fileSize = 0; - this.token = null; this.blockStatus = null; - this.serverSessionId = null; } - public DbImage(String uuid, int imageVersion, String imageName, String imagePath, - Timestamp imageCreateTime, Timestamp imageUpdateTime, String imageOwner, String contentOperatingSystem, + public DbImage( String uuid, int imageVersion, String imageName, String imagePath, + Timestamp imageCreateTime, Timestamp imageUpdateTime, int imageOwnerId, String contentOperatingSystem, boolean isValid, boolean isDeleted, String shortDescription, String longDescription, - Timestamp timestamp, long fileSize, String token, String missingBlocksList, String serverSessionId) + long fileSize, String missingBlocksList ) { this.uuid = uuid; this.imageVersion = imageVersion; @@ -67,26 +62,24 @@ public class DbImage this.imagePath = imagePath; this.imageCreateTime = imageCreateTime; this.imageUpdateTime = imageUpdateTime; - this.imageOwner = imageOwner; + this.imageOwnerId = imageOwnerId; this.contentOperatingSystem = contentOperatingSystem; this.isValid = isValid; this.isDeleted = isDeleted; this.shortDescription = shortDescription; this.longDescription = longDescription; - this.timestamp = timestamp; this.fileSize = fileSize; - this.token = token; String[] parts = missingBlocksList.split( ";" ); blockStatus = new int[ Util.getNumberOfBlocks( fileSize, Globals.blockSize ) ]; // initialize array to ones - for ( int i : blockStatus ) { - blockStatus[i] = UploadingImage.valid; + for ( int i = 0; i < blockStatus.length; ++i ) { + blockStatus[i] = UploadingImage.VALID; } - for ( int i = 0; i < parts.length; i++ ) { - blockStatus[i] = UploadingImage.missing; + for ( String block : parts ) { // Now mark missing blocks (if any) + int i = Util.tryToParseInt( block, -1 ); + if ( i >= 0 && i < blockStatus.length ) + blockStatus[i] = UploadingImage.MISSING; } - - this.serverSessionId = serverSessionId; } /** @@ -104,38 +97,30 @@ public class DbImage * Insert a new image into database * * @param imageData The metadata of the image - * @param ts The timestamp of inserting - * @param token The token that is able to upload this image - * @param amountBlocks The blocks that are missing for this image - * @param serverSessionId The server that is uploading this image + * @param filepath Local storage path of image * @return Affected rows */ - public static int insert( ImageData imageData, long ts, String token, int amountBlocks, String serverSessionId, String filepath ) + public static int insert( ImageData imageData, String filepath ) { - Date createTime = new Date( imageData.imageCreateTime ); - Date updateTime = new Date( imageData.imageUpdateTime ); - Date timestamp = new Date( ts ); - SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); - + int numBlocks = Util.getNumberOfBlocks( imageData.fileSize, Globals.blockSize ); String missingBlocksList = ""; - for ( int i = 0; i < amountBlocks; i++ ) { + for ( int i = 0; i < numBlocks; i++ ) { missingBlocksList = missingBlocksList + String.valueOf( i ) + ";"; } + DbUser user = DbUser.forLogin( imageData.imageOwner ); + int owner = 0; + if (user != null) + owner = user.userId; return MySQL .update( - "INSERT INTO images (UUID, image_version, image_name, image_path, image_createTime, image_updateTime, image_owner, content_operatingSystem, status_isValid, status_isDeleted, image_shortDescription, image_longDescription, timestamp, fileSize, token, missingBlocks, serverSessionId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO images (UUID, image_version, image_name, image_path, image_createTime, image_updateTime, image_owner, content_operatingSystem, status_isValid, status_isDeleted, image_shortDescription, image_longDescription, fileSize, missingBlocks) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", imageData.uuid, imageData.imageVersion, imageData.imageName, filepath, - sdf.format( createTime ), sdf.format( updateTime ), imageData.imageOwner, + imageData.imageCreateTime, imageData.imageUpdateTime, owner, imageData.contentOperatingSystem, imageData.statusIsValid, imageData.statusIsDeleted, imageData.imageShortDescription, - imageData.imageLongDescription, sdf.format( timestamp ), imageData.fileSize, - token, missingBlocksList, serverSessionId ); - } - - public String getUuid() - { - return this.uuid; + imageData.imageLongDescription, imageData.fileSize, + missingBlocksList ); } /** @@ -218,8 +203,23 @@ public class DbImage */ public ImageData getImageData() { + String owner = "unknown"; + DbUser user = DbUser.forLogin( this.imageOwnerId ); + if (user != null) + owner = user.getLogin(); return new ImageData( this.uuid, this.imageVersion, this.imageName, this.imageCreateTime.getTime(), - this.imageUpdateTime.getTime(), this.imageOwner, this.contentOperatingSystem, this.isValid, + this.imageUpdateTime.getTime(), owner, this.contentOperatingSystem, this.isValid, this.isDeleted, this.shortDescription, this.longDescription, this.fileSize ); } + + /** + * Get absolute path of this image + * + * @return absolute path + */ + public String getAbsolutePath() + { + return Globals.getImageDir() + "/" + this.imagePath; + } + } diff --git a/src/main/java/org/openslx/imagemaster/db/DbUser.java b/src/main/java/org/openslx/imagemaster/db/DbUser.java index 91e0615..c486da3 100644 --- a/src/main/java/org/openslx/imagemaster/db/DbUser.java +++ b/src/main/java/org/openslx/imagemaster/db/DbUser.java @@ -2,6 +2,7 @@ package org.openslx.imagemaster.db; import org.apache.log4j.Logger; import org.openslx.imagemaster.session.User; +import org.openslx.imagemaster.util.Sha512Crypt; /** * Represents a user that can login against the masterserver. @@ -11,9 +12,9 @@ public class DbUser extends User private static Logger log = Logger.getLogger( DbUser.class ); - public DbUser(int userId, String username, String password, String organization, + public DbUser( int userId, String username, String password, String organization, String firstName, String lastName, String eMail, - String satelliteAddress) + String satelliteAddress ) { super( userId, username, password, organization, firstName, lastName, eMail, satelliteAddress ); @@ -41,6 +42,37 @@ public class DbUser extends User parts[0], parts[1] ); } + /** + * Query database for user with given userId + * + * @param userid + * @return instance of DbUser for matching entry from DB, or null if not + * found + */ + public static DbUser forLogin( final int userid ) + { + return MySQL + .findUniqueOrNull( + DbUser.class, + "SELECT user.userid, user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user" + + " LEFT JOIN satellite USING (organization)" + + " WHERE user.userid = ? LIMIT 1", + userid ); + } + + public static boolean exists( final String login ) + { + return forLogin( login ) != null; + } + + public static DbUser forLogin( String login, String password ) + { + DbUser user = forLogin( login ); + if ( user == null || !Sha512Crypt.verifyPassword( password, user.password ) ) + return null; + return user; + } + public static boolean insertOrUpdate( User user ) { log.debug( "Inserted user '" + user.username + "' into db." ); @@ -58,7 +90,8 @@ public class DbUser extends User "SELECT user.userid, user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user" + " LEFT JOIN satellite USING (organization)" + " WHERE user.username = ? LIMIT 1", username ); - if ( user == null ) return 0; + if ( user == null ) + return 0; return user.userId; } @@ -70,29 +103,9 @@ public class DbUser extends User "SELECT user.userid, user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user" + " LEFT JOIN satellite USING (organization)" + " WHERE user.userid = ? LIMIT 1", id ); - if (user == null) return ""; + if ( user == null ) + return ""; return user.username; } - /** - * Checks if a user with id (userid@organization) exists - * @param id - * @return Whether the user exists - */ - public static boolean exists( String id ) - { - String[] parts = id.split( "@" ); - String user = parts[0]; - String organization = parts[1]; - - DbUser dbUser = MySQL.findUniqueOrNull( DbUser.class, - "SELECT user.userid, user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user" - + " LEFT JOIN satellite USING (organization)" - + " WHERE user.username = ? AND user.organization = ? LIMIT 1", user, organization); - - if ( dbUser == null ) return false; - - return true; - } - } diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index ee22493..ce20020 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -19,7 +19,7 @@ import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.thrift.iface.AuthorizationError; import org.openslx.imagemaster.thrift.iface.AuthorizationException; -import org.openslx.imagemaster.thrift.iface.DownloadInfos; +import org.openslx.imagemaster.thrift.iface.DownloadData; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.ImageDataError; import org.openslx.imagemaster.thrift.iface.ImageDataException; @@ -28,8 +28,8 @@ import org.openslx.imagemaster.thrift.iface.ServerAuthenticationError; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException; import org.openslx.imagemaster.thrift.iface.ServerSessionData; import org.openslx.imagemaster.thrift.iface.SessionData; +import org.openslx.imagemaster.thrift.iface.UploadData; import org.openslx.imagemaster.thrift.iface.UploadException; -import org.openslx.imagemaster.thrift.iface.UploadInfos; import org.openslx.imagemaster.thrift.iface.UserInfo; /** @@ -85,18 +85,18 @@ public class ApiServer session.getLastName(), session.getEMail() ); } - public static UploadInfos submitImage( String serverSessionId, ImageData imageDescription, List crcSums ) + public static UploadData submitImage( String serverSessionId, ImageData imageDescription, List crcSums ) throws AuthorizationException, ImageDataException, UploadException { // first check session of server if ( ServerSessionManager.getSession( serverSessionId ) == null ) { - throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessioId" ); + throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionId" ); } // then let the image processor decide what to do - return ImageProcessor.getUploadInfos( serverSessionId, imageDescription, crcSums ); + return ImageProcessor.getUploadInfos( imageDescription, crcSums ); } - public static DownloadInfos getImage( String uuid, String serverSessionId ) throws AuthorizationException, ImageDataException + public static DownloadData getImage( String uuid, String serverSessionId ) throws AuthorizationException, ImageDataException { // first check session of server if ( ServerSessionManager.getSession( serverSessionId ) == null ) { @@ -108,7 +108,7 @@ public class ApiServer } // then let the image processor decide what to do - return ImageProcessor.getDownloadInfos( serverSessionId, uuid, null ); + return ImageProcessor.getDownloadInfos( uuid ); } /** diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/Connection.java b/src/main/java/org/openslx/imagemaster/serverconnection/Connection.java deleted file mode 100644 index bfdb1bb..0000000 --- a/src/main/java/org/openslx/imagemaster/serverconnection/Connection.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.openslx.imagemaster.serverconnection; - -/** - * This represents a connection. - * (When a satellite is up- or downloading an image from/to masterserver). - * It is used to help the ConnectionHandler and is storing infos. - */ -public class Connection -{ - /** - * Where the file is stored locally. - */ - protected final String filepath; - - /** - * Type of this connection. - * True if uploading, false if downloading - */ - protected final boolean type; - public UploadingImage image = null; - public DownloadingClient client = null; - public final static boolean UPLOADING = true; - public final static boolean DOWNLOADING = false; - - /** - * Create a new connection data - * @param filepath Where the file is stored locally - * @param type True if uploading, false if downloading - * @param listenerThread The active listener thread that listens for incoming connections - */ - protected Connection(String filepath, boolean type) - { - this.filepath = filepath; - this.type = type; - } -} diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java b/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java index 0fb52f5..e6319c9 100644 --- a/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java +++ b/src/main/java/org/openslx/imagemaster/serverconnection/ConnectionHandler.java @@ -1,6 +1,5 @@ package org.openslx.imagemaster.serverconnection; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -10,14 +9,18 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import org.apache.commons.lang.mutable.MutableInt; import org.apache.log4j.Logger; import org.openslx.filetransfer.Downloader; import org.openslx.filetransfer.FileRange; @@ -26,6 +29,7 @@ import org.openslx.filetransfer.Listener; import org.openslx.filetransfer.Uploader; import org.openslx.filetransfer.WantRangeCallback; import org.openslx.imagemaster.Globals; +import org.openslx.imagemaster.db.DbImage; /** * Class to handle all incoming and outgoing connections. @@ -37,8 +41,11 @@ public class ConnectionHandler implements IncomingEvent private static Logger log = Logger.getLogger( ConnectionHandler.class ); private static SSLContext sslContext; - private static Map connections = new ConcurrentHashMap<>(); + private static Map pendingIncomingUploads = new ConcurrentHashMap<>(); + private static Map pendingIncomingDownloads = new ConcurrentHashMap<>(); private static IncomingEvent eventHandler = new ConnectionHandler(); + private static ThreadPoolExecutor uploadPool = new ThreadPoolExecutor( 0, 5, 6, TimeUnit.MINUTES, new SynchronousQueue() ); + private static ThreadPoolExecutor downloadPool = new ThreadPoolExecutor( 0, 5, 6, TimeUnit.MINUTES, new SynchronousQueue() ); private static Listener listener; @@ -81,153 +88,120 @@ public class ConnectionHandler implements IncomingEvent } /** - * Add a new connection with a unique token. - * To up- or download the file in file path. + * Add a new allowed incoming upload connection + * for the given token and image. * * @param token The unique token - * @param filepath The file to up- or download - * @param type True if upload or false if download - * @return The created connection + * @param image Image being uploaded */ - public static Connection addConnection( String token, String filepath, boolean type ) + public static void addUpload( String token, UploadingImage image ) { - log.debug( "Added connection (" + ( ( type ) ? "uploading" : "downloading" ) + ") with token: '" + token + "'" ); - - Connection connection = new Connection( filepath, type ); - synchronized ( connections ) { - connections.put( token, connection ); - } - return connection; - } - - public static boolean hasConnection( String token ) - { - return connections.containsKey( token ); + pendingIncomingUploads.put( token, image ); + log.debug( "Added upload" ); } - public static void removeConnection( String token ) + /** + * Add a new allowed incoming download connection + * for the given token and image. + * + * @param token The unique token + * @param image Image being uploaded + */ + public static void addDownload( String token, DbImage image ) { - synchronized ( connections ) { - connections.remove( token ); // token is remove, so connections are rejected - } + pendingIncomingDownloads.put( token, image ); + log.debug( "Added download" ); } /** * Server is uploading - client is downloading! */ @Override - public void incomingUploader( Uploader uploader ) throws IOException + public void incomingUploader( final Uploader uploader ) { String token = uploader.getToken(); - log.debug( "Got token :'" + token + "'" ); // check token to identify the client - if (token == null) - { + if ( token == null ) { uploader.sendErrorCode( "No token available." ); - uploader.close(null); + uploader.close( null ); return; } - if ( !connections.containsKey( token ) ) { + + final DbImage image = pendingIncomingDownloads.remove( token ); + if ( image == null ) { uploader.sendErrorCode( "Token not accepted." ); - uploader.close(null); + uploader.close( null ); return; } - // check if he was a downloading client - if ( connections.get( token ).type == Connection.UPLOADING ) { - uploader.sendErrorCode( "You can not download, if you are uploading." ); - uploader.close(null); - return; + try { + uploadPool.execute( new Runnable() { + @Override + public void run() + { + uploader.upload( image.getAbsolutePath() ); + } + } ); + } catch ( RejectedExecutionException e ) { + uploader.sendErrorCode( "Too many concurrent uploads." ); + uploader.close( null ); } - - String fileName = connections.get( token ).filepath; - uploader.upload(fileName); } /** * Server is downloading - client is uploading! */ @Override - public void incomingDownloader( Downloader downloader ) throws IOException + public void incomingDownloader( final Downloader downloader ) throws IOException { log.debug( "Client wants to upload" ); String token = downloader.getToken(); - if (token == null) + if ( token == null ) { downloader.sendErrorCode( "No token available." ); - downloader.close(null); + downloader.close( null ); return; } - // Check token to identify the client. - if ( !connections.containsKey( token ) ) { + + final UploadingImage image = pendingIncomingUploads.remove( token ); + if ( image == null ) { downloader.sendErrorCode( "Token not accepted." ); - downloader.close(null); + downloader.close( null ); return; } - - // check if he was a uploading client - if ( connections.get( token ).type == Connection.DOWNLOADING ) { - downloader.sendErrorCode( "You can not upload, if you are downloading." ); - downloader.close(null); - return; + final MutableInt lastBlock = new MutableInt( -1 ); + + try { + downloadPool.execute( new Runnable() { + @Override + public void run() + { + downloader.download( image.getAbsolutePath(), new WantRangeCallback() { + @Override + public FileRange get() + { + if ( lastBlock.intValue() != -1 ) { + image.setNeedsCheck( lastBlock.intValue() ); + image.increaseTransmittedTimes( lastBlock.intValue() ); + } + // get start of range. + int blockNumber = image.getNextMissingBlock(); + if ( blockNumber == -1 ) + return null; + lastBlock.setValue( blockNumber ); + log.debug( "Block " + blockNumber + " was transmitted " + image.getTimesTransmitted( blockNumber ) + " time(s)." ); + + long startOfRange = image.getNextMissingBlock() * Globals.blockSize; + long endOfRange = Math.min( startOfRange + Globals.blockSize, image.getFileSize() ); + FileRange range = new FileRange( startOfRange, endOfRange ); + return range; + } + } ); + } + } ); + } catch ( RejectedExecutionException e ) { + downloader.sendErrorCode( "Too many concurrent downloads." ); + downloader.close( null ); } - - String destinationFileName = connections.get( token ).filepath; - final UploadingImage image = connections.get( token ).image; - downloader.download( destinationFileName, new WantRangeCallback() { - - @Override - public FileRange get() { - // get start of range. - int blockNumber = image.getNextMissingBlock(); - if (blockNumber == -1) - return null; - - image.setNeedsCheck( blockNumber ); - image.increaseTransmittedTimes( blockNumber ); - log.debug( "Block " + blockNumber + " was transmitted " + image.getTimesTransmitted( blockNumber ) + " time(s)." ); - - long startOfRange = image.getNextMissingBlock() * Globals.blockSize; - long endOfRange = Math.min(startOfRange + Globals.blockSize, image.getImageFile().length()); - FileRange range = new FileRange(startOfRange, endOfRange); - return range; - } - }); -// long startOfRange = 0; -// String token = ""; -// // try to read meta data -// while ( downloader.readMetaData() ) { -// // check token to identify the client -// token = downloader.getToken(); -// if ( !connections.containsKey( token ) ) { -// downloader.sendErrorCode( "Token not accepted." ); -// downloader.close(null); -// return; -// } -// -// startOfRange = downloader.getStartOfRange(); -// -// if ( downloader.getDiffOfRange() <= 0 ) { -// return; -// } -// -// // check if he was a uploading client -// if ( connections.get( token ).type == Connection.DOWNLOADING ) { -// downloader.sendErrorCode( "You can not upload, if you are downloading." ); -// downloader.close(null); -// return; -// } -// -// -// int blockNumber = (int) ( startOfRange / Globals.blockSize ); -// UploadingImage image = connections.get( token ).image; -// image.setNeedsCheck( blockNumber ); -// image.increaseTransmittedTimes( blockNumber ); -// log.debug( "Block " + blockNumber + " was transmitted " + image.getTimesTransmitted( blockNumber ) + " time(s)." ); -// -// downloader.setOutputFilename( connections.get( token ).filepath ); -// downloader.receiveBinary(); -// } - downloader.close(null); } } diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/CrcScheduler.java b/src/main/java/org/openslx/imagemaster/serverconnection/CrcScheduler.java index 1ad921b..ff1374c 100644 --- a/src/main/java/org/openslx/imagemaster/serverconnection/CrcScheduler.java +++ b/src/main/java/org/openslx/imagemaster/serverconnection/CrcScheduler.java @@ -29,7 +29,7 @@ public class CrcScheduler extends TimerTask // iterate over the uploading images that need to be checked while ( iter.hasNext() ) { UploadingImage image = iter.next(); - log.debug( "Checking blocks of " + image.getDbImage().imageName ); + log.debug( "Checking blocks of " + image.getUuid() ); CrcChecker crcChecker = new CrcChecker( image.getImageFile(), image.getCrcFile() ); log.debug( "CRCFile is valid: " + crcChecker.hasValidCrcFile() ); if ( !crcChecker.hasValidCrcFile() ) { diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/DownloadingClient.java b/src/main/java/org/openslx/imagemaster/serverconnection/DownloadingClient.java deleted file mode 100644 index 630096f..0000000 --- a/src/main/java/org/openslx/imagemaster/serverconnection/DownloadingClient.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.openslx.imagemaster.serverconnection; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Helper class for the ImageProcessor and ConnectionHandler to know some things about the downloading client - */ -public class DownloadingClient -{ - - private final HashMap downloadingImages = new HashMap<>(); - - public void addDownload( String uuid, List list, String token ) - { - downloadingImages.put( uuid, new ImageInfos( uuid, list, token ) ); - } - - public void removeDownload( String uuid ) - { - downloadingImages.remove( uuid ); - } - - public boolean isDownloading( String uuid ) - { - return downloadingImages.containsKey( uuid ); - } - - public boolean hasDownloads() - { - return (downloadingImages.size() > 0); - } - - public List getLastRequestedBlocks( String token ) - { - for (Map.Entry entry : downloadingImages.entrySet() ) { - if (entry.getValue().token.equals( token )) return entry.getValue().lastRequestedBlocks; - } - return null; - } - - public void requestBlocks( String uuid, List list ) - { - if ( !downloadingImages.containsKey( uuid ) ) - return; - downloadingImages.get( uuid ).lastRequestedBlocks = list; - } - - public String getToken( String uuid ) - { - if ( !downloadingImages.containsKey( uuid ) ) - return null; - return downloadingImages.get( uuid ).token; - } - - class ImageInfos - { - public final String uuid; - public final String token; - private List lastRequestedBlocks; - - ImageInfos(String uuid, List list, String token) - { - this.uuid = uuid; - this.lastRequestedBlocks = list; - this.token = token; - } - } - -} diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java index d5e253c..739bc62 100644 --- a/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java +++ b/src/main/java/org/openslx/imagemaster/serverconnection/ImageProcessor.java @@ -1,9 +1,7 @@ package org.openslx.imagemaster.serverconnection; import java.io.File; -import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -15,13 +13,13 @@ import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.crcchecker.CrcFile; import org.openslx.imagemaster.db.DbImage; import org.openslx.imagemaster.db.DbUser; -import org.openslx.imagemaster.thrift.iface.DownloadInfos; +import org.openslx.imagemaster.thrift.iface.DownloadData; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.ImageDataError; import org.openslx.imagemaster.thrift.iface.ImageDataException; +import org.openslx.imagemaster.thrift.iface.UploadData; import org.openslx.imagemaster.thrift.iface.UploadError; import org.openslx.imagemaster.thrift.iface.UploadException; -import org.openslx.imagemaster.thrift.iface.UploadInfos; import org.openslx.imagemaster.util.RandomString; import org.openslx.imagemaster.util.Util; @@ -34,10 +32,6 @@ 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, @@ -48,14 +42,7 @@ public class ImageProcessor /** * The UUIDs of the images that need to be checked by the crc checker. */ - private static List imagesToCheck = new LinkedList<>(); - - /** - * The downloading clients. - * Key: serverSessionId - * Value: downloadingClientInfos - */ - private static HashMap downloadingClients = new HashMap<>(); + private static List imagesToCheck = new ArrayList<>(); /** * Checks if this image is already uploading and returns a new list with missing blocks if so. @@ -66,218 +53,81 @@ public class ImageProcessor * @return * @throws UploadException If some error occurred during the process */ - public static UploadInfos getUploadInfos( String serverSessionId, ImageData imageData, List crcSums ) + public static UploadData getUploadInfos( ImageData imageData, List crcSums ) throws UploadException, ImageDataException { // check image data - if ( imageData.imageName == null || imageData.imageName.isEmpty() ) { + if ( imageData.imageName == null || imageData.imageName.isEmpty() ) throw new ImageDataException( ImageDataError.INVALID_DATA, "Image name not set." ); - } else if ( imageData.imageOwner == null || imageData.imageOwner.isEmpty() ) { - throw new ImageDataException( ImageDataError.INVALID_DATA, "Image owner not set." ); - } else if ( imageData.contentOperatingSystem == null || imageData.contentOperatingSystem.isEmpty() ) { + if ( imageData.imageOwner == null || !DbUser.exists( imageData.imageOwner ) ) + throw new ImageDataException( ImageDataError.INVALID_DATA, "Invalid image owner." ); + if ( imageData.contentOperatingSystem == null || imageData.contentOperatingSystem.isEmpty() ) throw new ImageDataException( ImageDataError.INVALID_DATA, "Content operating system not set." ); - } else if ( imageData.fileSize <= 0 ) { + if ( imageData.fileSize <= 0 ) throw new ImageDataException( ImageDataError.INVALID_DATA, "File size is too small." ); - } else if ( !DbUser.exists( imageData.imageOwner ) ) { - throw new ImageDataException( ImageDataError.INVALID_DATA, "User is not known." ); - } - - //TODO: this is not working like this: - DbImage i = DbImage.getImageByUuid( imageData.uuid ); -// boolean isUpdate = false; -// if ( i != null ) { -// // image is already available -// // is the client updating?? -// if ( imageData.imageVersion <= i.imageVersion ) { -// throw new ImageDataException( ImageDataError.INVALID_DATA, "This image with the same or a newer version is already available." ); -// } else { -// // TODO: update db and prepare for new image file -// isUpdate = true; -// } -// } - log.debug( serverSessionId + " is submitting " + imageData.uuid ); + log.debug( "Satellite is submitting " + imageData.uuid ); - String uuid = imageData.uuid; - String token; - String filepath; - int nBlocks; - int[] allBlocks; + final String uuid = imageData.uuid; + final String filepathRelative; + final CrcFile crcFile = new CrcFile( crcSums ); UploadingImage image; synchronized ( uploadingImages ) { // check if image is already uploading - if ( ( image = uploadingImages.get( uuid ) ) != null ) { - if ( image.getCrcFile() == null ) { - CrcFile crcFile; - try { - // try to write crc file ... - crcFile = CrcFile.writeCrcFile( crcSums, generateFilepathOfCrcFile( imageData ) ); - } catch ( IOException e ) { - // ... and keep it in ram if it fails - crcFile = new CrcFile( crcSums ); - } - image.setCrcFile( crcFile ); + if ( ( image = uploadingImages.get( uuid ) ) == null ) { + // insert new image + if ( crcSums != null && !crcFile.isValid() ) + throw new UploadException( UploadError.INVALID_CRC, "CRC sums were invalid." ); + filepathRelative = generateFilepathOfImage( imageData ); + DbImage.insert( imageData, filepathRelative ); // Make sure it exists in DB + try { + image = new UploadingImage( uuid ); + } catch ( Exception e ) { + throw new UploadException( UploadError.GENERIC_ERROR, "Internal error" ); } - List missing = getNMissingBlocks( image, AMOUNT ); - if ( missing.isEmpty() && image.allBlocksValid() ) { - uploadDone( uuid ); - return new UploadInfos( image.getToken(), Globals.getSslSocketPort(), missing, image.allBlocksValid() ); - } - return new UploadInfos( image.getToken(), Globals.getSslSocketPort(), missing, false ); - } - - // insert new image - if ( !CrcFile.sumsAreValid( crcSums ) ) - throw new UploadException( UploadError.INVALID_CRC, "CRC sums were invalid." ); - filepath = generateFilepathOfImage( imageData ); - token = RandomString.generate( 100, false ); - nBlocks = Util.getNumberOfBlocks( imageData.fileSize, Globals.blockSize ); - allBlocks = new int[ nBlocks ]; // initialize array with all zeros which mean that this block is missing - image = new UploadingImage( token, allBlocks, System.currentTimeMillis(), uuid, filepath ); - image.setDbImage( i ); // set the dbImage (it doesn't matter if the image is null because the uploadingImage is creating it then - uploadingImages.put( uuid, image ); - } - - CrcFile crcFile; - try { - // try to write crc file ... - crcFile = CrcFile.writeCrcFile( crcSums, generateFilepathOfCrcFile( imageData ) ); - } catch ( IOException e ) { - // ... and keep it in ram if it fails - crcFile = new CrcFile( crcSums ); - } - image.setCrcFile( crcFile ); - - ConnectionHandler.addConnection( token, filepath, Connection.UPLOADING ).image = image; -// if ( isUpdate ) { -// i.updateVersion( i.imageVersion, Util.getNumberOfBlocks( i.fileSize, Globals.blockSize ) ); -// } else { - DbImage.insert( imageData, System.currentTimeMillis(), token, nBlocks, serverSessionId, filepath ); -// } - imagesToCheck.add( uuid ); - log.debug( imagesToCheck ); - - log.debug( image.toString() ); - return new UploadInfos( token, Globals.getSslSocketPort(), getNMissingBlocks( image, AMOUNT ), false ); - } - - public static DownloadInfos getDownloadInfos( String serverSessionId, String uuid, List requestedBlocks ) - { - // check if server is already downloading - if ( downloadingClients.containsKey( serverSessionId ) ) { - DownloadingClient client = downloadingClients.get( serverSessionId ); - - // remove download if done - if ( requestedBlocks.isEmpty() ) - { - downloadDone( serverSessionId, uuid ); - return new DownloadInfos(); - } - - if ( client.isDownloading( uuid ) ) - { - // client was downloading this image - // update the requested blocks - client.requestBlocks( uuid, requestedBlocks ); - return new DownloadInfos( client.getToken( uuid ), Globals.getSslSocketPort() ); + uploadingImages.put( uuid, image ); } - - // 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; - ConnectionHandler.addConnection( token, filepath, Connection.DOWNLOADING ); - - client.addDownload( uuid, requestedBlocks, token ); - downloadingClients.put( serverSessionId, client ); - return new DownloadInfos( token, Globals.getSslSocketPort() ); } - // insert new client and start listener - synchronized ( downloadingClients ) { - String token = RandomString.generate( 100, false ); - String filepath = DbImage.getImageByUuid( uuid ).imagePath; - - DownloadingClient client = new DownloadingClient(); - client.addDownload( uuid, requestedBlocks, token ); - downloadingClients.put( serverSessionId, client ); + final String token = RandomString.generate( 50, false ); - ConnectionHandler.addConnection( token, filepath, Connection.DOWNLOADING ).client = client; - return new DownloadInfos( token, Globals.getSslSocketPort() ); - } + ConnectionHandler.addUpload( token, image ); + // Set crc file on image - if there is already a crc file assigned, this does nothing + image.setCrcFile( crcFile ); + if ( image.allBlocksValid() ) + removeFinishedUploads(); + return new UploadData( token, Globals.getSslSocketPort() ); } - private static void downloadDone( String serverSessionId, String uuid ) + public static DownloadData getDownloadInfos( String uuid ) throws ImageDataException { - synchronized ( downloadingClients ) { - DownloadingClient client = downloadingClients.get( serverSessionId ); - client.removeDownload( uuid ); - ConnectionHandler.removeConnection( client.getToken( uuid ) ); - if ( !client.hasDownloads() ) { - downloadingClients.remove( serverSessionId ); - } - } + DbImage image = DbImage.getImageByUuid( uuid ); + if ( image == null ) + throw new ImageDataException( ImageDataError.UNKNOWN_IMAGE, "UUID '" + uuid + "' does not map to a known image." ); + // server was downloading another image and now gets a new connection for this new download + String token = RandomString.generate( 50, false ); + ConnectionHandler.addDownload( token, image ); + return new DownloadData( token, Globals.getSslSocketPort(), null ); // TODO: Return crc list } /** - * 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 blocks - * @throws UploadException If a block was transmitted to many times. + * Go though list of active uploading images and remove + * those that are finished. */ - private static List getNMissingBlocks( UploadingImage image, int amount ) throws UploadException + public static void removeFinishedUploads() { - int missing = image.getAmountOfBlocksNeedingRequest(); - log.debug( "The number of missing blocks: " + missing ); - if ( amount > missing ) - amount = missing; - List result = new ArrayList<>( amount ); - - int got = 0; - for ( int i = 0; i < image.getNumberOfBlocks(); i++ ) { - if ( image.needsRequest( i ) ) { - int times = image.getTimesTransmitted( i ); - if ( times > Globals.getSslTransmitTimes() ) { - log.debug( "Block " + i + " is probably broken." ); - throw new UploadException( UploadError.BROKEN_BLOCK, "Block " + i + " was transmitted " - + times + " and is still not valid." ); - } - result.add( i ); - got++; + for (Iterator it = uploadingImages.values().iterator(); it.hasNext(); ) { + UploadingImage image = it.next(); + if (image.allBlocksValid()) { + synchronized ( imagesToCheck ) { + imagesToCheck.remove( image.getUuid() ); + image.updateMissingBlocks( null ); + } + it.remove(); } - if ( got == amount ) - break; - } - - log.debug( "Returned " + got + " missing blocks." ); - - 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 ( imagesToCheck ) { - imagesToCheck.remove( uuid ); - log.debug( "Removing " + uuid ); - } - - UploadingImage image; - synchronized ( uploadingImages ) { - image = uploadingImages.remove( uuid ); } - image.getDbImage().updateMissingBlocks( null ); - // file was already downloaded in the right location by the updownloader class. - // remove the connection so that it can be used by a new client - ConnectionHandler.removeConnection( image.getToken() ); } public static List getImagesToCheck() @@ -297,28 +147,28 @@ public class ImageProcessor // TODO return null; } - + /** * Generates the filePath of an image. * And creates the folder if wanted. * The crc file is found under filePath + ".crc" * * @param imageData The data of the image - * @param createFolder If you want the folder to be created * @return The filePath of the given image */ public static String generateFilepathOfImage( ImageData imageData ) { return generateFilePathOfImage( imageData.uuid, imageData.imageName, imageData.imageVersion ); } - - public static String generateFilePathOfImage( String uuid, String imageName, int imageVersion) { - String result = Globals.getImageDir() + "/" + uuid + "/"; - File dir = new File(result); + + public static String generateFilePathOfImage( String uuid, String imageName, int imageVersion ) + { + String result = Util.sanitizeFileName( uuid ) + "/"; + File dir = new File( Globals.getImageDir() + "/" + result ); if ( !dir.exists() ) { dir.mkdirs(); } - result += imageName + "-v" + String.valueOf( imageVersion ) + ".vmdk"; + result += imageName + "-rev" + String.valueOf( imageVersion ); return result; } @@ -326,41 +176,10 @@ public class ImageProcessor { return generateFilepathOfImage( imageData ) + ".crc"; } - + public static String generateFilepathOfCrcFile( String uuid, String imageName, int imageVersion ) { return generateFilePathOfImage( uuid, imageName, imageVersion ) + ".crc"; } - /** - * Checks pending uploads in database and adds them to process list again. - */ - static - { - List list = DbImage.getUploadingImages(); - for ( DbImage image : list ) { - UploadingImage infos = new UploadingImage( image.token, image.blockStatus, image.timestamp.getTime(), image.uuid, image.imagePath ); - ConnectionHandler.addConnection( image.token, image.imagePath, Connection.UPLOADING ).image = infos; - CrcFile crcFile = new CrcFile( generateFilepathOfCrcFile( image.uuid, image.imageName, image.imageVersion ) ); // TODO: has to be adjusted with the corresponding value above - try { - if ( !crcFile.isValid() ) { - continue; - // UploadingImage object will contain a CRCFile = null which invokes the ImageProcessor to retry to save it - } - } catch ( IOException e ) { - continue; - // same thing here - } - infos.setCrcFile( crcFile ); - uploadingImages.put( image.uuid, infos ); - imagesToCheck.add( image.uuid ); - } - log.info( "Added " + list.size() + " pending upload(s) to process list again." ); - } - - - - public static void init() - { - } } diff --git a/src/main/java/org/openslx/imagemaster/serverconnection/UploadingImage.java b/src/main/java/org/openslx/imagemaster/serverconnection/UploadingImage.java index 169877c..78d5f2b 100644 --- a/src/main/java/org/openslx/imagemaster/serverconnection/UploadingImage.java +++ b/src/main/java/org/openslx/imagemaster/serverconnection/UploadingImage.java @@ -1,5 +1,6 @@ package org.openslx.imagemaster.serverconnection; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -10,16 +11,14 @@ import org.openslx.imagemaster.crcchecker.ImageFile; import org.openslx.imagemaster.db.DbImage; /** - * Helper class for ImageProcessor and ConnectionHandler to save some infos about the images in the process list. + * Helper class for ImageProcessor and ConnectionHandler to save some infos about the images in the + * process list. */ public class UploadingImage { public static final Logger log = Logger.getLogger( UploadingImage.class ); - /** - * Token for the satellite. - */ - private String token; + /** * The status list of the blocks. * x = 0 block is missing @@ -27,177 +26,164 @@ public class UploadingImage * x > 0 block is invalid and was transmitted x times (needs request) * x < 0 block is invalid and was transmitted x times (needs check) */ - private int[] blockStatus = null; - public static final int valid = 200; - public static final int missing = 0; - private long timestamp; // when did the server something for the last time + private final int[] blockStatus; + /** + * Remember last position in blockStatus array that was returned, so we don't always + * iterate from the beginning. + */ + private int lastStatusPos = 0; + + public static final int VALID = 200; + public static final int MISSING = 0; + private DbImage dbImage = null; // the DB representation of this image - private String uuid; - private String filename; + /** + * Class for accessing the file (read blocks from it) + */ private ImageFile imageFile = null; private CrcFile crcFile = null; - protected UploadingImage(String token, int[] initialBlockStatus, long timestamp, String uuid, String filename) + protected UploadingImage( String uuid ) { - this.token = token; - this.timestamp = timestamp; - this.uuid = uuid; - this.blockStatus = initialBlockStatus; - this.filename = filename; + this.dbImage = DbImage.getImageByUuid( uuid ); + if ( this.dbImage == null ) + throw new RuntimeException( "Unknown image " + uuid + " on UploadingImage creation" ); + this.blockStatus = this.dbImage.blockStatus; } protected void setValid( int index ) { - if ( blockStatus == null ) - return; synchronized ( blockStatus ) { - blockStatus[index] = valid; + blockStatus[index] = VALID; } } protected void updateDb() { - if ( blockStatus == null ) - return; - List missingBlocks = new ArrayList<>(); - synchronized ( blockStatus ) { for ( int block = 0; block < blockStatus.length; block++ ) { - if ( blockStatus[block] != valid ) { + if ( blockStatus[block] != VALID ) { missingBlocks.add( block ); } } } - getDbImage().updateMissingBlocks( missingBlocks ); + dbImage.updateMissingBlocks( missingBlocks ); } protected void setMissing( int index ) { - if ( blockStatus == null ) - return; synchronized ( blockStatus ) { - blockStatus[index] = missing; + blockStatus[index] = MISSING; } } protected void setNeedsRequest( int index ) { - if ( blockStatus == null ) - return; synchronized ( blockStatus ) { - blockStatus[index] *= ( blockStatus[index] < missing ) ? -1 : 1; // switch to positive value if needed + blockStatus[index] = Math.abs( blockStatus[index] ); // switch to positive value if needed } } protected void setNeedsCheck( int index ) { - if ( blockStatus == null ) - return; synchronized ( blockStatus ) { - blockStatus[index] *= ( blockStatus[index] > missing ) ? -1 : 1; // switch to negative value if needed + blockStatus[index] = -Math.abs( blockStatus[index] ); // switch to negative value if needed } } protected void increaseTransmittedTimes( int index ) { - if ( blockStatus == null || blockStatus[index] == 200 ) - return; synchronized ( blockStatus ) { - blockStatus[index] += ( blockStatus[index] <= missing ) ? -1 : 1; // increase in both directions + if ( blockStatus[index] == 200 ) + return; + blockStatus[index] += ( blockStatus[index] <= MISSING ) ? -1 : 1; // increase in both directions } } protected int getTimesTransmitted( int index ) { synchronized ( blockStatus ) { - return ( blockStatus[index] > 0 ) ? blockStatus[index] : ( -1 ) * blockStatus[index]; + return Math.abs( blockStatus[index] ); } } - protected String getToken() - { - return this.token; - } - protected boolean needsRequest( int index ) { - if ( blockStatus == null ) - return false; synchronized ( blockStatus ) { - return ( ( blockStatus[index] >= missing ) && ( blockStatus[index] != valid ) ); + return ( ( blockStatus[index] >= MISSING ) && ( blockStatus[index] != VALID ) ); } } protected boolean needsCheck( int index ) { - if ( blockStatus == null ) - return false; synchronized ( blockStatus ) { - return ( blockStatus[index] < missing ); + return ( blockStatus[index] < MISSING ); } } protected int getNumberOfBlocks() { - /////////////////////////////////////////////////////////////////// -// ArrayList l = new ArrayList( blockStatus.length ); -// for ( int i : blockStatus ) { -// l.add( i ); -// } -// log.debug( l ); - /////////////////////////////////////////////////////////////////// return blockStatus.length; } - + protected int getNextMissingBlock() { - // TODO: handle intern status of current uploading block. - for (int i = 0; i < blockStatus.length; i++) { - if (blockStatus[i] == 0) - return i; + synchronized ( blockStatus ) { + for ( int i = 0; i < blockStatus.length; i++ ) { + int index = ( i + lastStatusPos ) % blockStatus.length; + if ( blockStatus[index] == MISSING ) + return lastStatusPos = index; + } + for ( int index = 0; index < blockStatus.length; index++ ) { + if ( blockStatus[index] > MISSING && blockStatus[index] < VALID ) + return lastStatusPos = index; + } + for ( int index = 0; index < blockStatus.length; index++ ) { + if ( blockStatus[index] < MISSING ) + return lastStatusPos = index; + } } return -1; } + /* protected long getTimestamp() { return this.timestamp; } - - protected DbImage getDbImage() - { - if ( dbImage == null ) { - dbImage = DbImage.getImageByUuid( this.uuid ); - } - return this.dbImage; - } - - protected void setDbImage( DbImage dbImage ) - { - if ( dbImage != null ) { - return; - } else { - this.dbImage = dbImage; - } - } + */ protected ImageFile getImageFile() { if ( imageFile == null ) { - imageFile = new ImageFile( filename, Globals.blockSize ); + imageFile = new ImageFile( dbImage.getAbsolutePath(), Globals.blockSize ); } return imageFile; } protected CrcFile getCrcFile() { + if ( crcFile == null ) { + try { + crcFile = new CrcFile( dbImage.getAbsolutePath() + ".crc" ); + } catch ( IOException e ) { + // Not found... return null + } + } return crcFile; } protected void setCrcFile( CrcFile crcFile ) { - this.crcFile = crcFile; + if ( getCrcFile() == null ) { + this.crcFile = crcFile; + try { + crcFile.writeCrcFile( dbImage.getAbsolutePath() + ".crc" ); + } catch ( IOException e ) { + log.error( "Could not write crc list to file", e ); + } + } } public int getAmountOfBlocksNeedingRequest() @@ -228,8 +214,28 @@ public class UploadingImage @Override public String toString() { - return "UUID: " + uuid + ", filename " + filename + "\nmissing blocks " + getAmountOfBlocksNeedingRequest() + - ", number of blocks " + getNumberOfBlocks() + ", token " + getToken(); + return "UUID: " + dbImage.uuid + ", filename " + dbImage.imagePath + "\nmissing blocks " + getAmountOfBlocksNeedingRequest() + + ", number of blocks " + getNumberOfBlocks(); + + } + public String getAbsolutePath() + { + return dbImage.getAbsolutePath(); + } + + public long getFileSize() + { + return dbImage.fileSize; + } + + public String getUuid() + { + return dbImage.uuid; + } + + public void updateMissingBlocks( List missingBlocks ) + { + dbImage.updateMissingBlocks( missingBlocks ); } } diff --git a/src/main/java/org/openslx/imagemaster/session/Authenticator.java b/src/main/java/org/openslx/imagemaster/session/Authenticator.java index 5d1b728..19891b9 100644 --- a/src/main/java/org/openslx/imagemaster/session/Authenticator.java +++ b/src/main/java/org/openslx/imagemaster/session/Authenticator.java @@ -1,9 +1,7 @@ package org.openslx.imagemaster.session; import org.apache.log4j.Logger; -import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.db.DbUser; -import org.openslx.imagemaster.db.LdapUser; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; @@ -26,6 +24,7 @@ public class Authenticator public static User authenticate( String username, String password ) throws AuthenticationException { String login = username; + /* if ( username.split( "@" ).length == 2 ) { log.info( "username is in username@organization format" ); // we are in username@organization format @@ -37,10 +36,11 @@ public class Authenticator log.info( "username is not in a valid format." ); throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Credentials must be in (username@organization) or (prefix@username)" ); } + */ log.info( "Logging in with: " + login ); - LdapUser user = LdapUser.forLogin( login, password ); // throws exception if credentials are invalid + User user = DbUser.forLogin( login, password ); // throws exception if credentials are invalid if ( user == null ) { log.debug( "Login failed: " + username ); throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Something went wrong." ); diff --git a/src/main/java/org/openslx/imagemaster/session/User.java b/src/main/java/org/openslx/imagemaster/session/User.java index 82ba8ca..264c17f 100644 --- a/src/main/java/org/openslx/imagemaster/session/User.java +++ b/src/main/java/org/openslx/imagemaster/session/User.java @@ -14,8 +14,8 @@ public abstract class User public final String satelliteAddress; public final int userId; - protected User(int userId, String username, String password, String organization, String firstName, String lastName, String eMail, - String satelliteAddress) + protected User( int userId, String username, String password, String organization, String firstName, String lastName, String eMail, + String satelliteAddress ) { this.userId = userId; this.username = username; @@ -46,4 +46,9 @@ public abstract class User return sb.toString(); } + public String getLogin() + { + return username + "@" + organization; + } + } diff --git a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java index 6ca2384..84e3ede 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java @@ -8,7 +8,7 @@ import org.apache.thrift.TException; import org.openslx.imagemaster.server.ApiServer; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.thrift.iface.AuthorizationException; -import org.openslx.imagemaster.thrift.iface.DownloadInfos; +import org.openslx.imagemaster.thrift.iface.DownloadData; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.ImageDataException; import org.openslx.imagemaster.thrift.iface.ImageServer; @@ -16,8 +16,8 @@ import org.openslx.imagemaster.thrift.iface.InvalidTokenException; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException; import org.openslx.imagemaster.thrift.iface.ServerSessionData; import org.openslx.imagemaster.thrift.iface.SessionData; +import org.openslx.imagemaster.thrift.iface.UploadData; import org.openslx.imagemaster.thrift.iface.UploadException; -import org.openslx.imagemaster.thrift.iface.UploadInfos; import org.openslx.imagemaster.thrift.iface.UserInfo; public class ImageServerHandler implements ImageServer.Iface @@ -63,13 +63,13 @@ public class ImageServerHandler implements ImageServer.Iface } @Override - public UploadInfos submitImage( String serverSessionId, ImageData imageDescription, List crcSums ) throws AuthorizationException, ImageDataException, UploadException, TException + public UploadData submitImage( String serverSessionId, ImageData imageDescription, List crcSums ) throws AuthorizationException, ImageDataException, UploadException, TException { return ApiServer.submitImage( serverSessionId, imageDescription, crcSums ); } @Override - public DownloadInfos getImage( String uuid, String serverSessionId ) throws AuthorizationException, ImageDataException, TException + public DownloadData getImage( String serverSessionId, String uuid ) throws AuthorizationException, ImageDataException, TException { return ApiServer.getImage( uuid, serverSessionId ); } diff --git a/src/main/java/org/openslx/imagemaster/util/Util.java b/src/main/java/org/openslx/imagemaster/util/Util.java index 595c059..ffd3106 100644 --- a/src/main/java/org/openslx/imagemaster/util/Util.java +++ b/src/main/java/org/openslx/imagemaster/util/Util.java @@ -100,11 +100,23 @@ public class Util * @return The parsed int or 0 on error */ public static int tryToParseInt( String s ) + { + return tryToParseInt( s, 0 ); + } + + /** + * Tries to parse an int. Returns defaultValue on error. + * + * @param s The strig to parse + * @param defaultValue value to be returned if s is not parsable + * @return The parsed int + */ + public static int tryToParseInt( String s, int defaultValue ) { try { return Integer.parseInt( s ); } catch ( NumberFormatException e ) { - return 0; + return defaultValue; } } @@ -116,4 +128,12 @@ public class Util return blocks; } + public static String sanitizeFileName( String fileName ) + { + fileName = fileName.replaceAll( "[^a-zA-Z0-9_\\-]+", "_" ); + if ( fileName.length() > 40 ) + fileName = fileName.substring( 0, 40 ); + return fileName; + } + } diff --git a/src/test/java/org/openslx/imagemaster/AppTest.java b/src/test/java/org/openslx/imagemaster/AppTest.java index de18faa..079d0c2 100644 --- a/src/test/java/org/openslx/imagemaster/AppTest.java +++ b/src/test/java/org/openslx/imagemaster/AppTest.java @@ -1,14 +1,9 @@ package org.openslx.imagemaster; -import java.util.UUID; - import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.openslx.imagemaster.serverconnection.ImageProcessor; -import org.openslx.imagemaster.thrift.iface.ImageData; -import org.openslx.imagemaster.thrift.iface.UploadInfos; import org.openslx.imagemaster.util.Sha512Crypt; /** -- cgit v1.2.3-55-g7522