Commit ef5cf40f authored by Max Kellermann's avatar Max Kellermann

directory: require the caller to lock the db_mutex

Reduce the number of lock/unlock cycles, and make database handling safer.
parent 837bd79b
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "db_error.h" #include "db_error.h"
#include "db_print.h" #include "db_print.h"
#include "db_selection.h" #include "db_selection.h"
#include "db_lock.h"
#include "tag.h" #include "tag.h"
#include "client.h" #include "client.h"
#include "client_idle.h" #include "client_idle.h"
...@@ -1892,8 +1893,10 @@ handle_sticker_song(struct client *client, int argc, char *argv[]) ...@@ -1892,8 +1893,10 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
.name = argv[4], .name = argv[4],
}; };
db_lock();
directory = db_get_directory(argv[3]); directory = db_get_directory(argv[3]);
if (directory == NULL) { if (directory == NULL) {
db_unlock();
command_error(client, ACK_ERROR_NO_EXIST, command_error(client, ACK_ERROR_NO_EXIST,
"no such directory"); "no such directory");
return COMMAND_RETURN_ERROR; return COMMAND_RETURN_ERROR;
...@@ -1901,6 +1904,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[]) ...@@ -1901,6 +1904,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
success = sticker_song_find(directory, data.name, success = sticker_song_find(directory, data.name,
sticker_song_find_print_cb, &data); sticker_song_find_print_cb, &data);
db_unlock();
if (!success) { if (!success) {
command_error(client, ACK_ERROR_SYSTEM, command_error(client, ACK_ERROR_SYSTEM,
"failed to set search sticker database"); "failed to set search sticker database");
......
...@@ -92,7 +92,9 @@ db_get_directory(const char *name) ...@@ -92,7 +92,9 @@ db_get_directory(const char *name)
if (name == NULL) if (name == NULL)
return music_root; return music_root;
return directory_lookup_directory(music_root, name); struct directory *directory =
directory_lookup_directory(music_root, name);
return directory;
} }
struct song * struct song *
......
...@@ -50,6 +50,9 @@ db_finish(void); ...@@ -50,6 +50,9 @@ db_finish(void);
struct directory * struct directory *
db_get_root(void); db_get_root(void);
/**
* Caller must lock the #db_mutex.
*/
gcc_nonnull(1) gcc_nonnull(1)
struct directory * struct directory *
db_get_directory(const char *name); db_get_directory(const char *name);
......
...@@ -59,7 +59,11 @@ simple_db_lookup_directory(const struct simple_db *db, const char *uri) ...@@ -59,7 +59,11 @@ simple_db_lookup_directory(const struct simple_db *db, const char *uri)
assert(db->root != NULL); assert(db->root != NULL);
assert(uri != NULL); assert(uri != NULL);
return directory_lookup_directory(db->root, uri); db_lock();
struct directory *directory =
directory_lookup_directory(db->root, uri);
db_unlock();
return directory;
} }
static struct db * static struct db *
...@@ -236,7 +240,9 @@ simple_db_get_song(struct db *_db, const char *uri, GError **error_r) ...@@ -236,7 +240,9 @@ simple_db_get_song(struct db *_db, const char *uri, GError **error_r)
assert(db->root != NULL); assert(db->root != NULL);
db_lock();
struct song *song = directory_lookup_song(db->root, uri); struct song *song = directory_lookup_song(db->root, uri);
db_unlock();
if (song == NULL) if (song == NULL)
g_set_error(error_r, db_quark(), DB_NOT_FOUND, g_set_error(error_r, db_quark(), DB_NOT_FOUND,
"No such song: %s", uri); "No such song: %s", uri);
...@@ -301,13 +307,16 @@ simple_db_save(struct db *_db, GError **error_r) ...@@ -301,13 +307,16 @@ simple_db_save(struct db *_db, GError **error_r)
struct simple_db *db = (struct simple_db *)_db; struct simple_db *db = (struct simple_db *)_db;
struct directory *music_root = db->root; struct directory *music_root = db->root;
db_lock();
g_debug("removing empty directories from DB"); g_debug("removing empty directories from DB");
directory_prune_empty(music_root); directory_prune_empty(music_root);
g_debug("sorting DB"); g_debug("sorting DB");
directory_sort(music_root); directory_sort(music_root);
db_unlock();
g_debug("writing DB"); g_debug("writing DB");
FILE *fp = fopen(db->path, "w"); FILE *fp = fopen(db->path, "w");
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "db_save.h" #include "db_save.h"
#include "db_lock.h"
#include "directory.h" #include "directory.h"
#include "directory_save.h" #include "directory_save.h"
#include "song.h" #include "song.h"
...@@ -169,7 +170,9 @@ db_load_internal(FILE *fp, struct directory *music_root, GError **error) ...@@ -169,7 +170,9 @@ db_load_internal(FILE *fp, struct directory *music_root, GError **error)
g_debug("reading DB"); g_debug("reading DB");
db_lock();
success = directory_load(fp, music_root, buffer, error); success = directory_load(fp, music_root, buffer, error);
db_unlock();
g_string_free(buffer, true); g_string_free(buffer, true);
return success; return success;
......
...@@ -74,13 +74,11 @@ directory_free(struct directory *directory) ...@@ -74,13 +74,11 @@ directory_free(struct directory *directory)
void void
directory_delete(struct directory *directory) directory_delete(struct directory *directory)
{ {
assert(holding_db_lock());
assert(directory != NULL); assert(directory != NULL);
assert(directory->parent != NULL); assert(directory->parent != NULL);
db_lock();
list_del(&directory->siblings); list_del(&directory->siblings);
db_unlock();
directory_free(directory); directory_free(directory);
} }
...@@ -93,6 +91,7 @@ directory_get_name(const struct directory *directory) ...@@ -93,6 +91,7 @@ directory_get_name(const struct directory *directory)
struct directory * struct directory *
directory_new_child(struct directory *parent, const char *name_utf8) directory_new_child(struct directory *parent, const char *name_utf8)
{ {
assert(holding_db_lock());
assert(parent != NULL); assert(parent != NULL);
assert(name_utf8 != NULL); assert(name_utf8 != NULL);
assert(*name_utf8 != 0); assert(*name_utf8 != 0);
...@@ -111,32 +110,28 @@ directory_new_child(struct directory *parent, const char *name_utf8) ...@@ -111,32 +110,28 @@ directory_new_child(struct directory *parent, const char *name_utf8)
struct directory *directory = directory_new(path_utf8, parent); struct directory *directory = directory_new(path_utf8, parent);
g_free(allocated); g_free(allocated);
db_lock(); list_add(&directory->siblings, &parent->children);
list_add_tail(&directory->siblings, &parent->children);
db_unlock();
return directory; return directory;
} }
struct directory * struct directory *
directory_get_child(const struct directory *directory, const char *name) directory_get_child(const struct directory *directory, const char *name)
{ {
db_lock(); assert(holding_db_lock());
struct directory *child; struct directory *child;
directory_for_each_child(child, directory) { directory_for_each_child(child, directory)
if (strcmp(directory_get_name(child), name) == 0) { if (strcmp(directory_get_name(child), name) == 0)
db_unlock();
return child; return child;
}
}
db_unlock();
return NULL; return NULL;
} }
void void
directory_prune_empty(struct directory *directory) directory_prune_empty(struct directory *directory)
{ {
assert(holding_db_lock());
struct directory *child, *n; struct directory *child, *n;
directory_for_each_child_safe(child, n, directory) { directory_for_each_child_safe(child, n, directory) {
directory_prune_empty(child); directory_prune_empty(child);
...@@ -149,12 +144,14 @@ directory_prune_empty(struct directory *directory) ...@@ -149,12 +144,14 @@ directory_prune_empty(struct directory *directory)
struct directory * struct directory *
directory_lookup_directory(struct directory *directory, const char *uri) directory_lookup_directory(struct directory *directory, const char *uri)
{ {
assert(holding_db_lock());
assert(uri != NULL); assert(uri != NULL);
if (isRootDirectory(uri)) if (isRootDirectory(uri))
return directory; return directory;
char *duplicated = g_strdup(uri), *name = duplicated; char *duplicated = g_strdup(uri), *name = duplicated;
while (1) { while (1) {
char *slash = strchr(name, '/'); char *slash = strchr(name, '/');
if (slash == name) { if (slash == name) {
...@@ -201,21 +198,18 @@ directory_remove_song(G_GNUC_UNUSED struct directory *directory, ...@@ -201,21 +198,18 @@ directory_remove_song(G_GNUC_UNUSED struct directory *directory,
struct song * struct song *
directory_get_song(const struct directory *directory, const char *name_utf8) directory_get_song(const struct directory *directory, const char *name_utf8)
{ {
assert(holding_db_lock());
assert(directory != NULL); assert(directory != NULL);
assert(name_utf8 != NULL); assert(name_utf8 != NULL);
db_lock();
struct song *song; struct song *song;
directory_for_each_song(song, directory) { directory_for_each_song(song, directory) {
assert(song->parent == directory); assert(song->parent == directory);
if (strcmp(song->uri, name_utf8) == 0) { if (strcmp(song->uri, name_utf8) == 0)
db_unlock();
return song; return song;
}
} }
db_unlock();
return NULL; return NULL;
} }
...@@ -224,6 +218,7 @@ directory_lookup_song(struct directory *directory, const char *uri) ...@@ -224,6 +218,7 @@ directory_lookup_song(struct directory *directory, const char *uri)
{ {
char *duplicated, *base; char *duplicated, *base;
assert(holding_db_lock());
assert(directory != NULL); assert(directory != NULL);
assert(uri != NULL); assert(uri != NULL);
...@@ -260,10 +255,10 @@ directory_cmp(G_GNUC_UNUSED void *priv, ...@@ -260,10 +255,10 @@ directory_cmp(G_GNUC_UNUSED void *priv,
void void
directory_sort(struct directory *directory) directory_sort(struct directory *directory)
{ {
db_lock(); assert(holding_db_lock());
list_sort(NULL, &directory->children, directory_cmp); list_sort(NULL, &directory->children, directory_cmp);
song_list_sort(&directory->songs); song_list_sort(&directory->songs);
db_unlock();
struct directory *child; struct directory *child;
directory_for_each_child(child, directory) directory_for_each_child(child, directory)
......
...@@ -118,6 +118,8 @@ directory_free(struct directory *directory); ...@@ -118,6 +118,8 @@ directory_free(struct directory *directory);
/** /**
* Remove this #directory object from its parent and free it. This * Remove this #directory object from its parent and free it. This
* must not be called with the root directory. * must not be called with the root directory.
*
* Caller must lock the #db_mutex.
*/ */
void void
directory_delete(struct directory *directory); directory_delete(struct directory *directory);
...@@ -152,6 +154,9 @@ G_GNUC_PURE ...@@ -152,6 +154,9 @@ G_GNUC_PURE
const char * const char *
directory_get_name(const struct directory *directory); directory_get_name(const struct directory *directory);
/**
* Caller must lock the #db_mutex.
*/
G_GNUC_PURE G_GNUC_PURE
struct directory * struct directory *
directory_get_child(const struct directory *directory, const char *name); directory_get_child(const struct directory *directory, const char *name);
...@@ -159,6 +164,8 @@ directory_get_child(const struct directory *directory, const char *name); ...@@ -159,6 +164,8 @@ directory_get_child(const struct directory *directory, const char *name);
/** /**
* Create a new #directory object as a child of the given one. * Create a new #directory object as a child of the given one.
* *
* Caller must lock the #db_mutex.
*
* @param parent the parent directory the new one will be added to * @param parent the parent directory the new one will be added to
* @param name_utf8 the UTF-8 encoded name of the new sub directory * @param name_utf8 the UTF-8 encoded name of the new sub directory
*/ */
...@@ -169,6 +176,8 @@ directory_new_child(struct directory *parent, const char *name_utf8); ...@@ -169,6 +176,8 @@ directory_new_child(struct directory *parent, const char *name_utf8);
/** /**
* Look up a sub directory, and create the object if it does not * Look up a sub directory, and create the object if it does not
* exist. * exist.
*
* Caller must lock the #db_mutex.
*/ */
static inline struct directory * static inline struct directory *
directory_make_child(struct directory *directory, const char *name_utf8) directory_make_child(struct directory *directory, const char *name_utf8)
...@@ -179,6 +188,9 @@ directory_make_child(struct directory *directory, const char *name_utf8) ...@@ -179,6 +188,9 @@ directory_make_child(struct directory *directory, const char *name_utf8)
return child; return child;
} }
/**
* Caller must lock the #db_mutex.
*/
void void
directory_prune_empty(struct directory *directory); directory_prune_empty(struct directory *directory);
...@@ -209,6 +221,8 @@ directory_remove_song(struct directory *directory, struct song *song); ...@@ -209,6 +221,8 @@ directory_remove_song(struct directory *directory, struct song *song);
/** /**
* Look up a song in this directory by its name. * Look up a song in this directory by its name.
*
* Caller must lock the #db_mutex.
*/ */
G_GNUC_PURE G_GNUC_PURE
struct song * struct song *
...@@ -217,6 +231,8 @@ directory_get_song(const struct directory *directory, const char *name_utf8); ...@@ -217,6 +231,8 @@ directory_get_song(const struct directory *directory, const char *name_utf8);
/** /**
* Looks up a song by its relative URI. * Looks up a song by its relative URI.
* *
* Caller must lock the #db_mutex.
*
* @param directory the parent (or grandparent, ...) directory * @param directory the parent (or grandparent, ...) directory
* @param uri the relative URI * @param uri the relative URI
* @return the song, or NULL if none was found * @return the song, or NULL if none was found
...@@ -224,6 +240,11 @@ directory_get_song(const struct directory *directory, const char *name_utf8); ...@@ -224,6 +240,11 @@ directory_get_song(const struct directory *directory, const char *name_utf8);
struct song * struct song *
directory_lookup_song(struct directory *directory, const char *uri); directory_lookup_song(struct directory *directory, const char *uri);
/**
* Sort all directory entries recursively.
*
* Caller must lock the #db_mutex.
*/
void void
directory_sort(struct directory *directory); directory_sort(struct directory *directory);
......
...@@ -68,6 +68,8 @@ sticker_song_get(const struct song *song); ...@@ -68,6 +68,8 @@ sticker_song_get(const struct song *song);
* Finds stickers with the specified name below the specified * Finds stickers with the specified name below the specified
* directory. * directory.
* *
* Caller must lock the #db_mutex.
*
* @param directory the base directory to search in * @param directory the base directory to search in
* @param name the name of the sticker * @param name the name of the sticker
* @return true on success (even if no sticker was found), false on * @return true on success (even if no sticker was found), false on
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "config.h" /* must be first for large file support */ #include "config.h" /* must be first for large file support */
#include "update_internal.h" #include "update_internal.h"
#include "database.h" #include "database.h"
#include "db_lock.h"
#include "exclude.h" #include "exclude.h"
#include "directory.h" #include "directory.h"
#include "song.h" #include "song.h"
...@@ -89,6 +90,9 @@ directory_set_stat(struct directory *dir, const struct stat *st) ...@@ -89,6 +90,9 @@ directory_set_stat(struct directory *dir, const struct stat *st)
dir->have_stat = true; dir->have_stat = true;
} }
/**
* Caller must lock the #db_mutex.
*/
static void static void
delete_song(struct directory *dir, struct song *del) delete_song(struct directory *dir, struct song *del)
{ {
...@@ -97,11 +101,15 @@ delete_song(struct directory *dir, struct song *del) ...@@ -97,11 +101,15 @@ delete_song(struct directory *dir, struct song *del)
/* first, prevent traversers in main task from getting this */ /* first, prevent traversers in main task from getting this */
directory_remove_song(dir, del); directory_remove_song(dir, del);
db_unlock(); /* temporary unlock, because update_remove_song() blocks */
/* now take it out of the playlist (in the main_task) */ /* now take it out of the playlist (in the main_task) */
update_remove_song(del); update_remove_song(del);
/* finally, all possible references gone, free it */ /* finally, all possible references gone, free it */
song_free(del); song_free(del);
db_lock();
} }
static void static void
...@@ -110,6 +118,8 @@ delete_directory(struct directory *directory); ...@@ -110,6 +118,8 @@ delete_directory(struct directory *directory);
/** /**
* Recursively remove all sub directories and songs from a directory, * Recursively remove all sub directories and songs from a directory,
* leaving an empty directory. * leaving an empty directory.
*
* Caller must lock the #db_mutex.
*/ */
static void static void
clear_directory(struct directory *directory) clear_directory(struct directory *directory)
...@@ -127,6 +137,8 @@ clear_directory(struct directory *directory) ...@@ -127,6 +137,8 @@ clear_directory(struct directory *directory)
/** /**
* Recursively free a directory and all its contents. * Recursively free a directory and all its contents.
*
* Caller must lock the #db_mutex.
*/ */
static void static void
delete_directory(struct directory *directory) delete_directory(struct directory *directory)
...@@ -134,12 +146,14 @@ delete_directory(struct directory *directory) ...@@ -134,12 +146,14 @@ delete_directory(struct directory *directory)
assert(directory->parent != NULL); assert(directory->parent != NULL);
clear_directory(directory); clear_directory(directory);
directory_delete(directory); directory_delete(directory);
} }
static void static void
delete_name_in(struct directory *parent, const char *name) delete_name_in(struct directory *parent, const char *name)
{ {
db_lock();
struct directory *directory = directory_get_child(parent, name); struct directory *directory = directory_get_child(parent, name);
if (directory != NULL) { if (directory != NULL) {
...@@ -153,6 +167,8 @@ delete_name_in(struct directory *parent, const char *name) ...@@ -153,6 +167,8 @@ delete_name_in(struct directory *parent, const char *name)
modified = true; modified = true;
} }
db_unlock();
playlist_vector_remove(&parent->playlists, name); playlist_vector_remove(&parent->playlists, name);
} }
...@@ -160,6 +176,8 @@ static void ...@@ -160,6 +176,8 @@ static void
remove_excluded_from_directory(struct directory *directory, remove_excluded_from_directory(struct directory *directory,
GSList *exclude_list) GSList *exclude_list)
{ {
db_lock();
struct directory *child, *n; struct directory *child, *n;
directory_for_each_child_safe(child, n, directory) { directory_for_each_child_safe(child, n, directory) {
char *name_fs = utf8_to_fs_charset(directory_get_name(child)); char *name_fs = utf8_to_fs_charset(directory_get_name(child));
...@@ -184,6 +202,8 @@ remove_excluded_from_directory(struct directory *directory, ...@@ -184,6 +202,8 @@ remove_excluded_from_directory(struct directory *directory,
g_free(name_fs); g_free(name_fs);
} }
db_unlock();
} }
static bool static bool
...@@ -232,7 +252,10 @@ removeDeletedFromDirectory(struct directory *directory) ...@@ -232,7 +252,10 @@ removeDeletedFromDirectory(struct directory *directory)
if (directory_exists(child)) if (directory_exists(child))
continue; continue;
db_lock();
delete_directory(child); delete_directory(child);
db_unlock();
modified = true; modified = true;
} }
...@@ -242,7 +265,10 @@ removeDeletedFromDirectory(struct directory *directory) ...@@ -242,7 +265,10 @@ removeDeletedFromDirectory(struct directory *directory)
struct stat st; struct stat st;
if ((path = map_song_fs(song)) == NULL || if ((path = map_song_fs(song)) == NULL ||
stat(path, &st) < 0 || !S_ISREG(st.st_mode)) { stat(path, &st) < 0 || !S_ISREG(st.st_mode)) {
db_lock();
delete_song(directory, song); delete_song(directory, song);
db_unlock();
modified = true; modified = true;
} }
...@@ -344,8 +370,10 @@ update_archive_tree(struct directory *directory, char *name) ...@@ -344,8 +370,10 @@ update_archive_tree(struct directory *directory, char *name)
if (tmp) { if (tmp) {
*tmp = 0; *tmp = 0;
//add dir is not there already //add dir is not there already
db_lock();
subdir = directory_make_child(directory, name); subdir = directory_make_child(directory, name);
subdir->device = DEVICE_INARCHIVE; subdir->device = DEVICE_INARCHIVE;
db_unlock();
//create directories first //create directories first
update_archive_tree(subdir, tmp+1); update_archive_tree(subdir, tmp+1);
} else { } else {
...@@ -354,7 +382,9 @@ update_archive_tree(struct directory *directory, char *name) ...@@ -354,7 +382,9 @@ update_archive_tree(struct directory *directory, char *name)
return; return;
} }
//add file //add file
db_lock();
struct song *song = directory_get_song(directory, name); struct song *song = directory_get_song(directory, name);
db_unlock();
if (song == NULL) { if (song == NULL) {
song = song_file_load(name, directory); song = song_file_load(name, directory);
if (song != NULL) { if (song != NULL) {
...@@ -386,7 +416,9 @@ update_archive_file(struct directory *parent, const char *name, ...@@ -386,7 +416,9 @@ update_archive_file(struct directory *parent, const char *name,
struct directory *directory; struct directory *directory;
char *filepath; char *filepath;
db_lock();
directory = directory_get_child(parent, name); directory = directory_get_child(parent, name);
db_unlock();
if (directory != NULL && directory->mtime == st->st_mtime && if (directory != NULL && directory->mtime == st->st_mtime &&
!walk_discard) !walk_discard)
/* MPD has already scanned the archive, and it hasn't /* MPD has already scanned the archive, and it hasn't
...@@ -409,10 +441,12 @@ update_archive_file(struct directory *parent, const char *name, ...@@ -409,10 +441,12 @@ update_archive_file(struct directory *parent, const char *name,
if (directory == NULL) { if (directory == NULL) {
g_debug("creating archive directory: %s", name); g_debug("creating archive directory: %s", name);
db_lock();
directory = directory_new_child(parent, name); directory = directory_new_child(parent, 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 = st->st_mtime; directory->mtime = st->st_mtime;
...@@ -438,6 +472,8 @@ update_container_file( struct directory* directory, ...@@ -438,6 +472,8 @@ update_container_file( struct directory* directory,
char* vtrack = NULL; char* vtrack = NULL;
unsigned int tnum = 0; unsigned int tnum = 0;
char* pathname = map_directory_child_fs(directory, name); char* pathname = map_directory_child_fs(directory, name);
db_lock();
struct directory *contdir = directory_get_child(directory, name); struct directory *contdir = directory_get_child(directory, name);
// directory exists already // directory exists already
...@@ -454,6 +490,7 @@ update_container_file( struct directory* directory, ...@@ -454,6 +490,7 @@ update_container_file( struct directory* directory,
modified = true; modified = true;
} }
else { else {
db_unlock();
g_free(pathname); g_free(pathname);
return true; return true;
} }
...@@ -462,6 +499,7 @@ update_container_file( struct directory* directory, ...@@ -462,6 +499,7 @@ update_container_file( struct directory* directory,
contdir = directory_make_child(directory, name); contdir = directory_make_child(directory, name);
contdir->mtime = st->st_mtime; contdir->mtime = st->st_mtime;
contdir->device = DEVICE_CONTAINER; contdir->device = DEVICE_CONTAINER;
db_unlock();
while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL)
{ {
...@@ -489,7 +527,9 @@ update_container_file( struct directory* directory, ...@@ -489,7 +527,9 @@ update_container_file( struct directory* directory,
if (tnum == 1) if (tnum == 1)
{ {
db_lock();
delete_directory(contdir); delete_directory(contdir);
db_unlock();
return false; return false;
} }
else else
...@@ -536,13 +576,19 @@ update_regular_file(struct directory *directory, ...@@ -536,13 +576,19 @@ update_regular_file(struct directory *directory,
if ((plugin = decoder_plugin_from_suffix(suffix, false)) != NULL) if ((plugin = decoder_plugin_from_suffix(suffix, false)) != NULL)
{ {
db_lock();
struct song *song = directory_get_song(directory, name); struct song *song = directory_get_song(directory, name);
db_unlock();
if (!directory_child_access(directory, name, R_OK)) { if (!directory_child_access(directory, name, R_OK)) {
g_warning("no read permissions on %s/%s", g_warning("no read permissions on %s/%s",
directory_get_path(directory), name); directory_get_path(directory), name);
if (song != NULL) if (song != NULL) {
db_lock();
delete_song(directory, song); delete_song(directory, song);
db_unlock();
}
return; return;
} }
...@@ -552,8 +598,11 @@ update_regular_file(struct directory *directory, ...@@ -552,8 +598,11 @@ update_regular_file(struct directory *directory,
{ {
if (update_container_file(directory, name, st, plugin)) if (update_container_file(directory, name, st, plugin))
{ {
if (song != NULL) if (song != NULL) {
db_lock();
delete_song(directory, song); delete_song(directory, song);
db_unlock();
}
return; return;
} }
...@@ -579,7 +628,9 @@ update_regular_file(struct directory *directory, ...@@ -579,7 +628,9 @@ update_regular_file(struct directory *directory,
if (!song_file_update(song)) { if (!song_file_update(song)) {
g_debug("deleting unrecognized file %s/%s", g_debug("deleting unrecognized file %s/%s",
directory_get_path(directory), name); directory_get_path(directory), name);
db_lock();
delete_song(directory, song); delete_song(directory, song);
db_unlock();
} }
modified = true; modified = true;
...@@ -614,12 +665,18 @@ updateInDirectory(struct directory *directory, ...@@ -614,12 +665,18 @@ updateInDirectory(struct directory *directory,
if (inodeFoundInParent(directory, st->st_ino, st->st_dev)) if (inodeFoundInParent(directory, st->st_ino, st->st_dev))
return; return;
db_lock();
subdir = directory_make_child(directory, name); subdir = directory_make_child(directory, name);
db_unlock();
assert(directory == subdir->parent); assert(directory == subdir->parent);
ret = updateDirectory(subdir, st); ret = updateDirectory(subdir, st);
if (!ret) if (!ret) {
db_lock();
delete_directory(subdir); delete_directory(subdir);
db_unlock();
}
} else { } else {
g_debug("update: %s is not a directory, archive or music", name); g_debug("update: %s is not a directory, archive or music", name);
} }
...@@ -778,7 +835,9 @@ directory_make_child_checked(struct directory *parent, const char *name_utf8) ...@@ -778,7 +835,9 @@ directory_make_child_checked(struct directory *parent, const char *name_utf8)
struct directory *directory; struct directory *directory;
struct stat st; struct stat st;
db_lock();
directory = directory_get_child(parent, name_utf8); directory = directory_get_child(parent, name_utf8);
db_unlock();
if (directory != NULL) if (directory != NULL)
return directory; return directory;
...@@ -788,11 +847,14 @@ directory_make_child_checked(struct directory *parent, const char *name_utf8) ...@@ -788,11 +847,14 @@ directory_make_child_checked(struct directory *parent, const char *name_utf8)
/* 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();
struct song *conflicting = directory_get_song(parent, name_utf8); struct song *conflicting = directory_get_song(parent, name_utf8);
if (conflicting) if (conflicting)
delete_song(parent, conflicting); delete_song(parent, conflicting);
directory = directory_new_child(parent, name_utf8); directory = directory_new_child(parent, name_utf8);
db_unlock();
directory_set_stat(directory, &st); directory_set_stat(directory, &st);
return directory; return directory;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment