db/simple: use class ScopeDatabaseLock

This commit is contained in:
Max Kellermann 2015-12-15 23:27:05 +01:00
parent 7dd3b72a8c
commit e31f0b8b0c
8 changed files with 100 additions and 83 deletions

View File

@ -72,7 +72,6 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
char *line;
unsigned format = 0;
bool found_charset = false, found_version = false;
bool success;
bool tags[TAG_NUM_OF_ITEM_TYPES];
/* get initial info */
@ -152,9 +151,6 @@ db_load_internal(TextFile &file, Directory &music_root, Error &error)
LogDebug(db_domain, "reading DB");
db_lock();
success = directory_load(file, music_root, error);
db_unlock();
return success;
const ScopeDatabaseLock protect;
return directory_load(file, music_root, error);
}

View File

@ -240,13 +240,13 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
assert(prefixed_light_song == nullptr);
assert(borrowed_song_count == 0);
db_lock();
ScopeDatabaseLock protect;
auto r = root->LookupDirectory(uri);
if (r.directory->IsMount()) {
/* pass the request to the mounted database */
db_unlock();
protect.unlock();
const LightSong *song =
r.directory->mounted_database->GetSong(r.uri, error);
@ -260,7 +260,6 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
if (r.uri == nullptr) {
/* it's a directory */
db_unlock();
error.Format(db_domain, DB_NOT_FOUND,
"No such song: %s", uri);
return nullptr;
@ -268,14 +267,13 @@ SimpleDatabase::GetSong(const char *uri, Error &error) const
if (strchr(r.uri, '/') != nullptr) {
/* refers to a URI "below" the actual song */
db_unlock();
error.Format(db_domain, DB_NOT_FOUND,
"No such song: %s", uri);
return nullptr;
}
const Song *song = r.directory->FindSong(r.uri);
db_unlock();
protect.unlock();
if (song == nullptr) {
error.Format(db_domain, DB_NOT_FOUND,
"No such song: %s", uri);
@ -367,15 +365,15 @@ SimpleDatabase::GetStats(const DatabaseSelection &selection,
bool
SimpleDatabase::Save(Error &error)
{
db_lock();
{
const ScopeDatabaseLock protect;
LogDebug(simple_db_domain, "removing empty directories from DB");
root->PruneEmpty();
LogDebug(simple_db_domain, "removing empty directories from DB");
root->PruneEmpty();
LogDebug(simple_db_domain, "sorting DB");
root->Sort();
db_unlock();
LogDebug(simple_db_domain, "sorting DB");
root->Sort();
}
LogDebug(simple_db_domain, "writing DB");

View File

@ -39,6 +39,27 @@
#include <sys/stat.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
UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
{
@ -46,11 +67,9 @@ UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
if (tmp) {
const std::string child_name(name, tmp);
//add dir is not there already
db_lock();
Directory *subdir =
directory.MakeChild(child_name.c_str());
Directory *subdir = LockMakeChild(directory,
child_name.c_str());
subdir->device = DEVICE_INARCHIVE;
db_unlock();
//create directories first
UpdateArchiveTree(*subdir, tmp + 1);
@ -62,15 +81,14 @@ UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
}
//add file
db_lock();
Song *song = directory.FindSong(name);
db_unlock();
Song *song = LockFindSong(directory, name);
if (song == nullptr) {
song = Song::LoadFile(storage, name, directory);
if (song != nullptr) {
db_lock();
directory.AddSong(song);
db_unlock();
{
const ScopeDatabaseLock protect;
directory.AddSong(song);
}
modified = true;
FormatDefault(update_domain, "added %s/%s",
@ -108,9 +126,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
const StorageFileInfo &info,
const ArchivePlugin &plugin)
{
db_lock();
Directory *directory = parent.FindChild(name);
db_unlock();
Directory *directory = LockFindChild(parent, name);
if (directory != nullptr && directory->mtime == info.mtime &&
!walk_discard)
@ -139,12 +155,12 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
if (directory == nullptr) {
FormatDebug(update_domain,
"creating archive directory: %s", name);
db_lock();
const ScopeDatabaseLock protect;
directory = parent.CreateChild(name);
/* mark this directory as archive (we use device for
this) */
directory->device = DEVICE_INARCHIVE;
db_unlock();
}
directory->mtime = info.mtime;

View File

@ -78,16 +78,16 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
return false;
const DecoderPlugin &plugin = *_plugin;
db_lock();
Directory *contdir = MakeDirectoryIfModified(directory, name, info);
if (contdir == nullptr) {
/* not modified */
db_unlock();
return true;
}
Directory *contdir;
{
const ScopeDatabaseLock protect;
contdir = MakeDirectoryIfModified(directory, name, info);
if (contdir == nullptr)
/* not modified */
return true;
contdir->device = DEVICE_CONTAINER;
db_unlock();
contdir->device = DEVICE_CONTAINER;
}
const auto pathname = storage.MapFS(contdir->GetPath());
if (pathname.IsNull()) {
@ -116,9 +116,10 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
tag_builder.Commit(song->tag);
db_lock();
contdir->AddSong(song);
db_unlock();
{
const ScopeDatabaseLock protect;
contdir->AddSong(song);
}
modified = true;

View File

@ -50,9 +50,8 @@ DatabaseEditor::DeleteSong(Directory &dir, Song *del)
void
DatabaseEditor::LockDeleteSong(Directory &parent, Song *song)
{
db_lock();
const ScopeDatabaseLock protect;
DeleteSong(parent, song);
db_unlock();
}
/**
@ -87,17 +86,17 @@ DatabaseEditor::DeleteDirectory(Directory *directory)
void
DatabaseEditor::LockDeleteDirectory(Directory *directory)
{
db_lock();
const ScopeDatabaseLock protect;
DeleteDirectory(directory);
db_unlock();
}
bool
DatabaseEditor::DeleteNameIn(Directory &parent, const char *name)
{
const ScopeDatabaseLock protect;
bool modified = false;
db_lock();
Directory *directory = parent.FindChild(name);
if (directory != nullptr) {
@ -113,7 +112,5 @@ DatabaseEditor::DeleteNameIn(Directory &parent, const char *name)
parent.playlists.erase(name);
db_unlock();
return modified;
}

View File

@ -80,9 +80,11 @@ UpdateService::CancelMount(const char *uri)
/* determine which (mounted) database will be updated and what
storage will be scanned */
db_lock();
const auto lr = db.GetRoot().LookupDirectory(uri);
db_unlock();
Directory::LookupResult lr;
{
const ScopeDatabaseLock protect;
lr = db.GetRoot().LookupDirectory(uri);
}
if (!lr.directory->IsMount())
return;
@ -188,9 +190,12 @@ UpdateService::Enqueue(const char *path, bool discard)
SimpleDatabase *db2;
Storage *storage2;
db_lock();
const auto lr = db.GetRoot().LookupDirectory(path);
db_unlock();
Directory::LookupResult lr;
{
const ScopeDatabaseLock protect;
lr = db.GetRoot().LookupDirectory(path);
}
if (lr.directory->IsMount()) {
/* follow the mountpoint, update the mounted
database */

View File

@ -35,9 +35,11 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
const char *name, const char *suffix,
const StorageFileInfo &info)
{
db_lock();
Song *song = directory.FindSong(name);
db_unlock();
Song *song;
{
const ScopeDatabaseLock protect;
song = directory.FindSong(name);
}
if (!directory_child_access(storage, directory, name, R_OK)) {
FormatError(update_domain,
@ -69,9 +71,10 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
return;
}
db_lock();
directory.AddSong(song);
db_unlock();
{
const ScopeDatabaseLock protect;
directory.AddSong(song);
}
modified = true;
FormatDefault(update_domain, "added %s/%s",

View File

@ -78,7 +78,7 @@ inline void
UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
const ExcludeList &exclude_list)
{
db_lock();
const ScopeDatabaseLock protect;
directory.ForEachChildSafe([&](Directory &child){
const auto name_fs =
@ -99,8 +99,6 @@ UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
modified = true;
}
});
db_unlock();
}
inline void
@ -129,9 +127,8 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory)
i != end;) {
if (!directory_child_is_regular(storage, directory,
i->name.c_str())) {
db_lock();
const ScopeDatabaseLock protect;
i = directory.playlists.erase(i);
db_unlock();
} else
++i;
}
@ -198,10 +195,9 @@ UpdateWalk::UpdatePlaylistFile(Directory &directory,
PlaylistInfo pi(name, info.mtime);
db_lock();
const ScopeDatabaseLock protect;
if (directory.playlists.UpdateOrInsert(std::move(pi)))
modified = true;
db_unlock();
return true;
}
@ -232,9 +228,11 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory,
info.inode, info.device))
return;
db_lock();
Directory *subdir = directory.MakeChild(name);
db_unlock();
Directory *subdir;
{
const ScopeDatabaseLock protect;
subdir = directory.MakeChild(name);
}
assert(&directory == subdir->parent);
@ -393,9 +391,11 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent,
const char *uri_utf8,
const char *name_utf8)
{
db_lock();
Directory *directory = parent.FindChild(name_utf8);
db_unlock();
Directory *directory;
{
const ScopeDatabaseLock protect;
directory = parent.FindChild(name_utf8);
}
if (directory != nullptr) {
if (directory->IsMount())
@ -414,13 +414,14 @@ UpdateWalk::DirectoryMakeChildChecked(Directory &parent,
/* if we're adding directory paths, make sure to delete filenames
with potentially the same name */
db_lock();
Song *conflicting = parent.FindSong(name_utf8);
if (conflicting)
editor.DeleteSong(parent, conflicting);
{
const ScopeDatabaseLock protect;
Song *conflicting = parent.FindSong(name_utf8);
if (conflicting)
editor.DeleteSong(parent, conflicting);
directory = parent.CreateChild(name_utf8);
db_unlock();
directory = parent.CreateChild(name_utf8);
}
directory_set_stat(*directory, info);
return directory;