- 28,932 files - Full Java source code - Smali files - Resources Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1687 lines
55 KiB
Java
1687 lines
55 KiB
Java
package com.mbridge.msdk.foundation.tools;
|
|
|
|
import com.mbridge.msdk.foundation.tools.g;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.RandomAccessFile;
|
|
import java.nio.ByteOrder;
|
|
import java.nio.MappedByteBuffer;
|
|
import java.nio.channels.FileChannel;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.Executor;
|
|
import kotlin.jvm.internal.ByteCompanionObject;
|
|
|
|
/* loaded from: classes4.dex */
|
|
public class FastKV {
|
|
static final int ASYNC_BLOCKING = 1;
|
|
private static final String A_SUFFIX = ".kva";
|
|
private static final int BASE_GC_BYTES_THRESHOLD = 4096;
|
|
private static final int BASE_GC_KEYS_THRESHOLD = 80;
|
|
private static final String BOTH_FILES_ERROR = "both files error";
|
|
private static final String B_SUFFIX = ".kvb";
|
|
private static final String C_SUFFIX = ".kvc";
|
|
private static final int DATA_SIZE_LIMIT = 536870912;
|
|
private static final int DATA_START = 12;
|
|
private static final int DOUBLE_LIMIT;
|
|
private static final byte[] EMPTY_ARRAY = new byte[0];
|
|
static final String GC_FINISH = "gc finish";
|
|
private static final int INTERNAL_LIMIT = 2048;
|
|
private static final String MAP_FAILED = "map failed";
|
|
static final int NON_BLOCKING = 0;
|
|
private static final String OPEN_FILE_FAILED = "open file failed";
|
|
private static final int PAGE_SIZE;
|
|
private static final String PARSE_DATA_FAILED = "parse dara failed";
|
|
static final int SYNC_BLOCKING = 2;
|
|
private static final String TEMP_SUFFIX = ".tmp";
|
|
static final String TRUNCATE_FINISH = "truncate finish";
|
|
private static final int TRUNCATE_THRESHOLD;
|
|
private static final int[] TYPE_SIZE;
|
|
private MappedByteBuffer aBuffer;
|
|
private FileChannel aChannel;
|
|
private MappedByteBuffer bBuffer;
|
|
private FileChannel bChannel;
|
|
private long checksum;
|
|
private int dataEnd;
|
|
private final Map<String, a> encoderMap;
|
|
private q fastBuffer;
|
|
private int invalidBytes;
|
|
private final String name;
|
|
private final String path;
|
|
private int removeStart;
|
|
private boolean sizeChanged;
|
|
private String tempExternalName;
|
|
private int updateSize;
|
|
private int updateStart;
|
|
private int writingMode;
|
|
private final Map<String, g.b> data = new HashMap();
|
|
private final Executor executor = new t();
|
|
private final ArrayList<c> invalids = new ArrayList<>();
|
|
private final b logger = r.b;
|
|
private boolean autoCommit = true;
|
|
|
|
public interface a<T> {
|
|
T a(byte[] bArr, int i, int i2);
|
|
|
|
String a();
|
|
|
|
byte[] a(T t);
|
|
}
|
|
|
|
public interface b {
|
|
void a(String str, Exception exc);
|
|
|
|
void a(String str, String str2);
|
|
|
|
void b(String str, Exception exc);
|
|
}
|
|
|
|
private int bytesThreshold() {
|
|
int i = this.dataEnd;
|
|
if (i <= 16384) {
|
|
return 4096;
|
|
}
|
|
return i <= 65536 ? 8192 : 16384;
|
|
}
|
|
|
|
private long shiftCheckSum(long j, int i) {
|
|
int i2 = (i & 7) << 3;
|
|
return (j >>> (64 - i2)) | (j << i2);
|
|
}
|
|
|
|
static {
|
|
int a2 = ar.a();
|
|
PAGE_SIZE = a2;
|
|
int max = Math.max(a2 << 1, 16384);
|
|
DOUBLE_LIMIT = max;
|
|
TRUNCATE_THRESHOLD = max << 1;
|
|
TYPE_SIZE = new int[]{0, 1, 4, 4, 8, 8};
|
|
}
|
|
|
|
public FastKV(String str, String str2, a[] aVarArr, int i) {
|
|
this.path = str;
|
|
this.name = str2;
|
|
this.writingMode = i;
|
|
HashMap hashMap = new HashMap();
|
|
hashMap.put("StringSet", ao.a);
|
|
if (aVarArr != null && aVarArr.length > 0) {
|
|
for (a aVar : aVarArr) {
|
|
String a2 = aVar.a();
|
|
if (hashMap.containsKey(a2)) {
|
|
error("duplicate encoder tag:" + a2);
|
|
} else {
|
|
hashMap.put(a2, aVar);
|
|
}
|
|
}
|
|
}
|
|
this.encoderMap = hashMap;
|
|
loadData();
|
|
}
|
|
|
|
private void addObject(String str, Object obj, byte[] bArr, byte b2) {
|
|
Object obj2;
|
|
int length;
|
|
g.b hVar;
|
|
int saveArray = saveArray(str, bArr, b2);
|
|
if (saveArray != 0) {
|
|
String str2 = this.tempExternalName;
|
|
boolean z = str2 != null;
|
|
if (z) {
|
|
this.tempExternalName = null;
|
|
length = 32;
|
|
obj2 = str2;
|
|
} else {
|
|
obj2 = obj;
|
|
length = bArr.length;
|
|
}
|
|
if (b2 == 6) {
|
|
hVar = new g.i(this.updateStart, saveArray, (String) obj2, length, z);
|
|
} else if (b2 == 7) {
|
|
hVar = new g.a(this.updateStart, saveArray, obj2, length, z);
|
|
} else {
|
|
hVar = new g.h(this.updateStart, saveArray, obj2, length, z);
|
|
}
|
|
this.data.put(str, hVar);
|
|
updateChange();
|
|
}
|
|
}
|
|
|
|
private void addOrUpdate(String str, Object obj, byte[] bArr, g.j jVar, byte b2) {
|
|
if (jVar == null) {
|
|
addObject(str, obj, bArr, b2);
|
|
} else if (jVar.b || jVar.e != bArr.length) {
|
|
updateObject(str, obj, bArr, jVar);
|
|
} else {
|
|
updateBytes(jVar.a, bArr);
|
|
jVar.d = obj;
|
|
}
|
|
checkIfCommit();
|
|
}
|
|
|
|
private void checkGC() {
|
|
if (this.invalidBytes < (bytesThreshold() << 1)) {
|
|
if (this.invalids.size() < (this.dataEnd < 16384 ? 80 : 160)) {
|
|
return;
|
|
}
|
|
}
|
|
gc(0);
|
|
}
|
|
|
|
private void checkIfCommit() {
|
|
if (this.writingMode == 0 || !this.autoCommit) {
|
|
return;
|
|
}
|
|
commitToCFile();
|
|
}
|
|
|
|
private void checkKey(String str) {
|
|
if (str == null || str.isEmpty()) {
|
|
throw new IllegalArgumentException("key is empty");
|
|
}
|
|
}
|
|
|
|
private void checkKeySize(int i) {
|
|
if (i > 255) {
|
|
throw new IllegalArgumentException("key's length must less than 256");
|
|
}
|
|
}
|
|
|
|
private void checkValueSize(int i, boolean z) {
|
|
if (z) {
|
|
if (i != 32) {
|
|
throw new IllegalStateException("name size not match");
|
|
}
|
|
} else if (i < 0 || i >= 2048) {
|
|
throw new IllegalStateException("value size out of bound");
|
|
}
|
|
}
|
|
|
|
public synchronized void clear() {
|
|
resetData();
|
|
if (this.writingMode != 0) {
|
|
deleteCFiles();
|
|
}
|
|
}
|
|
|
|
private void resetData() {
|
|
if (this.writingMode == 0) {
|
|
try {
|
|
resetBuffer(this.aBuffer);
|
|
resetBuffer(this.bBuffer);
|
|
} catch (IOException unused) {
|
|
toBlockingMode();
|
|
}
|
|
}
|
|
clearData();
|
|
ar.a(new File(this.path + this.name));
|
|
}
|
|
|
|
private void deleteCFiles() {
|
|
try {
|
|
ar.a(new File(this.path, this.name + C_SUFFIX));
|
|
ar.a(new File(this.path, this.name + TEMP_SUFFIX));
|
|
} catch (Exception e) {
|
|
error(e);
|
|
}
|
|
}
|
|
|
|
private void resetBuffer(MappedByteBuffer mappedByteBuffer) throws IOException {
|
|
int capacity = mappedByteBuffer.capacity();
|
|
int i = PAGE_SIZE;
|
|
if (capacity != i) {
|
|
FileChannel fileChannel = mappedByteBuffer == this.aBuffer ? this.aChannel : this.bChannel;
|
|
fileChannel.truncate(i);
|
|
MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, i);
|
|
map.order(ByteOrder.LITTLE_ENDIAN);
|
|
if (mappedByteBuffer == this.aBuffer) {
|
|
this.aBuffer = map;
|
|
} else {
|
|
this.bBuffer = map;
|
|
}
|
|
mappedByteBuffer = map;
|
|
}
|
|
mappedByteBuffer.putInt(0, 0);
|
|
mappedByteBuffer.putLong(4, 0L);
|
|
}
|
|
|
|
private void toBlockingMode() {
|
|
this.writingMode = 1;
|
|
ar.a(this.aChannel);
|
|
ar.a(this.bChannel);
|
|
this.aChannel = null;
|
|
this.bChannel = null;
|
|
this.aBuffer = null;
|
|
this.bBuffer = null;
|
|
}
|
|
|
|
private void clearData() {
|
|
this.dataEnd = 12;
|
|
this.checksum = 0L;
|
|
clearInvalid();
|
|
this.data.clear();
|
|
q qVar = this.fastBuffer;
|
|
if (qVar == null || qVar.a.length != PAGE_SIZE) {
|
|
this.fastBuffer = new q(PAGE_SIZE);
|
|
} else {
|
|
qVar.b(0, 0);
|
|
this.fastBuffer.a(4, 0L);
|
|
}
|
|
}
|
|
|
|
private void error(Exception exc) {
|
|
b bVar = this.logger;
|
|
if (bVar != null) {
|
|
bVar.a(this.name, exc);
|
|
}
|
|
}
|
|
|
|
private void clearInvalid() {
|
|
this.invalidBytes = 0;
|
|
this.invalids.clear();
|
|
}
|
|
|
|
public synchronized boolean commit() {
|
|
this.autoCommit = true;
|
|
return commitToCFile();
|
|
}
|
|
|
|
private boolean commitToCFile() {
|
|
int i = this.writingMode;
|
|
if (i == 1) {
|
|
this.executor.execute(new Runnable() { // from class: com.mbridge.msdk.foundation.tools.FastKV.1
|
|
@Override // java.lang.Runnable
|
|
public final void run() {
|
|
FastKV.this.writeToCFile();
|
|
}
|
|
});
|
|
} else if (i == 2) {
|
|
return writeToCFile();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* JADX INFO: Access modifiers changed from: private */
|
|
public synchronized boolean writeToCFile() {
|
|
try {
|
|
try {
|
|
File file = new File(this.path, this.name + TEMP_SUFFIX);
|
|
if (ar.c(file)) {
|
|
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
|
randomAccessFile.setLength(this.dataEnd);
|
|
randomAccessFile.write(this.fastBuffer.a, 0, this.dataEnd);
|
|
randomAccessFile.close();
|
|
File file2 = new File(this.path, this.name + C_SUFFIX);
|
|
if (file2.exists()) {
|
|
if (file2.delete()) {
|
|
}
|
|
}
|
|
if (file.renameTo(file2)) {
|
|
return true;
|
|
}
|
|
warning(new Exception("rename failed"));
|
|
}
|
|
} catch (Exception e) {
|
|
error(e);
|
|
}
|
|
return false;
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void warning(Exception exc) {
|
|
b bVar = this.logger;
|
|
if (bVar != null) {
|
|
bVar.b(this.name, exc);
|
|
}
|
|
}
|
|
|
|
public synchronized boolean contains(String str) {
|
|
return this.data.containsKey(str);
|
|
}
|
|
|
|
private void copyBuffer(MappedByteBuffer mappedByteBuffer, MappedByteBuffer mappedByteBuffer2, int i) {
|
|
if (mappedByteBuffer.capacity() != mappedByteBuffer2.capacity()) {
|
|
try {
|
|
MappedByteBuffer map = (mappedByteBuffer2 == this.bBuffer ? this.bChannel : this.aChannel).map(FileChannel.MapMode.READ_WRITE, 0L, mappedByteBuffer.capacity());
|
|
map.order(ByteOrder.LITTLE_ENDIAN);
|
|
if (mappedByteBuffer2 == this.bBuffer) {
|
|
this.bBuffer = map;
|
|
} else {
|
|
this.aBuffer = map;
|
|
}
|
|
mappedByteBuffer2 = map;
|
|
} catch (IOException e) {
|
|
error(e);
|
|
toBlockingMode();
|
|
return;
|
|
}
|
|
}
|
|
mappedByteBuffer.rewind();
|
|
mappedByteBuffer2.rewind();
|
|
mappedByteBuffer.limit(i);
|
|
mappedByteBuffer2.put(mappedByteBuffer);
|
|
mappedByteBuffer.limit(mappedByteBuffer.capacity());
|
|
}
|
|
|
|
private void countInvalid(int i, int i2) {
|
|
this.invalidBytes += i2 - i;
|
|
this.invalids.add(new c(i, i2));
|
|
}
|
|
|
|
public synchronized void disableAutoCommit() {
|
|
this.autoCommit = false;
|
|
}
|
|
|
|
private void ensureSize(int i) {
|
|
int length = this.fastBuffer.a.length;
|
|
int i2 = this.dataEnd + i;
|
|
if (i2 >= length) {
|
|
int i3 = this.invalidBytes;
|
|
if (i3 > i && i3 > bytesThreshold()) {
|
|
gc(i);
|
|
return;
|
|
}
|
|
int newCapacity = getNewCapacity(length, i2);
|
|
byte[] bArr = new byte[newCapacity];
|
|
System.arraycopy(this.fastBuffer.a, 0, bArr, 0, this.dataEnd);
|
|
this.fastBuffer.a = bArr;
|
|
if (this.writingMode == 0) {
|
|
try {
|
|
FileChannel fileChannel = this.aChannel;
|
|
FileChannel.MapMode mapMode = FileChannel.MapMode.READ_WRITE;
|
|
long j = newCapacity;
|
|
MappedByteBuffer map = fileChannel.map(mapMode, 0L, j);
|
|
this.aBuffer = map;
|
|
ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
|
|
map.order(byteOrder);
|
|
MappedByteBuffer map2 = this.bChannel.map(mapMode, 0L, j);
|
|
this.bBuffer = map2;
|
|
map2.order(byteOrder);
|
|
} catch (IOException e) {
|
|
error(new Exception(MAP_FAILED, e));
|
|
this.fastBuffer.b(0, this.dataEnd - 12);
|
|
this.fastBuffer.a(4, this.checksum);
|
|
toBlockingMode();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void error(String str) {
|
|
b bVar = this.logger;
|
|
if (bVar != null) {
|
|
bVar.a(this.name, new Exception(str));
|
|
}
|
|
}
|
|
|
|
private void fastPutString(String str, String str2, g.i iVar) {
|
|
int a2 = q.a(str2);
|
|
if (iVar == null) {
|
|
int a3 = q.a(str);
|
|
checkKeySize(a3);
|
|
int i = a3 + 4;
|
|
this.updateSize = i + a2;
|
|
preparePutBytes();
|
|
this.fastBuffer.a((byte) 6);
|
|
putKey(str, a3);
|
|
putStringValue(str2, a2);
|
|
Map<String, g.b> map = this.data;
|
|
int i2 = this.updateStart;
|
|
map.put(str, new g.i(i2, i2 + i, str2, a2, false));
|
|
updateChange();
|
|
} else {
|
|
int i3 = iVar.a;
|
|
int i4 = i3 - iVar.c;
|
|
int i5 = iVar.e;
|
|
boolean z = false;
|
|
if (i5 == a2) {
|
|
this.checksum ^= this.fastBuffer.a(i3, i5);
|
|
if (a2 == str2.length()) {
|
|
str2.getBytes(0, a2, this.fastBuffer.a, iVar.a);
|
|
} else {
|
|
q qVar = this.fastBuffer;
|
|
qVar.b = iVar.a;
|
|
qVar.b(str2);
|
|
}
|
|
this.updateStart = iVar.a;
|
|
this.updateSize = a2;
|
|
} else {
|
|
this.updateSize = i4 + a2;
|
|
preparePutBytes();
|
|
this.fastBuffer.a((byte) 6);
|
|
int i6 = i4 - 3;
|
|
q qVar2 = this.fastBuffer;
|
|
byte[] bArr = qVar2.a;
|
|
System.arraycopy(bArr, iVar.c + 1, bArr, qVar2.b, i6);
|
|
this.fastBuffer.b += i6;
|
|
putStringValue(str2, a2);
|
|
remove((byte) 6, iVar.c, iVar.a + iVar.e);
|
|
r5 = iVar.b ? (String) iVar.d : null;
|
|
iVar.b = false;
|
|
int i7 = this.updateStart;
|
|
iVar.c = i7;
|
|
iVar.a = i7 + i4;
|
|
iVar.e = a2;
|
|
z = true;
|
|
}
|
|
iVar.d = str2;
|
|
updateChange();
|
|
if (z) {
|
|
checkGC();
|
|
}
|
|
if (r5 != null) {
|
|
ar.a(new File(this.path + this.name, r5));
|
|
}
|
|
}
|
|
checkIfCommit();
|
|
}
|
|
|
|
public synchronized void force() {
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.force();
|
|
this.bBuffer.force();
|
|
}
|
|
}
|
|
|
|
public void gc(int i) {
|
|
Collections.sort(this.invalids);
|
|
mergeInvalids();
|
|
c cVar = this.invalids.get(0);
|
|
int i2 = cVar.b;
|
|
int i3 = this.dataEnd;
|
|
int i4 = i3 - this.invalidBytes;
|
|
int i5 = i4 - 12;
|
|
int i6 = i4 - i2;
|
|
int i7 = i3 - i2;
|
|
boolean z = i5 < i7 + i6;
|
|
if (!z) {
|
|
this.checksum ^= this.fastBuffer.a(i2, i7);
|
|
}
|
|
int size = this.invalids.size();
|
|
int i8 = size - 1;
|
|
int i9 = this.dataEnd - this.invalids.get(i8).a;
|
|
int[] iArr = new int[(i9 > 0 ? size : i8) << 1];
|
|
int i10 = cVar.b;
|
|
int i11 = cVar.a;
|
|
for (int i12 = 1; i12 < size; i12++) {
|
|
c cVar2 = this.invalids.get(i12);
|
|
int i13 = cVar2.b - i11;
|
|
byte[] bArr = this.fastBuffer.a;
|
|
System.arraycopy(bArr, i11, bArr, i10, i13);
|
|
int i14 = (i12 - 1) << 1;
|
|
iArr[i14] = i11;
|
|
iArr[i14 + 1] = i11 - i10;
|
|
i10 += i13;
|
|
i11 = cVar2.a;
|
|
}
|
|
if (i9 > 0) {
|
|
byte[] bArr2 = this.fastBuffer.a;
|
|
System.arraycopy(bArr2, i11, bArr2, i10, i9);
|
|
int i15 = i8 << 1;
|
|
iArr[i15] = i11;
|
|
iArr[i15 + 1] = i11 - i10;
|
|
}
|
|
clearInvalid();
|
|
if (z) {
|
|
this.checksum = this.fastBuffer.a(12, i5);
|
|
} else {
|
|
this.checksum ^= this.fastBuffer.a(i2, i6);
|
|
}
|
|
this.dataEnd = i4;
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putInt(0, -1);
|
|
this.aBuffer.putLong(4, this.checksum);
|
|
this.aBuffer.position(i2);
|
|
this.aBuffer.put(this.fastBuffer.a, i2, i6);
|
|
this.aBuffer.putInt(0, i5);
|
|
this.bBuffer.putInt(0, i5);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.position(i2);
|
|
this.bBuffer.put(this.fastBuffer.a, i2, i6);
|
|
} else {
|
|
this.fastBuffer.b(0, i5);
|
|
this.fastBuffer.a(4, this.checksum);
|
|
}
|
|
updateOffset(i2, iArr);
|
|
int i16 = i4 + i;
|
|
if (this.fastBuffer.a.length - i16 > TRUNCATE_THRESHOLD) {
|
|
truncate(i16);
|
|
}
|
|
info(GC_FINISH);
|
|
}
|
|
|
|
public synchronized Map<String, Object> getAll() {
|
|
Object valueOf;
|
|
int size = this.data.size();
|
|
if (size == 0) {
|
|
return new HashMap();
|
|
}
|
|
HashMap hashMap = new HashMap(((size * 4) / 3) + 1);
|
|
for (Map.Entry<String, g.b> entry : this.data.entrySet()) {
|
|
String key = entry.getKey();
|
|
g.b value = entry.getValue();
|
|
switch (value.a()) {
|
|
case 1:
|
|
valueOf = Boolean.valueOf(((g.c) value).b);
|
|
break;
|
|
case 2:
|
|
valueOf = Integer.valueOf(((g.f) value).b);
|
|
break;
|
|
case 3:
|
|
valueOf = Float.valueOf(((g.e) value).b);
|
|
break;
|
|
case 4:
|
|
valueOf = Long.valueOf(((g.C0204g) value).b);
|
|
break;
|
|
case 5:
|
|
valueOf = Double.valueOf(((g.d) value).b);
|
|
break;
|
|
case 6:
|
|
g.i iVar = (g.i) value;
|
|
if (iVar.b) {
|
|
valueOf = getStringFromFile(iVar);
|
|
break;
|
|
} else {
|
|
valueOf = iVar.d;
|
|
break;
|
|
}
|
|
case 7:
|
|
g.a aVar = (g.a) value;
|
|
if (aVar.b) {
|
|
valueOf = getArrayFromFile(aVar);
|
|
break;
|
|
} else {
|
|
valueOf = aVar.d;
|
|
break;
|
|
}
|
|
case 8:
|
|
g.h hVar = (g.h) value;
|
|
if (hVar.b) {
|
|
valueOf = getObjectFromFile(hVar);
|
|
break;
|
|
} else {
|
|
valueOf = ((g.h) value).d;
|
|
break;
|
|
}
|
|
default:
|
|
valueOf = null;
|
|
break;
|
|
}
|
|
hashMap.put(key, valueOf);
|
|
}
|
|
return hashMap;
|
|
}
|
|
|
|
private String getStringFromFile(g.i iVar) {
|
|
try {
|
|
byte[] b2 = ar.b(new File(this.path + this.name, (String) iVar.d));
|
|
if (b2 != null && b2.length != 0) {
|
|
return new String(b2, StandardCharsets.UTF_8);
|
|
}
|
|
return "";
|
|
} catch (Exception e) {
|
|
error(e);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private byte[] getArrayFromFile(g.a aVar) {
|
|
try {
|
|
byte[] b2 = ar.b(new File(this.path + this.name, (String) aVar.d));
|
|
return b2 != null ? b2 : EMPTY_ARRAY;
|
|
} catch (Exception e) {
|
|
error(e);
|
|
return EMPTY_ARRAY;
|
|
}
|
|
}
|
|
|
|
private Object getObjectFromFile(g.h hVar) {
|
|
try {
|
|
byte[] b2 = ar.b(new File(this.path + this.name, (String) hVar.d));
|
|
if (b2 != null) {
|
|
int i = b2[0] & 255;
|
|
String str = new String(b2, 1, i, StandardCharsets.UTF_8);
|
|
a aVar = this.encoderMap.get(str);
|
|
if (aVar != null) {
|
|
int i2 = i + 1;
|
|
return aVar.a(b2, i2, b2.length - i2);
|
|
}
|
|
warning(new Exception("No encoder for tag:" + str));
|
|
return null;
|
|
}
|
|
warning(new Exception("Read object data failed"));
|
|
return null;
|
|
} catch (Exception e) {
|
|
error(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public byte[] getArray(String str) {
|
|
return getArray(str, EMPTY_ARRAY);
|
|
}
|
|
|
|
public synchronized byte[] getArray(String str, byte[] bArr) {
|
|
try {
|
|
g.a aVar = (g.a) this.data.get(str);
|
|
if (aVar != null) {
|
|
return aVar.b ? getArrayFromFile(aVar) : (byte[]) aVar.d;
|
|
}
|
|
return bArr;
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized boolean getBoolean(String str) {
|
|
return getBoolean(str, false);
|
|
}
|
|
|
|
public synchronized boolean getBoolean(String str, boolean z) {
|
|
g.c cVar = (g.c) this.data.get(str);
|
|
if (cVar != null) {
|
|
z = cVar.b;
|
|
}
|
|
return z;
|
|
}
|
|
|
|
public double getDouble(String str) {
|
|
return getDouble(str, 0.0d);
|
|
}
|
|
|
|
public synchronized double getDouble(String str, double d) {
|
|
g.d dVar = (g.d) this.data.get(str);
|
|
if (dVar != null) {
|
|
d = dVar.b;
|
|
}
|
|
return d;
|
|
}
|
|
|
|
public float getFloat(String str) {
|
|
return getFloat(str, 0.0f);
|
|
}
|
|
|
|
public synchronized float getFloat(String str, float f) {
|
|
g.e eVar = (g.e) this.data.get(str);
|
|
if (eVar != null) {
|
|
f = eVar.b;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
public int getInt(String str) {
|
|
return getInt(str, 0);
|
|
}
|
|
|
|
public synchronized int getInt(String str, int i) {
|
|
g.f fVar = (g.f) this.data.get(str);
|
|
if (fVar != null) {
|
|
i = fVar.b;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public synchronized long getLong(String str) {
|
|
g.C0204g c0204g;
|
|
c0204g = (g.C0204g) this.data.get(str);
|
|
return c0204g == null ? 0L : c0204g.b;
|
|
}
|
|
|
|
public synchronized long getLong(String str, long j) {
|
|
g.C0204g c0204g = (g.C0204g) this.data.get(str);
|
|
if (c0204g != null) {
|
|
j = c0204g.b;
|
|
}
|
|
return j;
|
|
}
|
|
|
|
private int getNewCapacity(int i, int i2) {
|
|
if (i2 > 536870912) {
|
|
throw new IllegalStateException("data size out of limit");
|
|
}
|
|
int i3 = PAGE_SIZE;
|
|
if (i2 <= i3) {
|
|
return i3;
|
|
}
|
|
while (i < i2) {
|
|
int i4 = DOUBLE_LIMIT;
|
|
i = i <= i4 ? i << 1 : i + i4;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public String getString(String str) {
|
|
return getString(str, "");
|
|
}
|
|
|
|
public synchronized String getString(String str, String str2) {
|
|
try {
|
|
g.i iVar = (g.i) this.data.get(str);
|
|
if (iVar != null) {
|
|
return iVar.b ? getStringFromFile(iVar) : (String) iVar.d;
|
|
}
|
|
return str2;
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized Set<String> getStringSet(String str) {
|
|
return (Set) getObject(str);
|
|
}
|
|
|
|
public synchronized <T> T getObject(String str) {
|
|
try {
|
|
g.h hVar = (g.h) this.data.get(str);
|
|
if (hVar != null) {
|
|
return hVar.b ? (T) getObjectFromFile(hVar) : (T) hVar.d;
|
|
}
|
|
return null;
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void info(String str) {
|
|
b bVar = this.logger;
|
|
if (bVar != null) {
|
|
bVar.a(this.name, str);
|
|
}
|
|
}
|
|
|
|
private boolean isABFileEqual() {
|
|
q qVar = new q(this.dataEnd);
|
|
this.bBuffer.rewind();
|
|
this.bBuffer.get(qVar.a, 0, this.dataEnd);
|
|
byte[] bArr = this.fastBuffer.a;
|
|
byte[] bArr2 = qVar.a;
|
|
for (int i = 0; i < this.dataEnd; i++) {
|
|
if (bArr[i] != bArr2[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private synchronized void loadData() {
|
|
try {
|
|
long nanoTime = System.nanoTime();
|
|
if (!loadFromCFile() && this.writingMode == 0) {
|
|
loadFromABFile();
|
|
}
|
|
if (this.fastBuffer == null) {
|
|
this.fastBuffer = new q(PAGE_SIZE);
|
|
}
|
|
if (this.logger != null) {
|
|
info("loading finish, data len:" + this.dataEnd + ", get keys:" + this.data.size() + ", use time:" + ((System.nanoTime() - nanoTime) / 1000000) + " ms");
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void loadFromABFile() {
|
|
FastKV fastKV = this;
|
|
File file = new File(fastKV.path, fastKV.name + A_SUFFIX);
|
|
File file2 = new File(fastKV.path, fastKV.name + B_SUFFIX);
|
|
try {
|
|
if (ar.c(file) && ar.c(file2)) {
|
|
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
|
RandomAccessFile randomAccessFile2 = new RandomAccessFile(file2, "rw");
|
|
long length = randomAccessFile.length();
|
|
long length2 = randomAccessFile2.length();
|
|
fastKV.aChannel = randomAccessFile.getChannel();
|
|
fastKV.bChannel = randomAccessFile2.getChannel();
|
|
try {
|
|
FileChannel fileChannel = fastKV.aChannel;
|
|
FileChannel.MapMode mapMode = FileChannel.MapMode.READ_WRITE;
|
|
MappedByteBuffer map = fileChannel.map(mapMode, 0L, length > 0 ? length : PAGE_SIZE);
|
|
fastKV.aBuffer = map;
|
|
ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
|
|
map.order(byteOrder);
|
|
MappedByteBuffer map2 = fastKV.bChannel.map(mapMode, 0L, length2 > 0 ? length2 : PAGE_SIZE);
|
|
fastKV.bBuffer = map2;
|
|
map2.order(byteOrder);
|
|
fastKV.fastBuffer = new q(fastKV.aBuffer.capacity());
|
|
if (length == 0 && length2 == 0) {
|
|
fastKV.dataEnd = 12;
|
|
return;
|
|
}
|
|
int i = fastKV.aBuffer.getInt();
|
|
long j = fastKV.aBuffer.getLong();
|
|
int i2 = fastKV.bBuffer.getInt();
|
|
long j2 = fastKV.bBuffer.getLong();
|
|
if (i >= 0) {
|
|
if (i <= length - 12) {
|
|
fastKV = this;
|
|
fastKV.dataEnd = i + 12;
|
|
fastKV.aBuffer.rewind();
|
|
fastKV.aBuffer.get(fastKV.fastBuffer.a, 0, fastKV.dataEnd);
|
|
if (j == fastKV.fastBuffer.a(12, i) && parseData() == 0) {
|
|
fastKV.checksum = j;
|
|
if (length == length2 && isABFileEqual()) {
|
|
return;
|
|
}
|
|
fastKV.warning(new Exception("B file error"));
|
|
fastKV.copyBuffer(fastKV.aBuffer, fastKV.bBuffer, fastKV.dataEnd);
|
|
return;
|
|
}
|
|
} else {
|
|
fastKV = this;
|
|
}
|
|
}
|
|
if (i2 >= 0 && i2 <= length2 - 12) {
|
|
fastKV.data.clear();
|
|
clearInvalid();
|
|
fastKV.dataEnd = i2 + 12;
|
|
if (fastKV.fastBuffer.a.length != fastKV.bBuffer.capacity()) {
|
|
fastKV.fastBuffer = new q(fastKV.bBuffer.capacity());
|
|
}
|
|
fastKV.bBuffer.rewind();
|
|
fastKV.bBuffer.get(fastKV.fastBuffer.a, 0, fastKV.dataEnd);
|
|
if (j2 == fastKV.fastBuffer.a(12, i2) && parseData() == 0) {
|
|
fastKV.warning(new Exception("A file error"));
|
|
fastKV.copyBuffer(fastKV.bBuffer, fastKV.aBuffer, fastKV.dataEnd);
|
|
fastKV.checksum = j2;
|
|
return;
|
|
}
|
|
}
|
|
fastKV.error(BOTH_FILES_ERROR);
|
|
resetData();
|
|
return;
|
|
} catch (IOException e) {
|
|
fastKV.error(e);
|
|
toBlockingMode();
|
|
fastKV.tryBlockingIO(file, file2);
|
|
return;
|
|
}
|
|
}
|
|
fastKV.error(new Exception(OPEN_FILE_FAILED));
|
|
toBlockingMode();
|
|
} catch (Exception e2) {
|
|
fastKV.error(e2);
|
|
clearData();
|
|
toBlockingMode();
|
|
}
|
|
}
|
|
|
|
private boolean loadFromCFile() {
|
|
File file = new File(this.path, this.name + C_SUFFIX);
|
|
File file2 = new File(this.path, this.name + TEMP_SUFFIX);
|
|
boolean z = false;
|
|
try {
|
|
if (!file.exists()) {
|
|
file = file2.exists() ? file2 : null;
|
|
}
|
|
if (file != null) {
|
|
if (!loadWithBlockingIO(file)) {
|
|
clearData();
|
|
deleteCFiles();
|
|
return false;
|
|
}
|
|
if (this.writingMode != 0) {
|
|
return false;
|
|
}
|
|
if (!writeToABFile(this.fastBuffer)) {
|
|
this.writingMode = 1;
|
|
return false;
|
|
}
|
|
info("recover from c file");
|
|
try {
|
|
deleteCFiles();
|
|
return true;
|
|
} catch (Exception e) {
|
|
e = e;
|
|
z = true;
|
|
error(e);
|
|
return z;
|
|
}
|
|
}
|
|
if (this.writingMode == 0) {
|
|
return false;
|
|
}
|
|
File file3 = new File(this.path, this.name + A_SUFFIX);
|
|
File file4 = new File(this.path, this.name + B_SUFFIX);
|
|
if (!file3.exists() || !file4.exists()) {
|
|
return false;
|
|
}
|
|
tryBlockingIO(file3, file4);
|
|
return false;
|
|
} catch (Exception e2) {
|
|
e = e2;
|
|
}
|
|
}
|
|
|
|
private boolean loadWithBlockingIO(File file) throws IOException {
|
|
long length = file.length();
|
|
if (length != 0 && length <= 536870912) {
|
|
int i = (int) length;
|
|
int newCapacity = getNewCapacity(PAGE_SIZE, i);
|
|
q qVar = this.fastBuffer;
|
|
if (qVar != null && qVar.a.length == newCapacity) {
|
|
qVar.b = 0;
|
|
} else {
|
|
qVar = new q(new byte[newCapacity]);
|
|
this.fastBuffer = qVar;
|
|
}
|
|
ar.a(file, qVar.a, i);
|
|
int c2 = qVar.c();
|
|
long b2 = qVar.b();
|
|
this.dataEnd = c2 + 12;
|
|
if (c2 >= 0 && c2 <= i - 12 && b2 == qVar.a(12, c2) && parseData() == 0) {
|
|
this.checksum = b2;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void mergeInvalids() {
|
|
int size = this.invalids.size() - 1;
|
|
c cVar = this.invalids.get(size);
|
|
while (size > 0) {
|
|
int i = size - 1;
|
|
c cVar2 = this.invalids.get(i);
|
|
if (cVar.b == cVar2.a) {
|
|
cVar2.a = cVar.a;
|
|
this.invalids.remove(size);
|
|
}
|
|
cVar = cVar2;
|
|
size = i;
|
|
}
|
|
}
|
|
|
|
/* JADX WARN: Code restructure failed: missing block: B:99:0x017f, code lost:
|
|
|
|
throw new java.lang.Exception(com.mbridge.msdk.foundation.tools.FastKV.PARSE_DATA_FAILED);
|
|
*/
|
|
/*
|
|
Code decompiled incorrectly, please refer to instructions dump.
|
|
To view partially-correct add '--show-bad-code' argument
|
|
*/
|
|
private int parseData() {
|
|
/*
|
|
Method dump skipped, instructions count: 400
|
|
To view this dump add '--comments-level debug' option
|
|
*/
|
|
throw new UnsupportedOperationException("Method not decompiled: com.mbridge.msdk.foundation.tools.FastKV.parseData():int");
|
|
}
|
|
|
|
private void preparePutBytes() {
|
|
ensureSize(this.updateSize);
|
|
int i = this.dataEnd;
|
|
this.updateStart = i;
|
|
this.dataEnd = this.updateSize + i;
|
|
this.fastBuffer.b = i;
|
|
this.sizeChanged = true;
|
|
}
|
|
|
|
public void putAll(Map<String, Object> map) {
|
|
putAll(map, null);
|
|
}
|
|
|
|
public synchronized void putAll(Map<String, Object> map, Map<Class, a> map2) {
|
|
try {
|
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
String key = entry.getKey();
|
|
Object value = entry.getValue();
|
|
if (key != null && !key.isEmpty()) {
|
|
if (value instanceof String) {
|
|
putString(key, (String) value);
|
|
} else if (value instanceof Boolean) {
|
|
putBoolean(key, ((Boolean) value).booleanValue());
|
|
} else if (value instanceof Integer) {
|
|
putInt(key, ((Integer) value).intValue());
|
|
} else if (value instanceof Long) {
|
|
putLong(key, ((Long) value).longValue());
|
|
} else if (value instanceof Float) {
|
|
putFloat(key, ((Float) value).floatValue());
|
|
} else if (value instanceof Double) {
|
|
putDouble(key, ((Double) value).doubleValue());
|
|
} else if (value instanceof Set) {
|
|
Set set = (Set) value;
|
|
if (!set.isEmpty() && (set.iterator().next() instanceof String)) {
|
|
putStringSet(key, (Set) value);
|
|
}
|
|
} else if (value instanceof byte[]) {
|
|
putArray(key, (byte[]) value);
|
|
} else if (map2 != null) {
|
|
a aVar = map2.get(value.getClass());
|
|
if (aVar != null) {
|
|
putObject(key, value, aVar);
|
|
} else {
|
|
warning(new Exception("missing encoder for type:" + value.getClass()));
|
|
}
|
|
} else {
|
|
warning(new Exception("missing encoders"));
|
|
}
|
|
}
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putArray(String str, byte[] bArr) {
|
|
try {
|
|
checkKey(str);
|
|
if (bArr == null) {
|
|
remove(str);
|
|
} else {
|
|
addOrUpdate(str, bArr, bArr, (g.a) this.data.get(str), (byte) 7);
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putBoolean(String str, boolean z) {
|
|
try {
|
|
checkKey(str);
|
|
g.c cVar = (g.c) this.data.get(str);
|
|
if (cVar == null) {
|
|
wrapHeader(str, (byte) 1);
|
|
q qVar = this.fastBuffer;
|
|
int i = qVar.b;
|
|
qVar.a(z ? (byte) 1 : (byte) 0);
|
|
updateChange();
|
|
this.data.put(str, new g.c(i, z));
|
|
checkIfCommit();
|
|
} else if (cVar.b != z) {
|
|
cVar.b = z;
|
|
updateBoolean(z ? (byte) 1 : (byte) 0, cVar.a);
|
|
checkIfCommit();
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putDouble(String str, double d) {
|
|
try {
|
|
checkKey(str);
|
|
g.d dVar = (g.d) this.data.get(str);
|
|
if (dVar == null) {
|
|
wrapHeader(str, (byte) 5);
|
|
q qVar = this.fastBuffer;
|
|
int i = qVar.b;
|
|
qVar.a(Double.doubleToRawLongBits(d));
|
|
updateChange();
|
|
this.data.put(str, new g.d(i, d));
|
|
checkIfCommit();
|
|
} else if (dVar.b != d) {
|
|
long doubleToRawLongBits = Double.doubleToRawLongBits(d);
|
|
long doubleToRawLongBits2 = Double.doubleToRawLongBits(dVar.b) ^ doubleToRawLongBits;
|
|
dVar.b = d;
|
|
updateInt64(doubleToRawLongBits, doubleToRawLongBits2, dVar.a);
|
|
checkIfCommit();
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putFloat(String str, float f) {
|
|
try {
|
|
checkKey(str);
|
|
g.e eVar = (g.e) this.data.get(str);
|
|
if (eVar == null) {
|
|
wrapHeader(str, (byte) 3);
|
|
q qVar = this.fastBuffer;
|
|
int i = qVar.b;
|
|
qVar.b(Float.floatToRawIntBits(f));
|
|
updateChange();
|
|
this.data.put(str, new g.e(i, f));
|
|
checkIfCommit();
|
|
} else if (eVar.b != f) {
|
|
eVar.b = f;
|
|
updateInt32(Float.floatToRawIntBits(f), (Float.floatToRawIntBits(eVar.b) ^ r6) & 4294967295L, eVar.a);
|
|
checkIfCommit();
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putInt(String str, int i) {
|
|
try {
|
|
checkKey(str);
|
|
g.f fVar = (g.f) this.data.get(str);
|
|
if (fVar == null) {
|
|
wrapHeader(str, (byte) 2);
|
|
q qVar = this.fastBuffer;
|
|
int i2 = qVar.b;
|
|
qVar.b(i);
|
|
updateChange();
|
|
this.data.put(str, new g.f(i2, i));
|
|
checkIfCommit();
|
|
} else {
|
|
if (fVar.b != i) {
|
|
fVar.b = i;
|
|
updateInt32(i, (r6 ^ i) & 4294967295L, fVar.a);
|
|
checkIfCommit();
|
|
}
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void putKey(String str, int i) {
|
|
this.fastBuffer.a((byte) i);
|
|
if (i == str.length()) {
|
|
q qVar = this.fastBuffer;
|
|
str.getBytes(0, i, qVar.a, qVar.b);
|
|
this.fastBuffer.b += i;
|
|
return;
|
|
}
|
|
this.fastBuffer.b(str);
|
|
}
|
|
|
|
public synchronized void putLong(String str, long j) {
|
|
try {
|
|
checkKey(str);
|
|
g.C0204g c0204g = (g.C0204g) this.data.get(str);
|
|
if (c0204g == null) {
|
|
wrapHeader(str, (byte) 4);
|
|
q qVar = this.fastBuffer;
|
|
int i = qVar.b;
|
|
qVar.a(j);
|
|
updateChange();
|
|
this.data.put(str, new g.C0204g(i, j));
|
|
checkIfCommit();
|
|
} else {
|
|
long j2 = c0204g.b;
|
|
if (j2 != j) {
|
|
c0204g.b = j;
|
|
updateInt64(j, j ^ j2, c0204g.a);
|
|
checkIfCommit();
|
|
}
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized <T> void putObject(String str, T t, a<T> aVar) {
|
|
byte[] bArr;
|
|
checkKey(str);
|
|
if (aVar == null) {
|
|
throw new IllegalArgumentException("Encoder is null");
|
|
}
|
|
String a2 = aVar.a();
|
|
if (a2 == null || a2.isEmpty() || a2.length() > 50) {
|
|
throw new IllegalArgumentException("Invalid encoder tag:" + a2);
|
|
}
|
|
if (!this.encoderMap.containsKey(a2)) {
|
|
throw new IllegalArgumentException("Encoder hasn't been registered");
|
|
}
|
|
if (t == null) {
|
|
remove(str);
|
|
return;
|
|
}
|
|
try {
|
|
bArr = aVar.a(t);
|
|
} catch (Exception e) {
|
|
error(e);
|
|
bArr = null;
|
|
}
|
|
if (bArr == null) {
|
|
remove(str);
|
|
return;
|
|
}
|
|
int a3 = q.a(a2);
|
|
q qVar = new q(a3 + 1 + bArr.length);
|
|
qVar.a((byte) a3);
|
|
qVar.b(a2);
|
|
qVar.a(bArr);
|
|
addOrUpdate(str, t, qVar.a, (g.h) this.data.get(str), (byte) 8);
|
|
}
|
|
|
|
public synchronized void putString(String str, String str2) {
|
|
try {
|
|
checkKey(str);
|
|
if (str2 == null) {
|
|
remove(str);
|
|
} else {
|
|
g.i iVar = (g.i) this.data.get(str);
|
|
if (str2.length() * 3 < 2048) {
|
|
fastPutString(str, str2, iVar);
|
|
} else {
|
|
addOrUpdate(str, str2, str2.isEmpty() ? EMPTY_ARRAY : str2.getBytes(StandardCharsets.UTF_8), iVar, (byte) 6);
|
|
}
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
public synchronized void putStringSet(String str, Set<String> set) {
|
|
try {
|
|
if (set == null) {
|
|
remove(str);
|
|
} else {
|
|
putObject(str, set, ao.a);
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void putStringValue(String str, int i) {
|
|
this.fastBuffer.a((short) i);
|
|
if (i == str.length()) {
|
|
q qVar = this.fastBuffer;
|
|
str.getBytes(0, i, qVar.a, qVar.b);
|
|
} else {
|
|
this.fastBuffer.b(str);
|
|
}
|
|
}
|
|
|
|
public synchronized void remove(String str) {
|
|
try {
|
|
g.b bVar = this.data.get(str);
|
|
if (bVar != null) {
|
|
this.data.remove(str);
|
|
byte a2 = bVar.a();
|
|
String str2 = null;
|
|
if (a2 <= 5) {
|
|
int a3 = q.a(str);
|
|
int i = bVar.a;
|
|
remove(a2, i - (a3 + 2), i + TYPE_SIZE[a2]);
|
|
} else {
|
|
g.j jVar = (g.j) bVar;
|
|
remove(a2, jVar.c, jVar.a + jVar.e);
|
|
if (jVar.b) {
|
|
str2 = (String) jVar.d;
|
|
}
|
|
}
|
|
byte b2 = (byte) (a2 | ByteCompanionObject.MIN_VALUE);
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putLong(4, this.checksum);
|
|
this.aBuffer.put(this.removeStart, b2);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.put(this.removeStart, b2);
|
|
} else {
|
|
this.fastBuffer.a(4, this.checksum);
|
|
}
|
|
this.removeStart = 0;
|
|
if (str2 != null) {
|
|
ar.a(new File(this.path + this.name, str2));
|
|
}
|
|
checkGC();
|
|
checkIfCommit();
|
|
}
|
|
} catch (Throwable th) {
|
|
throw th;
|
|
}
|
|
}
|
|
|
|
private void remove(byte b2, int i, int i2) {
|
|
countInvalid(i, i2);
|
|
byte b3 = (byte) (b2 | ByteCompanionObject.MIN_VALUE);
|
|
byte[] bArr = this.fastBuffer.a;
|
|
this.checksum = (((bArr[i] ^ b3) & 255) << ((i & 7) << 3)) ^ this.checksum;
|
|
bArr[i] = b3;
|
|
this.removeStart = i;
|
|
}
|
|
|
|
private int saveArray(String str, byte[] bArr, byte b2) {
|
|
this.tempExternalName = null;
|
|
if (bArr.length < 2048) {
|
|
return wrapArray(str, bArr, b2);
|
|
}
|
|
info("large value, key: " + str + ", size: " + bArr.length);
|
|
String b3 = ar.b();
|
|
if (ar.a(new File(this.path + this.name, b3), bArr)) {
|
|
this.tempExternalName = b3;
|
|
byte[] bArr2 = new byte[32];
|
|
b3.getBytes(0, 32, bArr2, 0);
|
|
return wrapArray(str, bArr2, (byte) (b2 | 64));
|
|
}
|
|
error("save large value failed");
|
|
return 0;
|
|
}
|
|
|
|
private void syncABBuffer(MappedByteBuffer mappedByteBuffer) {
|
|
if (this.sizeChanged && mappedByteBuffer != this.aBuffer) {
|
|
mappedByteBuffer.putInt(0, this.dataEnd - 12);
|
|
}
|
|
mappedByteBuffer.putLong(4, this.checksum);
|
|
int i = this.removeStart;
|
|
if (i != 0) {
|
|
mappedByteBuffer.put(i, this.fastBuffer.a[i]);
|
|
}
|
|
if (this.updateSize != 0) {
|
|
mappedByteBuffer.position(this.updateStart);
|
|
mappedByteBuffer.put(this.fastBuffer.a, this.updateStart, this.updateSize);
|
|
}
|
|
}
|
|
|
|
public synchronized String toString() {
|
|
return "FastKV: path:" + this.path + " name:" + this.name;
|
|
}
|
|
|
|
private void truncate(int i) {
|
|
int i2 = PAGE_SIZE;
|
|
int newCapacity = getNewCapacity(i2, i + i2);
|
|
byte[] bArr = this.fastBuffer.a;
|
|
if (newCapacity >= bArr.length) {
|
|
return;
|
|
}
|
|
byte[] bArr2 = new byte[newCapacity];
|
|
System.arraycopy(bArr, 0, bArr2, 0, this.dataEnd);
|
|
this.fastBuffer.a = bArr2;
|
|
if (this.writingMode == 0) {
|
|
try {
|
|
long j = newCapacity;
|
|
this.aChannel.truncate(j);
|
|
FileChannel fileChannel = this.aChannel;
|
|
FileChannel.MapMode mapMode = FileChannel.MapMode.READ_WRITE;
|
|
MappedByteBuffer map = fileChannel.map(mapMode, 0L, j);
|
|
this.aBuffer = map;
|
|
ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
|
|
map.order(byteOrder);
|
|
this.bChannel.truncate(j);
|
|
MappedByteBuffer map2 = this.bChannel.map(mapMode, 0L, j);
|
|
this.bBuffer = map2;
|
|
map2.order(byteOrder);
|
|
} catch (IOException e) {
|
|
error(new Exception(MAP_FAILED, e));
|
|
toBlockingMode();
|
|
}
|
|
}
|
|
info(TRUNCATE_FINISH);
|
|
}
|
|
|
|
private void tryBlockingIO(File file, File file2) {
|
|
try {
|
|
if (loadWithBlockingIO(file)) {
|
|
return;
|
|
}
|
|
} catch (IOException e) {
|
|
warning(e);
|
|
}
|
|
clearData();
|
|
try {
|
|
if (loadWithBlockingIO(file2)) {
|
|
return;
|
|
}
|
|
} catch (IOException e2) {
|
|
warning(e2);
|
|
}
|
|
clearData();
|
|
}
|
|
|
|
private void updateBoolean(byte b2, int i) {
|
|
long shiftCheckSum = this.checksum ^ shiftCheckSum(1L, i);
|
|
this.checksum = shiftCheckSum;
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putLong(4, shiftCheckSum);
|
|
this.aBuffer.put(i, b2);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.put(i, b2);
|
|
} else {
|
|
this.fastBuffer.a(4, shiftCheckSum);
|
|
}
|
|
this.fastBuffer.a[i] = b2;
|
|
}
|
|
|
|
private void updateBytes(int i, byte[] bArr) {
|
|
int length = bArr.length;
|
|
this.checksum ^= this.fastBuffer.a(i, length);
|
|
q qVar = this.fastBuffer;
|
|
qVar.b = i;
|
|
qVar.a(bArr);
|
|
long a2 = this.checksum ^ this.fastBuffer.a(i, length);
|
|
this.checksum = a2;
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putInt(0, -1);
|
|
this.aBuffer.putLong(4, this.checksum);
|
|
this.aBuffer.position(i);
|
|
this.aBuffer.put(bArr);
|
|
this.aBuffer.putInt(0, this.dataEnd - 12);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.position(i);
|
|
this.bBuffer.put(bArr);
|
|
return;
|
|
}
|
|
this.fastBuffer.a(4, a2);
|
|
}
|
|
|
|
private void updateChange() {
|
|
this.checksum ^= this.fastBuffer.a(this.updateStart, this.updateSize);
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putInt(0, -1);
|
|
syncABBuffer(this.aBuffer);
|
|
this.aBuffer.putInt(0, this.dataEnd - 12);
|
|
syncABBuffer(this.bBuffer);
|
|
} else {
|
|
if (this.sizeChanged) {
|
|
this.fastBuffer.b(0, this.dataEnd - 12);
|
|
}
|
|
this.fastBuffer.a(4, this.checksum);
|
|
}
|
|
this.sizeChanged = false;
|
|
this.removeStart = 0;
|
|
this.updateSize = 0;
|
|
}
|
|
|
|
private void updateInt32(int i, long j, int i2) {
|
|
long shiftCheckSum = shiftCheckSum(j, i2) ^ this.checksum;
|
|
this.checksum = shiftCheckSum;
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putLong(4, shiftCheckSum);
|
|
this.aBuffer.putInt(i2, i);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.putInt(i2, i);
|
|
} else {
|
|
this.fastBuffer.a(4, shiftCheckSum);
|
|
}
|
|
this.fastBuffer.b(i2, i);
|
|
}
|
|
|
|
private void updateInt64(long j, long j2, int i) {
|
|
long shiftCheckSum = shiftCheckSum(j2, i) ^ this.checksum;
|
|
this.checksum = shiftCheckSum;
|
|
if (this.writingMode == 0) {
|
|
this.aBuffer.putLong(4, shiftCheckSum);
|
|
this.aBuffer.putLong(i, j);
|
|
this.bBuffer.putLong(4, this.checksum);
|
|
this.bBuffer.putLong(i, j);
|
|
} else {
|
|
this.fastBuffer.a(4, shiftCheckSum);
|
|
}
|
|
this.fastBuffer.a(i, j);
|
|
}
|
|
|
|
private void updateObject(String str, Object obj, byte[] bArr, g.j jVar) {
|
|
int saveArray = saveArray(str, bArr, jVar.a());
|
|
if (saveArray != 0) {
|
|
String str2 = jVar.b ? (String) jVar.d : null;
|
|
remove(jVar.a(), jVar.c, jVar.a + jVar.e);
|
|
String str3 = this.tempExternalName;
|
|
boolean z = str3 != null;
|
|
jVar.c = this.updateStart;
|
|
jVar.a = saveArray;
|
|
jVar.b = z;
|
|
if (z) {
|
|
jVar.d = str3;
|
|
jVar.e = 32;
|
|
this.tempExternalName = null;
|
|
} else {
|
|
jVar.d = obj;
|
|
jVar.e = bArr.length;
|
|
}
|
|
updateChange();
|
|
checkGC();
|
|
if (str2 != null) {
|
|
ar.a(new File(this.path + this.name, str2));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateOffset(int i, int[] iArr) {
|
|
for (g.b bVar : this.data.values()) {
|
|
int i2 = bVar.a;
|
|
if (i2 > i) {
|
|
int length = (iArr.length >> 1) - 1;
|
|
int i3 = 0;
|
|
while (true) {
|
|
if (i3 > length) {
|
|
break;
|
|
}
|
|
int i4 = (i3 + length) >>> 1;
|
|
int i5 = iArr[i4 << 1];
|
|
if (i5 >= i2) {
|
|
if (i5 <= i2) {
|
|
length = i4;
|
|
break;
|
|
}
|
|
length = i4 - 1;
|
|
} else {
|
|
i3 = i4 + 1;
|
|
}
|
|
}
|
|
int i6 = iArr[(length << 1) + 1];
|
|
bVar.a -= i6;
|
|
if (bVar.a() >= 6) {
|
|
((g.j) bVar).c -= i6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private int wrapArray(String str, byte[] bArr, byte b2) {
|
|
wrapHeader(str, b2, bArr.length + 2);
|
|
this.fastBuffer.a((short) bArr.length);
|
|
q qVar = this.fastBuffer;
|
|
int i = qVar.b;
|
|
qVar.a(bArr);
|
|
return i;
|
|
}
|
|
|
|
private void wrapHeader(String str, byte b2) {
|
|
wrapHeader(str, b2, TYPE_SIZE[b2]);
|
|
}
|
|
|
|
private void wrapHeader(String str, byte b2, int i) {
|
|
int a2 = q.a(str);
|
|
checkKeySize(a2);
|
|
this.updateSize = a2 + 2 + i;
|
|
preparePutBytes();
|
|
this.fastBuffer.a(b2);
|
|
putKey(str, a2);
|
|
}
|
|
|
|
private boolean writeToABFile(q qVar) {
|
|
int length = qVar.a.length;
|
|
File file = new File(this.path, this.name + A_SUFFIX);
|
|
File file2 = new File(this.path, this.name + B_SUFFIX);
|
|
try {
|
|
if (!ar.c(file) || !ar.c(file2)) {
|
|
throw new Exception(OPEN_FILE_FAILED);
|
|
}
|
|
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
|
|
RandomAccessFile randomAccessFile2 = new RandomAccessFile(file2, "rw");
|
|
long j = length;
|
|
randomAccessFile.setLength(j);
|
|
randomAccessFile2.setLength(j);
|
|
this.aChannel = randomAccessFile.getChannel();
|
|
this.bChannel = randomAccessFile2.getChannel();
|
|
FileChannel fileChannel = this.aChannel;
|
|
FileChannel.MapMode mapMode = FileChannel.MapMode.READ_WRITE;
|
|
MappedByteBuffer map = fileChannel.map(mapMode, 0L, j);
|
|
this.aBuffer = map;
|
|
ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
|
|
map.order(byteOrder);
|
|
MappedByteBuffer map2 = this.bChannel.map(mapMode, 0L, j);
|
|
this.bBuffer = map2;
|
|
map2.order(byteOrder);
|
|
this.aBuffer.put(qVar.a, 0, this.dataEnd);
|
|
this.bBuffer.put(qVar.a, 0, this.dataEnd);
|
|
return true;
|
|
} catch (Exception e) {
|
|
error(e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static class Builder {
|
|
private static final Map<String, FastKV> INSTANCE_MAP = new ConcurrentHashMap();
|
|
private a[] encoders;
|
|
private final String name;
|
|
private final String path;
|
|
private int writingMode = 0;
|
|
|
|
public Builder asyncBlocking() {
|
|
this.writingMode = 1;
|
|
return this;
|
|
}
|
|
|
|
public Builder blocking() {
|
|
this.writingMode = 2;
|
|
return this;
|
|
}
|
|
|
|
public Builder encoder(a[] aVarArr) {
|
|
this.encoders = aVarArr;
|
|
return this;
|
|
}
|
|
|
|
public Builder(String str, String str2) {
|
|
if (str == null || str.isEmpty()) {
|
|
throw new IllegalArgumentException("path is empty");
|
|
}
|
|
if (str2 == null || str2.isEmpty()) {
|
|
throw new IllegalArgumentException("name is empty");
|
|
}
|
|
if (!str.endsWith("/")) {
|
|
str = str + '/';
|
|
}
|
|
this.path = str;
|
|
this.name = str2;
|
|
}
|
|
|
|
public FastKV build() {
|
|
String str = this.path + this.name;
|
|
Map<String, FastKV> map = INSTANCE_MAP;
|
|
FastKV fastKV = map.get(str);
|
|
if (fastKV == null) {
|
|
synchronized (Builder.class) {
|
|
try {
|
|
fastKV = map.get(str);
|
|
if (fastKV == null) {
|
|
fastKV = new FastKV(this.path, this.name, this.encoders, this.writingMode);
|
|
map.put(str, fastKV);
|
|
}
|
|
} finally {
|
|
}
|
|
}
|
|
}
|
|
return fastKV;
|
|
}
|
|
}
|
|
|
|
public static class c implements Comparable<c> {
|
|
int a;
|
|
int b;
|
|
|
|
@Override // java.lang.Comparable
|
|
public final /* bridge */ /* synthetic */ int compareTo(c cVar) {
|
|
return this.b - cVar.b;
|
|
}
|
|
|
|
public c(int i, int i2) {
|
|
this.b = i;
|
|
this.a = i2;
|
|
}
|
|
}
|
|
}
|