@Override public boolean run(ClientContext context) { try { storage.failOnDiskError(e); } finally { // Must terminate the request anyway. request.onFailure(new LowLevelPutException(LowLevelPutException.INTERNAL_ERROR, "Disk error", e), context); } return true; } });
/** Called on startup to check which keys we actually have. Does nothing unless the segment * claims to have been encoded already. FIXME consider calling this later on for robustness, * but we would then need to re-encode ... */ public void checkKeys() { synchronized(this) { if(!encoded) return; } try { for(int i=0;i<totalBlockCount;i++) { readKey(i); } } catch (IOException e) { parent.failOnDiskError(e); return; } catch (MissingKeyException e) { // Easy to recover so may as well... Logger.error(this, "Missing key even though segment encoded. Recovering by re-encoding..."); synchronized(this) { encoded = false; } return; } }
@Override public void onEncode(SendableRequestItem token, ClientKey key, ClientContext context) { BlockInsert block = (BlockInsert) token; // Should already be set. This is a sanity check. try { if(storage.hasFinished()) return; block.segment.setKey(block.blockNumber, (ClientCHK) key); } catch (IOException e) { if(storage.hasFinished()) return; // Race condition possible as this is a callback storage.failOnDiskError(e); } }
public void storeStatus() { if(!parent.persistent) return; DataOutputStream dos; try { dos = new DataOutputStream(parent.writeChecksummedTo(parent.crossSegmentStatusOffset(segNo), statusLength)); innerStoreStatus(dos); } catch (IOException e) { Logger.error(this, "Impossible: "+e, e); return; } try { dos.close(); } catch (IOException e) { Logger.error(this, "I/O error writing segment status?: "+e, e); parent.failOnDiskError(e); } }
public void storeStatus(boolean force) { if(!parent.persistent) return; if(parent.hasFinished()) return; try { DataOutputStream dos; synchronized(this) { if(!force && !metadataDirty) return; if(cancelled) return; try { dos = new DataOutputStream(parent.writeChecksummedTo(parent.segmentStatusOffset(segNo), statusLength)); innerStoreStatus(dos); } catch (IOException e) { Logger.error(this, "Impossible: "+e, e); return; } metadataDirty = false; } // Outside the lock is safe since if we fail we will fail the whole splitfile. dos.close(); } catch (IOException e) { Logger.error(this, "I/O error writing segment status?: "+e, e); parent.failOnDiskError(e); } }
/** Called when a block insert succeeds */ public void onInsertedBlock(int blockNo, ClientCHK key) { try { if(parent.hasFinished()) return; this.setKey(blockNo, key); if(blockChooser.onSuccess(blockNo)) parent.callback.onInsertedBlock(); lazyWriteMetadata(); } catch (IOException e) { if(parent.hasFinished()) return; // Race condition possible as this is a callback parent.failOnDiskError(e); } }
/** Encode a segment. Much simpler than fetcher! */ private void innerEncode(MemoryLimitedChunk chunk) { try { synchronized(this) { if(cancelled) return; } if(logMINOR) Logger.minor(this, "Encoding "+this); byte[][] dataBlocks = readDataBlocks(); byte[][] checkBlocks = new byte[crossCheckBlockCount][]; for(int i=0;i<checkBlocks.length;i++) checkBlocks[i] = new byte[CHKBlock.DATA_LENGTH]; if(dataBlocks == null || checkBlocks == null) return; // Failed with disk error. parent.codec.encode(dataBlocks, checkBlocks, new boolean[checkBlocks.length], CHKBlock.DATA_LENGTH); writeCheckBlocks(checkBlocks); synchronized(this) { encoded = true; } if(logMINOR) Logger.minor(this, "Finished encoding "+this); storeStatus(); } catch (IOException e) { parent.failOnDiskError(e); } }
parent.failOnDiskError(e); } catch (Throwable t) { Logger.error(this, "Failed: "+t, t);
} catch (IOException e1) { if(parent.hasFinished()) return; // Race condition possible as this is a callback parent.failOnDiskError(e1); return;