Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /sql /vfs_wrapper_fuchsia.cc
blob: 4278066c9665e3a72c285e45abaab3a0b6230000 [file] [log] [blame] [edit]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include"sql/vfs_wrapper_fuchsia.h"
#include<string>
#include"base/check.h"
#include"base/check_op.h"
#include"base/containers/fixed_flat_set.h"
#include"base/containers/flat_map.h"
#include"base/containers/flat_set.h"
#include"base/logging.h"
#include"base/no_destructor.h"
#include"base/synchronization/lock.h"
#include"base/thread_annotations.h"
#include"sql/vfs_wrapper.h"
#include"third_party/sqlite/sqlite3.h"
namespace sql{
namespace{
structFileLock{
int lock_level;
// Used to track the pointers to different VfsFile instances that hold shared
// locks on the same underlying file. The pointer is only used as a unique id
// for the VfsFile instance. The contents are never accessed.
base::flat_set<VfsFile*> readers={};
// Used to track a VfsFile instance that holds a reserved/pending/exclusive
// lock for writing. The pointer is only used as a unique id for the VfsFile
// instance. The contents are never accessed.
VfsFile* writer=nullptr;
};
// Singleton that stores and mutates state as described in
// https://www.sqlite.org/lockingv3.html
classFuchsiaFileLockManager{
public:
FuchsiaFileLockManager()=default;
// Returns lock manager for the current process.
staticFuchsiaFileLockManager*Instance(){
static base::NoDestructor<FuchsiaFileLockManager> lock_manager;
return lock_manager.get();
}
intLock(VfsFile* vfs_file,int requested_lock){
DCHECK_GT(requested_lock, SQLITE_LOCK_NONE)
<<"SQLITE_LOCK_NONE can only be set via Unlock";
base::AutoLock lock(lock_);
constauto file_lock_state=GetFileLockStateLocked(vfs_file);
// Allow any lock level since the lock isn't held.
if(file_lock_state.readers.empty()&& file_lock_state.writer==nullptr){
if(requested_lock== SQLITE_LOCK_SHARED){
locked_files_[vfs_file->file_name]={.lock_level= requested_lock,
.readers={vfs_file}};
}else{
locked_files_[vfs_file->file_name]={.lock_level= requested_lock,
.writer= vfs_file};
}
return SQLITE_OK;
}
if(requested_lock== SQLITE_LOCK_SHARED){
if(file_lock_state.lock_level>= SQLITE_LOCK_PENDING){
DVLOG(1)<<"lock for file "<< vfs_file->file_name
<<" is held by a writer and cannot be shared.";
return SQLITE_BUSY;
}
locked_files_[vfs_file->file_name].readers.insert(vfs_file);
return SQLITE_OK;
}
if(file_lock_state.writer!=nullptr&&
file_lock_state.writer!= vfs_file){
DVLOG(1)<<"lock for file "<< vfs_file->file_name
<<" is already held by another writer.";
return SQLITE_BUSY;
}
if(requested_lock== SQLITE_LOCK_EXCLUSIVE&&
(file_lock_state.readers.size()>1||
(file_lock_state.readers.size()==1&&
!file_lock_state.readers.contains(vfs_file)))){
DVLOG(1)<<"lock for file "<< vfs_file->file_name
<<" is held by readers and can't yet be upgraded to exclusive.";
return SQLITE_BUSY;
}
DCHECK(file_lock_state.writer==nullptr||
file_lock_state.writer== vfs_file);
locked_files_[vfs_file->file_name].lock_level= requested_lock;
locked_files_[vfs_file->file_name].writer= vfs_file;
locked_files_[vfs_file->file_name].readers.erase(vfs_file);
DCHECK(locked_files_[vfs_file->file_name].lock_level<
SQLITE_LOCK_EXCLUSIVE||
locked_files_[vfs_file->file_name].readers.empty());
return SQLITE_OK;
}
intUnlock(VfsFile* vfs_file,int requested_lock){
base::AutoLock lock(lock_);
constauto file_lock_state=GetFileLockStateLocked(vfs_file);
DCHECK_LE(requested_lock, file_lock_state.lock_level)
<<"Attempted to unlock to a higher lock level, unlock can only "
"decrement.";
// Shortcut if the caller doesn't currently hold a lock.
if(!file_lock_state.readers.contains(vfs_file)&&
file_lock_state.writer!= vfs_file){
DVLOG(1)<<"caller can't unlock because it doesn't currently "
<<"hold a lock for file "<< vfs_file->file_name;
return SQLITE_OK;
}
if(requested_lock== SQLITE_LOCK_NONE){
locked_files_[vfs_file->file_name].readers.erase(vfs_file);
}elseif(requested_lock== SQLITE_LOCK_SHARED){
locked_files_[vfs_file->file_name].readers.insert(vfs_file);
}
if(requested_lock< SQLITE_LOCK_RESERVED&&
file_lock_state.writer== vfs_file){
locked_files_[vfs_file->file_name].writer=nullptr;
}
// Check that `vfs_file` is correctly tracked given the `requested_lock`.
DCHECK(requested_lock== SQLITE_LOCK_SHARED||
!locked_files_[vfs_file->file_name].readers.contains(vfs_file));
DCHECK_EQ(requested_lock> SQLITE_LOCK_SHARED,
locked_files_[vfs_file->file_name].writer== vfs_file);
// Mark lock level as shared if there are only shared usages.
if(!file_lock_state.readers.empty()&& file_lock_state.writer==nullptr){
locked_files_[vfs_file->file_name].lock_level= SQLITE_LOCK_SHARED;
return SQLITE_OK;
}
// Remove lock if there are no usages left.
if(file_lock_state.readers.empty()&& file_lock_state.writer==nullptr){
DCHECK_EQ(requested_lock, SQLITE_LOCK_NONE);
locked_files_.erase(vfs_file->file_name);
return SQLITE_OK;
}
if(file_lock_state.writer!= vfs_file){
DCHECK_GE(file_lock_state.lock_level, SQLITE_LOCK_RESERVED);
DCHECK_LE(requested_lock, SQLITE_LOCK_SHARED);
return SQLITE_OK;
}
locked_files_[vfs_file->file_name].lock_level= requested_lock;
return SQLITE_OK;
}
intCheckReservedLock(VfsFile* vfs_file,int* result){
base::AutoLock lock(lock_);
constauto file_lock_state=GetFileLockStateLocked(vfs_file);
switch(file_lock_state.lock_level){
case SQLITE_LOCK_NONE:
case SQLITE_LOCK_SHARED:
*result=0;
return SQLITE_OK;
case SQLITE_LOCK_RESERVED:
case SQLITE_LOCK_PENDING:
case SQLITE_LOCK_EXCLUSIVE:
*result=1;
return SQLITE_OK;
default:
return SQLITE_IOERR_CHECKRESERVEDLOCK;
}
}
private:
~FuchsiaFileLockManager()=delete;
constFileLock&GetFileLockStateLocked(VfsFile* vfs_file)
EXCLUSIVE_LOCKS_REQUIRED(lock_){
staticconstFileLock kUnlockedFileLock={.lock_level= SQLITE_LOCK_NONE};
constauto file_lock_state_iter= locked_files_.find(vfs_file->file_name);
if(file_lock_state_iter== locked_files_.end()){
return kUnlockedFileLock;
}
return file_lock_state_iter->second;
}
base::Lock lock_;
// Set of all currently locked files.
base::flat_map<std::string,FileLock> locked_files_ GUARDED_BY(lock_);
};
}// namespace
intLock(sqlite3_file* sqlite_file,int file_lock){
DCHECK(file_lock== SQLITE_LOCK_SHARED|| file_lock== SQLITE_LOCK_RESERVED||
file_lock== SQLITE_LOCK_PENDING||
file_lock== SQLITE_LOCK_EXCLUSIVE);
auto* vfs_file=reinterpret_cast<VfsFile*>(sqlite_file);
returnFuchsiaFileLockManager::Instance()->Lock(vfs_file, file_lock);
}
intUnlock(sqlite3_file* sqlite_file,int file_lock){
auto* vfs_file=reinterpret_cast<VfsFile*>(sqlite_file);
returnFuchsiaFileLockManager::Instance()->Unlock(vfs_file, file_lock);
}
intCheckReservedLock(sqlite3_file* sqlite_file,int* result){
auto* vfs_file=reinterpret_cast<VfsFile*>(sqlite_file);
returnFuchsiaFileLockManager::Instance()->CheckReservedLock(vfs_file,
result);
}
}// namespace sql

[8]ページ先頭

©2009-2025 Movatter.jp