private void recoverTranslog(CommitPoint commitPoint, ImmutableMap<String, BlobMetaData> blobs) throws IndexShardGatewayRecoveryException { if (commitPoint.translogFiles().isEmpty()) { // no translog files, bail indexShard.start("post recovery from gateway, no translog"); return; } try { indexShard.performRecoveryPrepareForTranslog(); final AtomicReference<Throwable> failure = new AtomicReference<Throwable>(); final CountDownLatch latch = new CountDownLatch(1); final Iterator<CommitPoint.FileInfo> transIt = commitPoint.translogFiles().iterator(); blobContainer.readBlob( transIt.next().name(), new BlobContainer.ReadBlobListener() { FastByteArrayOutputStream bos = new FastByteArrayOutputStream(); boolean ignore = false; @Override public synchronized void onPartial(byte[] data, int offset, int size) throws IOException { if (ignore) { return; } bos.write(data, offset, size); // if we don't have enough to read the header size of the first translog, bail and // wait for the next one if (bos.size() < 4) { return; } BytesStreamInput si = new BytesStreamInput(bos.unsafeByteArray(), 0, bos.size()); int position; while (true) { try { position = si.position(); if (position + 4 > bos.size()) { break; } int opSize = si.readInt(); int curPos = si.position(); if ((si.position() + opSize) > bos.size()) { break; } Translog.Operation operation = TranslogStreams.readTranslogOperation(si); if ((si.position() - curPos) != opSize) { logger.warn( "mismatch in size, expected [{}], got [{}]", opSize, si.position() - curPos); } recoveryStatus.translog().addTranslogOperations(1); indexShard.performRecoveryOperation(operation); if (si.position() >= bos.size()) { position = si.position(); break; } } catch (Exception e) { logger.warn( "failed to retrieve translog after [{}] operations, ignoring the rest, considered corrupted", e, recoveryStatus.translog().currentTranslogOperations()); ignore = true; latch.countDown(); return; } } FastByteArrayOutputStream newBos = new FastByteArrayOutputStream(); int leftOver = bos.size() - position; if (leftOver > 0) { newBos.write(bos.unsafeByteArray(), position, leftOver); } bos = newBos; } @Override public synchronized void onCompleted() { if (ignore) { return; } if (!transIt.hasNext()) { latch.countDown(); return; } blobContainer.readBlob(transIt.next().name(), this); } @Override public void onFailure(Throwable t) { failure.set(t); latch.countDown(); } }); latch.await(); if (failure.get() != null) { throw failure.get(); } indexShard.performRecoveryFinalization(true); } catch (Throwable e) { throw new IndexShardGatewayRecoveryException(shardId, "Failed to recover translog", e); } }