ProcessLock.java
/*
* Decompiled with CFR 0_132.
*
* Could not load the following classes:
* android.text.TextUtils
*/
package org.xutils.common.util;
import android.text.TextUtils;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.xutils.common.util.DoubleKeyValueMap;
import org.xutils.common.util.IOUtil;
import org.xutils.common.util.LogUtil;
import org.xutils.x;
public final class ProcessLock
implements Closeable {
private final String mLockName;
private final FileLock mFileLock;
private final File mFile;
private final Closeable mStream;
private final boolean mWriteMode;
private static final String LOCK_FILE_DIR = "process_lock";
private static final DoubleKeyValueMap<String, Integer, ProcessLock> LOCK_MAP = new DoubleKeyValueMap();
private static final DecimalFormat FORMAT;
private ProcessLock(String lockName, File file, FileLock fileLock, Closeable stream, boolean writeMode) {
this.mLockName = lockName;
this.mFileLock = fileLock;
this.mFile = file;
this.mStream = stream;
this.mWriteMode = writeMode;
}
public static ProcessLock tryLock(String lockName, boolean writeMode) {
return ProcessLock.tryLockInternal(lockName, ProcessLock.customHash(lockName), writeMode);
}
public static ProcessLock tryLock(String lockName, boolean writeMode, long maxWaitTimeMillis) throws InterruptedException {
ProcessLock lock = null;
long expiryTime = System.currentTimeMillis() + maxWaitTimeMillis;
String hash = ProcessLock.customHash(lockName);
while (System.currentTimeMillis() < expiryTime && (lock = ProcessLock.tryLockInternal(lockName, hash, writeMode)) == null) {
try {
Thread.sleep(1L);
}
catch (InterruptedException iex2) {
throw iex2;
}
catch (Throwable iex2) {
}
}
return lock;
}
public boolean isValid() {
return ProcessLock.isValid(this.mFileLock);
}
public void release() {
ProcessLock.release(this.mLockName, this.mFileLock, this.mFile, this.mStream);
}
@Override
public void close() throws IOException {
this.release();
}
private static boolean isValid(FileLock fileLock) {
return fileLock != null && fileLock.isValid();
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
private static void release(String lockName, FileLock fileLock, File file, Closeable stream) {
DoubleKeyValueMap<String, Integer, ProcessLock> doubleKeyValueMap = LOCK_MAP;
synchronized (doubleKeyValueMap) {
if (fileLock != null) {
try {
LOCK_MAP.remove(lockName, fileLock.hashCode());
ConcurrentHashMap<Integer, ProcessLock> locks = LOCK_MAP.get(lockName);
if (locks == null || locks.isEmpty()) {
IOUtil.deleteFileOrDir(file);
}
if (fileLock.channel().isOpen()) {
fileLock.release();
}
}
catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
finally {
IOUtil.closeQuietly(fileLock.channel());
}
}
IOUtil.closeQuietly(stream);
}
}
private static String customHash(String str) {
if (TextUtils.isEmpty((CharSequence)str)) {
return "0";
}
double hash = 0.0;
byte[] bytes = str.getBytes();
for (int i = 0; i < str.length(); ++i) {
hash = (255.0 * hash + (double)bytes[i]) * 0.005;
}
return FORMAT.format(hash);
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
private static ProcessLock tryLockInternal(String lockName, String hash, boolean writeMode) {
DoubleKeyValueMap<String, Integer, ProcessLock> doubleKeyValueMap = LOCK_MAP;
synchronized (doubleKeyValueMap) {
block14 : {
ConcurrentHashMap<Integer, ProcessLock> locks = LOCK_MAP.get(lockName);
if (locks != null && !locks.isEmpty()) {
Iterator<Map.Entry<Integer, ProcessLock>> itr = locks.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry<Integer, ProcessLock> entry = itr.next();
ProcessLock value = entry.getValue();
if (value != null) {
if (!value.isValid()) {
itr.remove();
continue;
}
if (writeMode) {
return null;
}
if (!value.mWriteMode) continue;
return null;
}
itr.remove();
}
}
FileChannel channel = null;
Closeable stream = null;
try {
File file = new File(x.app().getDir(LOCK_FILE_DIR, 0), hash);
if (!file.exists() && !file.createNewFile()) break block14;
if (writeMode) {
FileOutputStream out = new FileOutputStream(file, false);
channel = out.getChannel();
stream = out;
} else {
FileInputStream in = new FileInputStream(file);
channel = in.getChannel();
stream = in;
}
if (channel != null) {
FileLock fileLock = channel.tryLock(0L, Long.MAX_VALUE, !writeMode);
if (ProcessLock.isValid(fileLock)) {
ProcessLock result = new ProcessLock(lockName, file, fileLock, stream, writeMode);
LOCK_MAP.put(lockName, fileLock.hashCode(), result);
return result;
}
ProcessLock.release(lockName, fileLock, file, stream);
break block14;
}
throw new IOException("can not get file channel:" + file.getAbsolutePath());
}
catch (Throwable ignored) {
LogUtil.d("tryLock: " + lockName + ", " + ignored.getMessage());
IOUtil.closeQuietly(stream);
IOUtil.closeQuietly(channel);
}
}
}
return null;
}
public String toString() {
return this.mLockName + ": " + this.mFile.getName();
}
protected void finalize() throws Throwable {
super.finalize();
this.release();
}
static {
File dir = x.app().getDir(LOCK_FILE_DIR, 0);
IOUtil.deleteFileOrDir(dir);
FORMAT = new DecimalFormat("0.##################");
}
}