db/simple: use class ScopeDatabaseLock
This commit is contained in:
parent
7dd3b72a8c
commit
e31f0b8b0c
@ -72,7 +72,6 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
|
|||||||
char *line;
|
char *line;
|
||||||
unsigned format = 0;
|
unsigned format = 0;
|
||||||
bool found_charset = false, found_version = false;
|
bool found_charset = false, found_version = false;
|
||||||
bool success;
|
|
||||||
bool tags[TAG_NUM_OF_ITEM_TYPES];
|
bool tags[TAG_NUM_OF_ITEM_TYPES];
|
||||||
|
|
||||||
/* get initial info */
|
/* get initial info */
|
||||||
@ -152,9 +151,6 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
|
|||||||
|
|
||||||
LogDebug(db_domain, "reading DB");
|
LogDebug(db_domain, "reading DB");
|
||||||
|
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
success = directory_load(file, music_root, error);
|
return directory_load(file, music_root, error);
|
||||||
db_unlock();
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
@ -240,13 +240,13 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
|
|||||||
assert(prefixed_light_song == nullptr);
|
assert(prefixed_light_song == nullptr);
|
||||||
assert(borrowed_song_count == 0);
|
assert(borrowed_song_count == 0);
|
||||||
|
|
||||||
db_lock();
|
ScopeDatabaseLock protect;
|
||||||
|
|
||||||
auto r = root->LookupDirectory(uri);
|
auto r = root->LookupDirectory(uri);
|
||||||
|
|
||||||
if (r.directory->IsMount()) {
|
if (r.directory->IsMount()) {
|
||||||
/* pass the request to the mounted database */
|
/* pass the request to the mounted database */
|
||||||
db_unlock();
|
protect.unlock();
|
||||||
|
|
||||||
const LightSong *song =
|
const LightSong *song =
|
||||||
r.directory->mounted_database->GetSong(r.uri, error);
|
r.directory->mounted_database->GetSong(r.uri, error);
|
||||||
@ -260,7 +260,6 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
|
|||||||
|
|
||||||
if (r.uri == nullptr) {
|
if (r.uri == nullptr) {
|
||||||
/* it's a directory */
|
/* it's a directory */
|
||||||
db_unlock();
|
|
||||||
error.Format(db_domain, DB_NOT_FOUND,
|
error.Format(db_domain, DB_NOT_FOUND,
|
||||||
"No such song: %s", uri);
|
"No such song: %s", uri);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -268,14 +267,13 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
|
|||||||
|
|
||||||
if (strchr(r.uri, '/') != nullptr) {
|
if (strchr(r.uri, '/') != nullptr) {
|
||||||
/* refers to a URI "below" the actual song */
|
/* refers to a URI "below" the actual song */
|
||||||
db_unlock();
|
|
||||||
error.Format(db_domain, DB_NOT_FOUND,
|
error.Format(db_domain, DB_NOT_FOUND,
|
||||||
"No such song: %s", uri);
|
"No such song: %s", uri);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Song *song = r.directory->FindSong(r.uri);
|
const Song *song = r.directory->FindSong(r.uri);
|
||||||
db_unlock();
|
protect.unlock();
|
||||||
if (song == nullptr) {
|
if (song == nullptr) {
|
||||||
error.Format(db_domain, DB_NOT_FOUND,
|
error.Format(db_domain, DB_NOT_FOUND,
|
||||||
"No such song: %s", uri);
|
"No such song: %s", uri);
|
||||||
@ -367,15 +365,15 @@ SimpleDatabase::GetStats(const DatabaseSelection &selection,
|
|||||||
bool
|
bool
|
||||||
SimpleDatabase::Save(Error &error)
|
SimpleDatabase::Save(Error &error)
|
||||||
{
|
{
|
||||||
db_lock();
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
|
||||||
LogDebug(simple_db_domain, "removing empty directories from DB");
|
LogDebug(simple_db_domain, "removing empty directories from DB");
|
||||||
root->PruneEmpty();
|
root->PruneEmpty();
|
||||||
|
|
||||||
LogDebug(simple_db_domain, "sorting DB");
|
LogDebug(simple_db_domain, "sorting DB");
|
||||||
root->Sort();
|
root->Sort();
|
||||||
|
}
|
||||||
db_unlock();
|
|
||||||
|
|
||||||
LogDebug(simple_db_domain, "writing DB");
|
LogDebug(simple_db_domain, "writing DB");
|
||||||
|
|
||||||
|
@ -39,6 +39,27 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static Directory *
|
||||||
|
LockFindChild(Directory &directory, const char *name)
|
||||||
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
return directory.FindChild(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Directory *
|
||||||
|
LockMakeChild(Directory &directory, const char *name)
|
||||||
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
return directory.MakeChild(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Song *
|
||||||
|
LockFindSong(Directory &directory, const char *name)
|
||||||
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
return directory.FindSong(name);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
|
UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
|
||||||
{
|
{
|
||||||
@ -46,11 +67,9 @@ UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
|
|||||||
if (tmp) {
|
if (tmp) {
|
||||||
const std::string child_name(name, tmp);
|
const std::string child_name(name, tmp);
|
||||||
//add dir is not there already
|
//add dir is not there already
|
||||||
db_lock();
|
Directory *subdir = LockMakeChild(directory,
|
||||||
Directory *subdir =
|
child_name.c_str());
|
||||||
directory.MakeChild(child_name.c_str());
|
|
||||||
subdir->device = DEVICE_INARCHIVE;
|
subdir->device = DEVICE_INARCHIVE;
|
||||||
db_unlock();
|
|
||||||
|
|
||||||
//create directories first
|
//create directories first
|
||||||
UpdateArchiveTree(*subdir, tmp + 1);
|
UpdateArchiveTree(*subdir, tmp + 1);
|
||||||
@ -62,15 +81,14 @@ UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//add file
|
//add file
|
||||||
db_lock();
|
Song *song = LockFindSong(directory, name);
|
||||||
Song *song = directory.FindSong(name);
|
|
||||||
db_unlock();
|
|
||||||
if (song == nullptr) {
|
if (song == nullptr) {
|
||||||
song = Song::LoadFile(storage, name, directory);
|
song = Song::LoadFile(storage, name, directory);
|
||||||
if (song != nullptr) {
|
if (song != nullptr) {
|
||||||
db_lock();
|
{
|
||||||
directory.AddSong(song);
|
const ScopeDatabaseLock protect;
|
||||||
db_unlock();
|
directory.AddSong(song);
|
||||||
|
}
|
||||||
|
|
||||||
modified = true;
|
modified = true;
|
||||||
FormatDefault(update_domain, "added %s/%s",
|
FormatDefault(update_domain, "added %s/%s",
|
||||||
@ -108,9 +126,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
|
|||||||
const StorageFileInfo &info,
|
const StorageFileInfo &info,
|
||||||
const ArchivePlugin &plugin)
|
const ArchivePlugin &plugin)
|
||||||
{
|
{
|
||||||
db_lock();
|
Directory *directory = LockFindChild(parent, name);
|
||||||
Directory *directory = parent.FindChild(name);
|
|
||||||
db_unlock();
|
|
||||||
|
|
||||||
if (directory != nullptr && directory->mtime == info.mtime &&
|
if (directory != nullptr && directory->mtime == info.mtime &&
|
||||||
!walk_discard)
|
!walk_discard)
|
||||||
@ -139,12 +155,12 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
|
|||||||
if (directory == nullptr) {
|
if (directory == nullptr) {
|
||||||
FormatDebug(update_domain,
|
FormatDebug(update_domain,
|
||||||
"creating archive directory: %s", name);
|
"creating archive directory: %s", name);
|
||||||
db_lock();
|
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
directory = parent.CreateChild(name);
|
directory = parent.CreateChild(name);
|
||||||
/* mark this directory as archive (we use device for
|
/* mark this directory as archive (we use device for
|
||||||
this) */
|
this) */
|
||||||
directory->device = DEVICE_INARCHIVE;
|
directory->device = DEVICE_INARCHIVE;
|
||||||
db_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
directory->mtime = info.mtime;
|
directory->mtime = info.mtime;
|
||||||
|
@ -78,16 +78,16 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
|
|||||||
return false;
|
return false;
|
||||||
const DecoderPlugin &plugin = *_plugin;
|
const DecoderPlugin &plugin = *_plugin;
|
||||||
|
|
||||||
db_lock();
|
Directory *contdir;
|
||||||
Directory *contdir = MakeDirectoryIfModified(directory, name, info);
|
{
|
||||||
if (contdir == nullptr) {
|
const ScopeDatabaseLock protect;
|
||||||
/* not modified */
|
contdir = MakeDirectoryIfModified(directory, name, info);
|
||||||
db_unlock();
|
if (contdir == nullptr)
|
||||||
return true;
|
/* not modified */
|
||||||
}
|
return true;
|
||||||
|
|
||||||
contdir->device = DEVICE_CONTAINER;
|
contdir->device = DEVICE_CONTAINER;
|
||||||
db_unlock();
|
}
|
||||||
|
|
||||||
const auto pathname = storage.MapFS(contdir->GetPath());
|
const auto pathname = storage.MapFS(contdir->GetPath());
|
||||||
if (pathname.IsNull()) {
|
if (pathname.IsNull()) {
|
||||||
@ -116,9 +116,10 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
|
|||||||
|
|
||||||
tag_builder.Commit(song->tag);
|
tag_builder.Commit(song->tag);
|
||||||
|
|
||||||
db_lock();
|
{
|
||||||
contdir->AddSong(song);
|
const ScopeDatabaseLock protect;
|
||||||
db_unlock();
|
contdir->AddSong(song);
|
||||||
|
}
|
||||||
|
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
||||||
|
@ -50,9 +50,8 @@ DatabaseEditor::DeleteSong(Directory &dir, Song *del)
|
|||||||
void
|
void
|
||||||
DatabaseEditor::LockDeleteSong(Directory &parent, Song *song)
|
DatabaseEditor::LockDeleteSong(Directory &parent, Song *song)
|
||||||
{
|
{
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
DeleteSong(parent, song);
|
DeleteSong(parent, song);
|
||||||
db_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,17 +86,17 @@ DatabaseEditor::DeleteDirectory(Directory *directory)
|
|||||||
void
|
void
|
||||||
DatabaseEditor::LockDeleteDirectory(Directory *directory)
|
DatabaseEditor::LockDeleteDirectory(Directory *directory)
|
||||||
{
|
{
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
DeleteDirectory(directory);
|
DeleteDirectory(directory);
|
||||||
db_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseEditor::DeleteNameIn(Directory &parent, const char *name)
|
DatabaseEditor::DeleteNameIn(Directory &parent, const char *name)
|
||||||
{
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
|
|
||||||
db_lock();
|
|
||||||
Directory *directory = parent.FindChild(name);
|
Directory *directory = parent.FindChild(name);
|
||||||
|
|
||||||
if (directory != nullptr) {
|
if (directory != nullptr) {
|
||||||
@ -113,7 +112,5 @@ DatabaseEditor::DeleteNameIn(Directory &parent, const char *name)
|
|||||||
|
|
||||||
parent.playlists.erase(name);
|
parent.playlists.erase(name);
|
||||||
|
|
||||||
db_unlock();
|
|
||||||
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
@ -80,9 +80,11 @@ UpdateService::CancelMount(const char *uri)
|
|||||||
/* determine which (mounted) database will be updated and what
|
/* determine which (mounted) database will be updated and what
|
||||||
storage will be scanned */
|
storage will be scanned */
|
||||||
|
|
||||||
db_lock();
|
Directory::LookupResult lr;
|
||||||
const auto lr = db.GetRoot().LookupDirectory(uri);
|
{
|
||||||
db_unlock();
|
const ScopeDatabaseLock protect;
|
||||||
|
lr = db.GetRoot().LookupDirectory(uri);
|
||||||
|
}
|
||||||
|
|
||||||
if (!lr.directory->IsMount())
|
if (!lr.directory->IsMount())
|
||||||
return;
|
return;
|
||||||
@ -188,9 +190,12 @@ UpdateService::Enqueue(const char *path, bool discard)
|
|||||||
SimpleDatabase *db2;
|
SimpleDatabase *db2;
|
||||||
Storage *storage2;
|
Storage *storage2;
|
||||||
|
|
||||||
db_lock();
|
Directory::LookupResult lr;
|
||||||
const auto lr = db.GetRoot().LookupDirectory(path);
|
{
|
||||||
db_unlock();
|
const ScopeDatabaseLock protect;
|
||||||
|
lr = db.GetRoot().LookupDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
if (lr.directory->IsMount()) {
|
if (lr.directory->IsMount()) {
|
||||||
/* follow the mountpoint, update the mounted
|
/* follow the mountpoint, update the mounted
|
||||||
database */
|
database */
|
||||||
|
@ -35,9 +35,11 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
|
|||||||
const char *name, const char *suffix,
|
const char *name, const char *suffix,
|
||||||
const StorageFileInfo &info)
|
const StorageFileInfo &info)
|
||||||
{
|
{
|
||||||
db_lock();
|
Song *song;
|
||||||
Song *song = directory.FindSong(name);
|
{
|
||||||
db_unlock();
|
const ScopeDatabaseLock protect;
|
||||||
|
song = directory.FindSong(name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!directory_child_access(storage, directory, name, R_OK)) {
|
if (!directory_child_access(storage, directory, name, R_OK)) {
|
||||||
FormatError(update_domain,
|
FormatError(update_domain,
|
||||||
@ -69,9 +71,10 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_lock();
|
{
|
||||||
directory.AddSong(song);
|
const ScopeDatabaseLock protect;
|
||||||
db_unlock();
|
directory.AddSong(song);
|
||||||
|
}
|
||||||
|
|
||||||
modified = true;
|
modified = true;
|
||||||
FormatDefault(update_domain, "added %s/%s",
|
FormatDefault(update_domain, "added %s/%s",
|
||||||
|
@ -78,7 +78,7 @@ inline void
|
|||||||
UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
|
UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
|
||||||
const ExcludeList &exclude_list)
|
const ExcludeList &exclude_list)
|
||||||
{
|
{
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
|
|
||||||
directory.ForEachChildSafe([&](Directory &child){
|
directory.ForEachChildSafe([&](Directory &child){
|
||||||
const auto name_fs =
|
const auto name_fs =
|
||||||
@ -99,8 +99,6 @@ UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
|
|||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
db_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -129,9 +127,8 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory)
|
|||||||
i != end;) {
|
i != end;) {
|
||||||
if (!directory_child_is_regular(storage, directory,
|
if (!directory_child_is_regular(storage, directory,
|
||||||
i->name.c_str())) {
|
i->name.c_str())) {
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
i = directory.playlists.erase(i);
|
i = directory.playlists.erase(i);
|
||||||
db_unlock();
|
|
||||||
} else
|
} else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@ -198,10 +195,9 @@ UpdateWalk::UpdatePlaylistFile(Directory &directory,
|
|||||||
|
|
||||||
PlaylistInfo pi(name, info.mtime);
|
PlaylistInfo pi(name, info.mtime);
|
||||||
|
|
||||||
db_lock();
|
const ScopeDatabaseLock protect;
|
||||||
if (directory.playlists.UpdateOrInsert(std::move(pi)))
|
if (directory.playlists.UpdateOrInsert(std::move(pi)))
|
||||||
modified = true;
|
modified = true;
|
||||||
db_unlock();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,9 +228,11 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory,
|
|||||||
info.inode, info.device))
|
info.inode, info.device))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
db_lock();
|
Directory *subdir;
|
||||||
Directory *subdir = directory.MakeChild(name);
|
{
|
||||||
db_unlock();
|
const ScopeDatabaseLock protect;
|
||||||
|
subdir = directory.MakeChild(name);
|
||||||
|
}
|
||||||
|
|
||||||
assert(&directory == subdir->parent);
|
assert(&directory == subdir->parent);
|
||||||
|
|
||||||
@ -393,9 +391,11 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent,
|
|||||||
const char *uri_utf8,
|
const char *uri_utf8,
|
||||||
const char *name_utf8)
|
const char *name_utf8)
|
||||||
{
|
{
|
||||||
db_lock();
|
Directory *directory;
|
||||||
Directory *directory = parent.FindChild(name_utf8);
|
{
|
||||||
db_unlock();
|
const ScopeDatabaseLock protect;
|
||||||
|
directory = parent.FindChild(name_utf8);
|
||||||
|
}
|
||||||
|
|
||||||
if (directory != nullptr) {
|
if (directory != nullptr) {
|
||||||
if (directory->IsMount())
|
if (directory->IsMount())
|
||||||
@ -414,13 +414,14 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent,
|
|||||||
|
|
||||||
/* if we're adding directory paths, make sure to delete filenames
|
/* if we're adding directory paths, make sure to delete filenames
|
||||||
with potentially the same name */
|
with potentially the same name */
|
||||||
db_lock();
|
{
|
||||||
Song *conflicting = parent.FindSong(name_utf8);
|
const ScopeDatabaseLock protect;
|
||||||
if (conflicting)
|
Song *conflicting = parent.FindSong(name_utf8);
|
||||||
editor.DeleteSong(parent, conflicting);
|
if (conflicting)
|
||||||
|
editor.DeleteSong(parent, conflicting);
|
||||||
|
|
||||||
directory = parent.CreateChild(name_utf8);
|
directory = parent.CreateChild(name_utf8);
|
||||||
db_unlock();
|
}
|
||||||
|
|
||||||
directory_set_stat(*directory, info);
|
directory_set_stat(*directory, info);
|
||||||
return directory;
|
return directory;
|
||||||
|
Loading…
Reference in New Issue
Block a user