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; 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;
} }

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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 */

View File

@ -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",

View File

@ -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;