mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-05 00:23:09 +02:00
Updated AndroidX
This commit is contained in:
112
app/src/main/java/androidx/room/CopyLock.java
Normal file
112
app/src/main/java/androidx/room/CopyLock.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package androidx.room.util;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RestrictTo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Utility class for in-process and multi-process key-based lock mechanism for safely copying
|
||||
* database files.
|
||||
* <p>
|
||||
* Acquiring the lock will be quick if no other thread or process has a lock with the same key.
|
||||
* But if the lock is already held then acquiring it will block, until the other thread or process
|
||||
* releases the lock. Note that the key and lock directory must be the same to achieve
|
||||
* synchronization.
|
||||
* <p>
|
||||
* Locking is done via two levels:
|
||||
* <ol>
|
||||
* <li>
|
||||
* Thread locking within the same JVM process is done via a map of String key to ReentrantLock
|
||||
* objects.
|
||||
* <li>
|
||||
* Multi-process locking is done via a lock file whose name contains the key and FileLock
|
||||
* objects.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
|
||||
public class CopyLock {
|
||||
|
||||
// in-process lock map
|
||||
private static final Map<String, Lock> sThreadLocks = new HashMap<>();
|
||||
|
||||
private final File mCopyLockFile;
|
||||
private final Lock mThreadLock;
|
||||
private final boolean mFileLevelLock;
|
||||
private FileChannel mLockChannel;
|
||||
|
||||
/**
|
||||
* Creates a lock with {@code name} and using {@code lockDir} as the directory for the
|
||||
* lock files.
|
||||
* @param name the name of this lock.
|
||||
* @param lockDir the directory where the lock files will be located.
|
||||
* @param processLock whether to use file for process level locking or not.
|
||||
*/
|
||||
public CopyLock(@NonNull String name, @NonNull File lockDir, boolean processLock) {
|
||||
mCopyLockFile = new File(lockDir, name + ".lck");
|
||||
mThreadLock = getThreadLock(mCopyLockFile.getAbsolutePath());
|
||||
mFileLevelLock = processLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to grab the lock, blocking if already held by another thread or process.
|
||||
*/
|
||||
public void lock() {
|
||||
mThreadLock.lock();
|
||||
if (mFileLevelLock) {
|
||||
try {
|
||||
mLockChannel = new FileOutputStream(mCopyLockFile).getChannel();
|
||||
mLockChannel.lock();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Unable to grab copy lock.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the lock.
|
||||
*/
|
||||
public void unlock() {
|
||||
if (mLockChannel != null) {
|
||||
try {
|
||||
mLockChannel.close();
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
mThreadLock.unlock();
|
||||
}
|
||||
|
||||
private static Lock getThreadLock(String key) {
|
||||
synchronized (sThreadLocks) {
|
||||
Lock threadLock = sThreadLocks.get(key);
|
||||
if (threadLock == null) {
|
||||
threadLock = new ReentrantLock();
|
||||
sThreadLocks.put(key, threadLock);
|
||||
}
|
||||
return threadLock;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user