/** Read a single block from a specific slot, which could be any block number. * @throws IOException If an error occurred reading the data from disk. */ private synchronized byte[] readBlock(int slotNumber) throws IOException { if(slotNumber >= blocksForDecode()) throw new IllegalArgumentException(); return parent.readBlock(this, slotNumber); }
/** Caller must have already lock()'ed parent.raf and synchronized(this). * @throws IOException */ private synchronized void writeDownloadedBlock(int slotNumber, byte[] data) throws IOException { // FIXME Do we need to pad here for really old splitfiles, or does the FEC code do it? if(data.length != CHKBlock.DATA_LENGTH) throw new IllegalArgumentException(); if(slotNumber >= blocksForDecode()) throw new IllegalArgumentException(); parent.writeBlock(this, slotNumber, data); }
public synchronized boolean needsDecode() { if(finished || succeeded || failed) return false; if(tryDecode) return false; return blockChooser.successCount() == blocksForDecode(); }
SplitFileSegmentKeys readSegmentKeys() throws IOException, ChecksumFailedException { SplitFileSegmentKeys keys = new SplitFileSegmentKeys(blocksForDecode(), checkBlocks, parent.splitfileSingleCryptoKey, parent.splitfileSingleCryptoAlgorithm); byte[] buf = new byte[SplitFileSegmentKeys.storedKeysLength(blocksForDecode(), checkBlocks, parent.splitfileSingleCryptoKey != null)]; parent.preadChecksummed(segmentKeyListOffset, buf, 0, buf.length); DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf)); keys.readKeys(dis, false); keys.readKeys(dis, true); return keys; }
private synchronized byte[][] readAllBlocks() throws IOException { RAFLock lock = parent.lockRAFOpen(); try { // FIXME consider using a single big byte[]. byte[][] ret = new byte[blocksForDecode()][]; for(int i=0;i<ret.length;i++) ret[i] = readBlock(i); return ret; } finally { lock.unlock(); } }
synchronized(this) { if(succeeded || failed || finished) return false; if(!corruptMetadata && blockChooser.successCount() < blocksForDecode()) return false; if(tryDecode) return true; tryDecode = true; Math.max(parent.fecCodec.maxMemoryOverheadDecode(blocksForDecode(), checkBlocks), parent.fecCodec.maxMemoryOverheadEncode(blocksForDecode(), checkBlocks)); final int prio = parent.getPriorityClass(); parent.memoryLimitedJobRunner.queueJob(new MemoryLimitedJob(limit) {
parent.maxRetries, parent.cooldownTries, parent.cooldownLength, this, keysFetching, ignoreLastBlock ? dataBlocks - 1 : -1); int minFetched = blocksForDecode(); if(crossCheckBlocks != 0) crossSegmentsByBlock = new SplitFileFetcherCrossSegmentStorage[minFetched]; crossCheckBlocks, writeRetries, parent.checksumLength, parent.persistent); segmentKeyListLength = storedKeysLength(blocksForDecode(), checkBlocks, parent.splitfileSingleCryptoKey != null, parent.checksumLength); this.segmentBlockDataOffset = segmentDataOffset;
/** Write a full set of data blocks to disk and update the metadata accordingly. */ private void writeAllDataBlocks(byte[][] dataBlocks) throws IOException { RAFLock lock = parent.lockRAFOpen(); try { synchronized(this) { assert(dataBlocks.length == blocksForDecode()); for(int i=0;i<dataBlocks.length;i++) { writeDownloadedBlock(i, dataBlocks[i]); blockChooser.onSuccess(i); blocksFetched[i] = (short)i; } succeeded = true; } } finally { lock.unlock(); } }
parent.maxRetries, parent.cooldownTries, parent.cooldownLength, this, keysFetching, ignoreLastBlock ? dataBlocks - 1 : -1); int minFetched = blocksForDecode(); if(crossSegmentCheckBlocks != 0) crossSegmentsByBlock = new SplitFileFetcherCrossSegmentStorage[minFetched]; crossSegmentCheckBlocks, writeRetries, parent.checksumLength, true); segmentKeyListLength = storedKeysLength(blocksForDecode(), checkBlocks, parent.splitfileSingleCryptoKey != null, parent.checksumLength);
if(fetchedCount < blocksForDecode()) { int oldBlocksFetchedCount = blockChooser.successCount(); blockChooser.replaceSuccesses(used); if(fetchedCount < blocksForDecode()) { byte[][] dataBlocks = new byte[blocksForDecode()][]; byte[][] checkBlocks = new byte[this.checkBlocks][]; if(blockNumber < blocksForDecode()) validDataBlocks++; if(blockNumber < dataBlocks.length) maybeBlocks.clear(); maybeBlocks = null; if(validBlocks < blocksForDecode()) { if(validDataBlocks < blocksForDecode()) { if(logMINOR) Logger.minor(this, "Decoding in memory for "+this); parent.fecCodec.decode(dataBlocks, checkBlocks, dataBlocksPresent, checkBlocksPresent, CHKBlock.DATA_LENGTH);
private boolean checkEncodedDataBlocks(byte[][] checkBlocks, boolean[] checkBlocksPresent, SplitFileSegmentKeys keys, boolean capturingBinaryBlob) { for(int i=0;i<checkBlocks.length;i++) { if(checkBlocksPresent[i]) continue; ClientCHK decodeKey = keys.getKey(i+blocksForDecode(), null, false); // Encode it to check whether the key is the same. ClientCHKBlock block; try { block = ClientCHKBlock.encodeSplitfileBlock(checkBlocks[i], decodeKey.getCryptoKey(), decodeKey.getCryptoAlgorithm()); ClientCHK actualKey = block.getClientKey(); if(!actualKey.equals(decodeKey)) { Logger.error(this, "Splitfile check block "+i+" does not encode to expected key for "+this+" for "+parent); return false; } if(capturingBinaryBlob) parent.fetcher.maybeAddToBinaryBlob(block); } catch (CHKEncodeException e) { // Impossible! parent.fail(new FetchException(FetchExceptionMode.INTERNAL_ERROR, "Decoded block could not be encoded")); Logger.error(this, "Impossible: Decoded block could not be encoded"); return false; } } return true; }
continue; if(blockChooser.successCount() >= blocksForDecode()) { if(logMINOR) Logger.minor(this, "Already decoding");