private void initIndexContent(DataInputStream in) throws IOException { try { while (true) { char flag = (char) in.readByte(); String key = in.readUTF(); if (flag == DELETE) { lruEntries.remove(key); return; } DiskLruCacheEntry entry = lruEntries.get(key); if (entry == null) { entry = new DiskLruCacheEntry(this, key); lruEntries.put(key, entry); } switch (flag) { case CLEAN: entry.size = in.readInt(); break; case UPDATE: case WRITE: entry.clean(); // reset to clean or deleted break; case READ: // this work was already done by calling lruEntries.get() break; default: throw new IOException("unexpected index line: " + flag + ":" + key); } } } catch (EOFException e) { // end } }
/* (non-Javadoc) * @see org.xidea.android.impl.io.DiskLruCacheIF#close() */ @Override public synchronized void close() throws IOException { if (indexWriter == null) { return; // already closed } for (final DiskLruCacheEntry entry : new ArrayList<DiskLruCacheEntry>(lruEntries.values())) { entry.clean(); } trimToSize(); indexWriter.close(); indexWriter = null; }
@Override public synchronized InputStream getWritebackFilter( InputStream in, String key, int pos, final Callback<Boolean> complete) throws IOException { validate(key); DiskLruCacheEntry entry = lruEntries.get(key); if (entry == null) { entry = new DiskLruCacheEntry(this, key); lruEntries.put(key, entry); } boolean readable = entry.isReadable(); InputStream wrapper = entry.getWritebackFilter(in, pos, complete); // flush the index before creating files to prevent file leaks if (wrapper != null) { writeIndex(readable ? UPDATE : WRITE, entry); return wrapper; // } return in; }
@Override public synchronized InputStream get(String key) throws IOException { validate(key); final DiskLruCacheEntry entry = lruEntries.get(key); if (entry != null) { InputStream in = entry.newInputStream(); if (in != null) { redundantOpCount++; writeIndex(READ, entry); // .flush(); do not flush immediately for // performance if (indexRebuildRequired()) { executorService.submit(cleanupCallable); } } return in; } return null; }
/** * Creates a new index that omits redundant information. This replaces the current index if it * exists. */ private synchronized void rebuildIndex() throws IOException { if (indexWriter != null) { indexWriter.close(); } File indexFileTmp = new File(directory, INDEX_FILE + ".tmp"); indexWriter = new DataOutputStream(new FileOutputStream(indexFileTmp)); indexWriter.writeUTF(MAGIC); indexWriter.writeByte('\n'); for (final DiskLruCacheEntry entry : lruEntries.values()) { boolean readable = entry.isReadable(); writeIndex( entry.isWriting() ? (readable ? UPDATE : WRITE) : (readable ? CLEAN : DELETE), entry); } indexWriter.close(); File indexFile = new File(directory, INDEX_FILE); indexFileTmp.renameTo(indexFile); indexWriter = new DataOutputStream(new FileOutputStream(indexFile, true)); }
/* (non-Javadoc) * @see org.xidea.android.impl.io.DiskLruCacheIF#remove(java.lang.String) */ @Override public synchronized boolean remove(String key) throws IOException { validate(key); final DiskLruCacheEntry entry = lruEntries.get(key); if (entry == null) { return false; } int s = entry.size; entry.delete(); size -= s; lruEntries.remove(key); redundantOpCount++; writeIndex(DELETE, entry); if (indexRebuildRequired()) { executorService.submit(cleanupCallable); } return true; }
private void initIndex(DataInputStream in) throws IOException { try { final String magic = in.readUTF(); final char blank = (char) in.readByte(); if (!MAGIC.equals(magic) || '\n' != blank) { throw new IOException("unexpected index header: [" + magic + ", " + blank + "]"); } initIndexContent(in); for (final Iterator<DiskLruCacheEntry> i = lruEntries.values().iterator(); i.hasNext(); ) { final DiskLruCacheEntry entry = i.next(); if (entry.isReadable()) { size += entry.size; } else { entry.delete(); i.remove(); } } } finally { IOUtil.closeQuietly(in); } }