LruDiskCache.java

/*
 * Decompiled with CFR 0_132.
 * 
 * Could not load the following classes:
 *  android.text.TextUtils
 */
package org.xutils.cache;

import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;
import org.xutils.DbManager;
import org.xutils.cache.DiskCacheEntity;
import org.xutils.cache.DiskCacheFile;
import org.xutils.common.task.PriorityExecutor;
import org.xutils.common.util.FileUtil;
import org.xutils.common.util.IOUtil;
import org.xutils.common.util.LogUtil;
import org.xutils.common.util.MD5;
import org.xutils.common.util.ProcessLock;
import org.xutils.config.DbConfigs;
import org.xutils.db.Selector;
import org.xutils.db.sqlite.WhereBuilder;
import org.xutils.ex.DbException;
import org.xutils.ex.FileLockedException;
import org.xutils.x;

public final class LruDiskCache {
    private static final HashMap<String, LruDiskCache> DISK_CACHE_MAP = new HashMap(5);
    private static final int LIMIT_COUNT = 5000;
    private static final long LIMIT_SIZE = 104857600L;
    private static final int LOCK_WAIT = 3000;
    private static final String CACHE_DIR_NAME = "xUtils_cache";
    private static final String TEMP_FILE_SUFFIX = ".tmp";
    private boolean available = false;
    private final DbManager cacheDb = x.getDb(DbConfigs.HTTP.getConfig());
    private File cacheDir;
    private long diskCacheSize = 104857600L;
    private final Executor trimExecutor = new PriorityExecutor(1, true);
    private long lastTrimTime = 0L;
    private static final long TRIM_TIME_SPAN = 1000L;

    public static synchronized LruDiskCache getDiskCache(String dirName) {
        LruDiskCache cache;
        if (TextUtils.isEmpty((CharSequence)dirName)) {
            dirName = CACHE_DIR_NAME;
        }
        if ((cache = DISK_CACHE_MAP.get(dirName)) == null) {
            cache = new LruDiskCache(dirName);
            DISK_CACHE_MAP.put(dirName, cache);
        }
        return cache;
    }

    private LruDiskCache(String dirName) {
        this.cacheDir = FileUtil.getCacheDir(dirName);
        if (this.cacheDir != null && (this.cacheDir.exists() || this.cacheDir.mkdirs())) {
            this.available = true;
        }
        this.deleteNoIndexFiles();
    }

    public LruDiskCache setMaxSize(long maxSize) {
        if (maxSize > 0L) {
            long diskFreeSize = FileUtil.getDiskAvailableSize();
            this.diskCacheSize = diskFreeSize > maxSize ? maxSize : diskFreeSize;
        }
        return this;
    }

    public DiskCacheEntity get(String key) {
        if (!this.available || TextUtils.isEmpty((CharSequence)key)) {
            return null;
        }
        DiskCacheEntity result = null;
        try {
            result = this.cacheDb.selector(DiskCacheEntity.class).where("key", "=", key).findFirst();
        }
        catch (Throwable ex) {
            LogUtil.e(ex.getMessage(), ex);
        }
        if (result != null) {
            if (result.getExpires() < System.currentTimeMillis()) {
                return null;
            }
            final DiskCacheEntity finalResult = result;
            this.trimExecutor.execute(new Runnable(){

                @Override
                public void run() {
                    finalResult.setHits(finalResult.getHits() + 1L);
                    finalResult.setLastAccess(System.currentTimeMillis());
                    try {
                        LruDiskCache.this.cacheDb.update(finalResult, "hits", "lastAccess");
                    }
                    catch (Throwable ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                }
            });
        }
        return result;
    }

    public void put(DiskCacheEntity entity) {
        if (!this.available || entity == null || TextUtils.isEmpty((CharSequence)entity.getTextContent()) || entity.getExpires() < System.currentTimeMillis()) {
            return;
        }
        try {
            this.cacheDb.replace(entity);
        }
        catch (DbException ex) {
            LogUtil.e(ex.getMessage(), ex);
        }
        this.trimSize();
    }

    public DiskCacheFile getDiskCacheFile(String key) throws InterruptedException {
        ProcessLock processLock;
        if (!this.available || TextUtils.isEmpty((CharSequence)key)) {
            return null;
        }
        DiskCacheFile result = null;
        DiskCacheEntity entity = this.get(key);
        if (entity != null && new File(entity.getPath()).exists() && (processLock = ProcessLock.tryLock(entity.getPath(), false, 3000L)) != null && processLock.isValid() && !(result = new DiskCacheFile(entity, entity.getPath(), processLock)).exists()) {
            try {
                this.cacheDb.delete(entity);
            }
            catch (DbException ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
            result = null;
        }
        return result;
    }

    public DiskCacheFile createDiskCacheFile(DiskCacheEntity entity) throws IOException {
        if (!this.available || entity == null) {
            return null;
        }
        DiskCacheFile result = null;
        entity.setPath(new File(this.cacheDir, MD5.md5(entity.getKey())).getAbsolutePath());
        String tempFilePath = entity.getPath() + TEMP_FILE_SUFFIX;
        ProcessLock processLock = ProcessLock.tryLock(tempFilePath, true);
        if (processLock != null && processLock.isValid()) {
            result = new DiskCacheFile(entity, tempFilePath, processLock);
            if (!result.getParentFile().exists()) {
                result.mkdirs();
            }
        } else {
            throw new FileLockedException(entity.getPath());
        }
        return result;
    }

    public void clearCacheFiles() {
        IOUtil.deleteFileOrDir(this.cacheDir);
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     * Enabled force condition propagation
     * Lifted jumps to return sites
     */
    DiskCacheFile commitDiskCacheFile(DiskCacheFile cacheFile) throws IOException {
        DiskCacheFile result;
        block11 : {
            if (cacheFile != null && cacheFile.length() < 1L) {
                IOUtil.closeQuietly(cacheFile);
                return null;
            }
            if (!this.available) return null;
            if (cacheFile == null) {
                return null;
            }
            result = null;
            DiskCacheEntity cacheEntity = cacheFile.cacheEntity;
            if (!cacheFile.getName().endsWith(TEMP_FILE_SUFFIX)) return cacheFile;
            ProcessLock processLock = null;
            DiskCacheFile destFile = null;
            try {
                String destPath = cacheEntity.getPath();
                processLock = ProcessLock.tryLock(destPath, true, 3000L);
                if (processLock == null) throw new FileLockedException(destPath);
                if (!processLock.isValid()) throw new FileLockedException(destPath);
                destFile = new DiskCacheFile(cacheEntity, destPath, processLock);
                if (!cacheFile.renameTo(destFile)) throw new IOException("rename:" + cacheFile.getAbsolutePath());
                try {
                    result = destFile;
                    this.cacheDb.replace(cacheEntity);
                }
                catch (DbException ex) {
                    LogUtil.e(ex.getMessage(), ex);
                }
                this.trimSize();
                if (result != null) break block11;
                result = cacheFile;
            }
            catch (InterruptedException ex) {
                result = cacheFile;
                LogUtil.e(ex.getMessage(), ex);
                return result;
            }
            finally {
                if (result == null) {
                    result = cacheFile;
                    IOUtil.closeQuietly(destFile);
                    IOUtil.closeQuietly(processLock);
                    IOUtil.deleteFileOrDir(destFile);
                } else {
                    IOUtil.closeQuietly(cacheFile);
                    IOUtil.deleteFileOrDir(cacheFile);
                }
            }
            IOUtil.closeQuietly(destFile);
            IOUtil.closeQuietly(processLock);
            IOUtil.deleteFileOrDir(destFile);
            return result;
        }
        IOUtil.closeQuietly(cacheFile);
        IOUtil.deleteFileOrDir(cacheFile);
        return result;
    }

    private void trimSize() {
        this.trimExecutor.execute(new Runnable(){

            @Override
            public void run() {
                if (LruDiskCache.this.available) {
                    long current = System.currentTimeMillis();
                    if (current - LruDiskCache.this.lastTrimTime < 1000L) {
                        return;
                    }
                    LruDiskCache.this.lastTrimTime = current;
                    LruDiskCache.this.deleteExpiry();
                    try {
                        Object rmList;
                        int count = (int)LruDiskCache.this.cacheDb.selector(DiskCacheEntity.class).count();
                        if (count > 5010 && (rmList = LruDiskCache.this.cacheDb.selector(DiskCacheEntity.class).orderBy("lastAccess").orderBy("hits").limit(count - 5000).offset(0).findAll()) != null && rmList.size() > 0) {
                            Iterator<DiskCacheEntity> iterator = rmList.iterator();
                            while (iterator.hasNext()) {
                                DiskCacheEntity entity = iterator.next();
                                try {
                                    LruDiskCache.this.cacheDb.delete(entity);
                                    String path = entity.getPath();
                                    if (TextUtils.isEmpty((CharSequence)path)) continue;
                                    LruDiskCache.this.deleteFileWithLock(path);
                                    LruDiskCache.this.deleteFileWithLock(path + LruDiskCache.TEMP_FILE_SUFFIX);
                                }
                                catch (DbException ex) {
                                    LogUtil.e(ex.getMessage(), ex);
                                }
                            }
                        }
                    }
                    catch (DbException ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                    try {
                        while (FileUtil.getFileOrDirSize(LruDiskCache.this.cacheDir) > LruDiskCache.this.diskCacheSize) {
                            List<DiskCacheEntity> rmList = LruDiskCache.this.cacheDb.selector(DiskCacheEntity.class).orderBy("lastAccess").orderBy("hits").limit(10).offset(0).findAll();
                            if (rmList == null || rmList.size() <= 0) continue;
                            for (DiskCacheEntity entity : rmList) {
                                try {
                                    LruDiskCache.this.cacheDb.delete(entity);
                                    String path = entity.getPath();
                                    if (TextUtils.isEmpty((CharSequence)path)) continue;
                                    LruDiskCache.this.deleteFileWithLock(path);
                                    LruDiskCache.this.deleteFileWithLock(path + LruDiskCache.TEMP_FILE_SUFFIX);
                                }
                                catch (DbException ex) {
                                    LogUtil.e(ex.getMessage(), ex);
                                }
                            }
                        }
                    }
                    catch (DbException ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                }
            }
        });
    }

    private void deleteExpiry() {
        try {
            WhereBuilder whereBuilder = WhereBuilder.b("expires", "<", System.currentTimeMillis());
            List<DiskCacheEntity> rmList = this.cacheDb.selector(DiskCacheEntity.class).where(whereBuilder).findAll();
            this.cacheDb.delete(DiskCacheEntity.class, whereBuilder);
            if (rmList != null && rmList.size() > 0) {
                for (DiskCacheEntity entity : rmList) {
                    String path = entity.getPath();
                    if (TextUtils.isEmpty((CharSequence)path)) continue;
                    this.deleteFileWithLock(path);
                }
            }
        }
        catch (Throwable ex) {
            LogUtil.e(ex.getMessage(), ex);
        }
    }

    private void deleteNoIndexFiles() {
        this.trimExecutor.execute(new Runnable(){

            @Override
            public void run() {
                if (LruDiskCache.this.available) {
                    try {
                        File[] fileList = LruDiskCache.this.cacheDir.listFiles();
                        if (fileList != null) {
                            for (File file : fileList) {
                                try {
                                    long count = LruDiskCache.this.cacheDb.selector(DiskCacheEntity.class).where("path", "=", file.getAbsolutePath()).count();
                                    if (count >= 1L) continue;
                                    IOUtil.deleteFileOrDir(file);
                                }
                                catch (Throwable ex) {
                                    LogUtil.e(ex.getMessage(), ex);
                                }
                            }
                        }
                    }
                    catch (Throwable ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                }
            }
        });
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private boolean deleteFileWithLock(String path) {
        ProcessLock processLock = null;
        try {
            processLock = ProcessLock.tryLock(path, true);
            if (processLock != null && processLock.isValid()) {
                File file = new File(path);
                boolean bl = IOUtil.deleteFileOrDir(file);
                return bl;
            }
        }
        finally {
            IOUtil.closeQuietly(processLock);
        }
        return false;
    }

}