/** Pulls bitmap from diskcache */ private @Nullable ParcelFileDescriptor createPipe(final ArtInfo artInfo) { final byte[] bytes = mL2Cache.getBytes(artInfo.cacheKey()); if (bytes == null) { return null; } try { final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); final OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]); final ParcelFileDescriptor in = pipe[0]; final Scheduler.Worker worker = mScheduler.createWorker(); worker.schedule( new Action0() { @Override public void call() { try { IOUtils.write(bytes, out); out.flush(); } catch (IOException e) { Timber.w("createPipe(e=%s) for %s", e.getMessage(), artInfo); } finally { IOUtils.closeQuietly(out); worker.unsubscribe(); } } }); return in; } catch (IOException e) { Timber.e(e, "createPipe() for %s", artInfo); return null; } }
/** * Eagerly creates a pipe, then blocks on a background thread while we wait for the fetcher to * return the bitmap, simply closing the pipe if no art was found */ private @Nullable ParcelFileDescriptor createPipe2(final ArtInfo artInfo) { try { final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); final OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]); final ParcelFileDescriptor in = pipe[0]; final Scheduler.Worker worker = mScheduler.createWorker(); worker.schedule( new Action0() { @Override public void call() { OptionalBitmap bitmap = null; ArtworkFetcherService.Connection binder = null; try { // make a new request and wait for it to come in. binder = ArtworkFetcherService.bindService(getContext()); final BlockingQueue<OptionalBitmap> queue = new LinkedBlockingQueue<>(1); final CompletionListener listener = new CompletionListener() { @Override public void onError(Throwable e) { Timber.w("onError(%s) for %s", e.getMessage(), artInfo); queue.offer(new OptionalBitmap(null)); } @Override public void onNext(Bitmap o) { queue.offer(new OptionalBitmap(o)); } }; if (!binder.getService().newRequest(artInfo, listener)) { throw new InterruptedException("Enqueue failed"); } bitmap = queue.take(); if (bitmap.hasBitmap()) { byte[] bytes = mL2Cache.bitmapToBytes(bitmap.getBitmap()); IOUtils.write(bytes, out); out.flush(); } } catch (InterruptedException | IOException e) { Timber.w("createPipe2(e=%s) for %s", e.getMessage(), artInfo); if (binder != null) { binder.getService().cancelRequest(artInfo); } } finally { if (bitmap != null) bitmap.recycle(); IOUtils.closeQuietly(binder); IOUtils.closeQuietly(out); worker.unsubscribe(); } } }); return in; } catch (IOException e) { Timber.e(e, "createPipe2() for %s", artInfo); return null; } }
/** * Publishes a response with the attached observable. * * @param response the response to publish. * @param observable pushing into the event sink. */ protected void publishResponse( final CouchbaseResponse response, final Subject<CouchbaseResponse, CouchbaseResponse> observable) { if (response.status() != ResponseStatus.RETRY && observable != null) { final Scheduler.Worker worker = env().scheduler().createWorker(); worker.schedule( new Action0() { @Override public void call() { try { observable.onNext(response); observable.onCompleted(); } catch (Exception ex) { LOGGER.warn("Caught exception while onNext on observable", ex); observable.onError(ex); } finally { worker.unsubscribe(); } } }); } else { responseBuffer.publishEvent(ResponseHandler.RESPONSE_TRANSLATOR, response, observable); } }