diff options
author | Simon Rettberg | 2016-04-18 15:18:05 +0200 |
---|---|---|
committer | Simon Rettberg | 2016-04-18 15:18:05 +0200 |
commit | cc70f09431deb7937e01cc6583884fb5067a2994 (patch) | |
tree | fcf7c8720a4479b09e07c82eb13f7015bb4d0533 /src/main/java/org/openslx/filetransfer/util/ChunkList.java | |
parent | Preparations/changes for global image sync (diff) | |
download | master-sync-shared-cc70f09431deb7937e01cc6583884fb5067a2994.tar.gz master-sync-shared-cc70f09431deb7937e01cc6583884fb5067a2994.tar.xz master-sync-shared-cc70f09431deb7937e01cc6583884fb5067a2994.zip |
More additions for central image store
Diffstat (limited to 'src/main/java/org/openslx/filetransfer/util/ChunkList.java')
-rw-r--r-- | src/main/java/org/openslx/filetransfer/util/ChunkList.java | 98 |
1 files changed, 96 insertions, 2 deletions
diff --git a/src/main/java/org/openslx/filetransfer/util/ChunkList.java b/src/main/java/org/openslx/filetransfer/util/ChunkList.java index 1b33102..e00aa0e 100644 --- a/src/main/java/org/openslx/filetransfer/util/ChunkList.java +++ b/src/main/java/org/openslx/filetransfer/util/ChunkList.java @@ -2,12 +2,14 @@ package org.openslx.filetransfer.util; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; +import org.openslx.util.ThriftUtil; public class ChunkList { @@ -33,7 +35,7 @@ public class ChunkList // 0 = complete, 1 = missing, 2 = uploading, 3 = queued for copying, 4 = copying, 5 = hashing private final ByteBuffer statusArray; - + /** * True if at least one block has a checksum set */ @@ -121,6 +123,35 @@ public class ChunkList } /** + * Set status of blocks according to given "ismissing" list. Intended to be called + * right after creating the list, in case we have a local file already and want to + * resume downloading. + */ + public synchronized void resumeFromStatusList( List<Boolean> statusList, long fileLength ) + { + if ( !completeChunks.isEmpty() || !pendingChunks.isEmpty() ) { + LOGGER.warn( "Inconsistent state: resume called when not all chunks are marked missing" ); + } + int index = 0; + for ( Boolean missing : statusList ) { + FileChunk chunk = allChunks.get( index ); + if ( fileLength != 0 && fileLength < chunk.range.endOffset ) + break; // Stop, file is shorter than end of this chunk + if ( missingChunks.remove( chunk ) || pendingChunks.remove( chunk ) ) { + completeChunks.add( chunk ); + } + if ( missing ) { + // Trigger hashing + chunk.setStatus( ChunkStatus.HASHING ); + } else { + // Assume complete + chunk.setStatus( ChunkStatus.COMPLETE ); + } + index++; + } + } + + /** * Get a chunk that is marked complete, has a sha1 hash, but has not been hash-checked yet. * * @return chunk @@ -166,7 +197,7 @@ public class ChunkList public synchronized int markFailed( FileChunk c ) { if ( !pendingChunks.remove( c ) ) { - LOGGER.warn( "Inconsistent state: markTransferred called for Chunk " + c.toString() + LOGGER.warn( "Inconsistent state: markFailed called for Chunk " + c.toString() + ", but chunk is not marked as currently transferring!" ); return -1; } @@ -178,6 +209,25 @@ public class ChunkList } /** + * Mark a missing chunk as complete. + */ + private synchronized boolean markMissingAsComplete( int index ) + { + FileChunk chunk = allChunks.get( index ); + if ( completeChunks.contains( chunk ) ) + return true; + if ( !missingChunks.remove( chunk ) ) { + LOGGER.warn( "Inconsistent state: markMissingAsComplete called for chunk " + chunk.toString() + " (indexed as " + index + + ") which is not missing" ); + return false; + } + chunk.setStatus( ChunkStatus.COMPLETE ); + completeChunks.add( chunk ); + this.notifyAll(); + return true; + } + + /** * Check if all blocks in this list are marked as successfully transfered. If a complete chunk is * marked as "hashing", or if there are some complete chunks without a sha1sum and some with a * sha1sum, the transfer is considered incomplete. @@ -259,4 +309,48 @@ public class ChunkList return allChunks; } + public static boolean hashListsEqualFcBb( List<FileChunk> one, List<ByteBuffer> two ) + { + return hashListsEqualFcArray( one, ThriftUtil.unwrapByteBufferList( two ) ); + } + + public static boolean hashListsEqualFcArray( List<FileChunk> one, List<byte[]> two ) + { + if ( one.size() != two.size() ) + return false; + FileChunk first = one.get( 0 ); + if ( first == null || first.getSha1Sum() == null ) + return false; + Iterator<byte[]> it = two.iterator(); + for ( FileChunk existingChunk : one ) { + byte[] testChunk = it.next(); + if ( !Arrays.equals( testChunk, existingChunk.getSha1Sum() ) ) + return false; + } + return true; + } + + public static boolean hashListsEqualBbBb( List<ByteBuffer> list1, List<ByteBuffer> list2 ) + { + return hashListsEqualBbArray( list1, ThriftUtil.unwrapByteBufferList( list2 ) ); + } + + public static boolean hashListsEqualBbArray( List<ByteBuffer> bufferList, List<byte[]> arrayList ) + { + return hashListsEqualArray( ThriftUtil.unwrapByteBufferList( bufferList ), arrayList ); + } + + public static boolean hashListsEqualArray( List<byte[]> list1, List<byte[]> list2 ) + { + if ( list1.size() != list2.size() ) + return false; + Iterator<byte[]> it1 = list1.iterator(); + Iterator<byte[]> it2 = list2.iterator(); + while ( it1.hasNext() && it2.hasNext() ) { + if ( !Arrays.equals( it1.next(), it2.next() ) ) + return false; + } + return true; + } + } |