Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
ef5cf40f
Commit
ef5cf40f
authored
Jan 31, 2012
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
directory: require the caller to lock the db_mutex
Reduce the number of lock/unlock cycles, and make database handling safer.
parent
837bd79b
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
127 additions
and
26 deletions
+127
-26
command.c
src/command.c
+4
-0
database.c
src/database.c
+3
-1
database.h
src/database.h
+3
-0
simple_db_plugin.c
src/db/simple_db_plugin.c
+11
-2
db_save.c
src/db_save.c
+3
-0
directory.c
src/directory.c
+15
-20
directory.h
src/directory.h
+21
-0
song_sticker.h
src/song_sticker.h
+2
-0
update_walk.c
src/update_walk.c
+65
-3
No files found.
src/command.c
View file @
ef5cf40f
...
@@ -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"
);
...
...
src/database.c
View file @
ef5cf40f
...
@@ -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
*
...
...
src/database.h
View file @
ef5cf40f
...
@@ -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
);
...
...
src/db/simple_db_plugin.c
View file @
ef5cf40f
...
@@ -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"
);
...
...
src/db_save.c
View file @
ef5cf40f
...
@@ -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
;
...
...
src/directory.c
View file @
ef5cf40f
...
@@ -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
)
...
...
src/directory.h
View file @
ef5cf40f
...
@@ -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
);
...
...
src/song_sticker.h
View file @
ef5cf40f
...
@@ -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
...
...
src/update_walk.c
View file @
ef5cf40f
...
@@ -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
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment