From 53d503ce75eb1d9439cfb75053d3cff4cbca6ff9 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sat, 13 Oct 2007 18:30:33 +0200 Subject: [PATCH 1/1] Replace struct table_info by struct afs_table. This is a much cleaner approach and it simplifies afs.c a bit. --- afs.c | 156 ++++++++++++++++++++++++---------------------------- afs.h | 42 +++++++++----- aft.c | 32 +++++++---- attribute.c | 28 +++++++--- blob.c | 51 +++++++++++------ mood.c | 6 +- playlist.c | 2 +- score.c | 39 +++++++------ server.ggo | 22 +++----- 9 files changed, 211 insertions(+), 167 deletions(-) diff --git a/afs.c b/afs.c index 17557e5e..95f6b311 100644 --- a/afs.c +++ b/afs.c @@ -10,6 +10,7 @@ #include #include "server.cmdline.h" #include "para.h" +#include "string.h" #include "afh.h" #include "server.h" #include "error.h" @@ -19,7 +20,6 @@ #include "net.h" #include "afs.h" #include "ipc.h" -#include "string.h" #include "list.h" #include "sched.h" #include "signal.h" @@ -53,7 +53,15 @@ enum afs_table_num { NUM_AFS_TABLES }; -static struct table_info afs_tables[NUM_AFS_TABLES]; +static struct afs_table afs_tables[NUM_AFS_TABLES] = { + [TBLNUM_AUDIO_FILES] = {.init = aft_init}, + [TBLNUM_ATTRIBUTES] = {.init = attribute_init}, + [TBLNUM_SCORES] = {.init = score_init}, + [TBLNUM_MOODS] = {.init = moods_init}, + [TBLNUM_LYRICS] = {.init = lyrics_init}, + [TBLNUM_IMAGES] = {.init = images_init}, + [TBLNUM_PLAYLIST] = {.init = playlists_init}, +}; struct command_task { /** The file descriptor for the local socket. */ @@ -460,26 +468,29 @@ int close_audio_file(struct audio_file_data *afd) static enum play_mode init_admissible_files(void) { - int ret; - - if (conf.mood_given) { - ret = change_current_mood(conf.mood_arg); - if (ret >= 0) { - if (conf.playlist_given) - PARA_WARNING_LOG("ignoring playlist %s\n", - conf.playlist_arg); - return PLAY_MODE_MOOD; + int ret = 0; + char *arg = conf.afs_initial_mode_arg; + + if (conf.afs_initial_mode_given) { + if (!strncmp(arg, "p:", 2)) { + ret = playlist_open(arg + 2); + if (ret >= 0) + return PLAY_MODE_PLAYLIST; + goto dummy; } + if (!strncmp(arg, "m:", 2)) { + ret = change_current_mood(arg + 2); + if (ret >= 0) + return PLAY_MODE_MOOD; + goto dummy; + } + PARA_ERROR_LOG("bad afs initial mode arg: %s\n", arg); } - if (conf.playlist_given) { - ret = playlist_open(conf.playlist_arg); - if (ret >= 0) - return PLAY_MODE_PLAYLIST; - } - ret = change_current_mood(NULL); /* open first available mood */ - if (ret >= 0) - return PLAY_MODE_MOOD; - change_current_mood(""); /* open dummy mood, always successful */ +dummy: + if (ret < 0) + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + PARA_NOTICE_LOG("defaulting to dummy mood\n"); + change_current_mood(""); /* always successful */ return PLAY_MODE_MOOD; } @@ -505,26 +516,18 @@ static int setup_command_socket_or_die(void) return ret; } -static void close_afs_tables(enum osl_close_flags flags) +static void close_afs_tables(void) { + int i; PARA_NOTICE_LOG("closing afs_tables\n"); - score_shutdown(flags); - attribute_shutdown(flags); - close_current_mood(); - playlist_close(); - moods_shutdown(flags); - playlists_shutdown(flags); - lyrics_shutdown(flags); - images_shutdown(flags); - aft_shutdown(flags); + for (i = 0; i < NUM_AFS_TABLES; i++) + afs_tables[i].close(); } static char *database_dir; -static int make_database_dir(void) +static void get_database_dir(void) { - int ret; - if (!database_dir) { if (conf.afs_database_dir_given) database_dir = para_strdup(conf.afs_database_dir_arg); @@ -536,56 +539,36 @@ static int make_database_dir(void) } } PARA_INFO_LOG("afs_database dir %s\n", database_dir); +} + +static int make_database_dir(void) +{ + int ret; + + get_database_dir(); ret = para_mkdir(database_dir, 0777); if (ret >= 0 || is_errno(-ret, EEXIST)) return 1; - free(database_dir); - database_dir = NULL; return ret; } - static int open_afs_tables(void) { - int ret = make_database_dir(); + int i, ret; - if (ret < 0) - return ret; - ret = attribute_init(&afs_tables[TBLNUM_ATTRIBUTES], database_dir); - if (ret < 0) + get_database_dir(); + for (i = 0; i < NUM_AFS_TABLES; i++) { + ret = afs_tables[i].open(database_dir); + if (ret >= 0) + continue; + PARA_ERROR_LOG("%s init: %s\n", afs_tables[i].name, + PARA_STRERROR(-ret)); + } + if (ret >= 0) return ret; - ret = moods_init(&afs_tables[TBLNUM_MOODS], database_dir); - if (ret < 0) - goto moods_init_error; - ret = playlists_init(&afs_tables[TBLNUM_PLAYLIST], database_dir); - if (ret < 0) - goto playlists_init_error; - ret = lyrics_init(&afs_tables[TBLNUM_LYRICS], database_dir); - if (ret < 0) - goto lyrics_init_error; - ret = images_init(&afs_tables[TBLNUM_IMAGES], database_dir); - if (ret < 0) - goto images_init_error; - ret = score_init(&afs_tables[TBLNUM_SCORES], database_dir); - if (ret < 0) - goto score_init_error; - ret = aft_init(&afs_tables[TBLNUM_AUDIO_FILES], database_dir); - if (ret < 0) - goto aft_init_error; - return 1; - -aft_init_error: - score_shutdown(OSL_MARK_CLEAN); -score_init_error: - images_shutdown(OSL_MARK_CLEAN); -images_init_error: - lyrics_shutdown(OSL_MARK_CLEAN); -lyrics_init_error: - playlists_shutdown(OSL_MARK_CLEAN); -playlists_init_error: - moods_shutdown(OSL_MARK_CLEAN); -moods_init_error: - attribute_shutdown(OSL_MARK_CLEAN); + do + afs_tables[i].close(); + while (i--); return ret; } @@ -617,7 +600,7 @@ static void signal_post_select(struct sched *s, struct task *t) if (st->signum == SIGUSR1) return; /* ignore SIGUSR1 */ if (st->signum == SIGHUP) { - close_afs_tables(OSL_MARK_CLEAN); + close_afs_tables(); t->ret = open_afs_tables(); return; } @@ -818,9 +801,11 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd) { enum play_mode current_play_mode; struct sched s; - int ret; + int i, ret; INIT_LIST_HEAD(&afs_client_list); + for (i = 0; i < NUM_AFS_TABLES; i++) + afs_tables[i].init(&afs_tables[i]); ret = open_afs_tables(); if (ret < 0) { @@ -840,7 +825,7 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd) ret = sched(&s); if (ret < 0) PARA_EMERG_LOG("%s\n", PARA_STRERROR(-ret)); - close_afs_tables(OSL_MARK_CLEAN); + close_afs_tables(); exit(EXIT_FAILURE); } @@ -850,15 +835,15 @@ static int create_tables_callback(const struct osl_object *query, uint32_t table_mask = *(uint32_t *)query->data; int i, ret; - close_afs_tables(OSL_MARK_CLEAN); + close_afs_tables(); for (i = 0; i < NUM_AFS_TABLES; i++) { - struct table_info *ti = afs_tables + i; + struct afs_table *t = &afs_tables[i]; - if (ti->flags & TBLFLAG_SKIP_CREATE) - continue; if (!(table_mask & (1 << i))) continue; - ret = osl_create_table(ti->desc); + if (!t->create) + continue; + ret = t->create(database_dir); if (ret < 0) return ret; } @@ -873,15 +858,16 @@ int com_init(int fd, int argc, char * const * const argv) struct osl_object query = {.data = &table_mask, .size = sizeof(table_mask)}; + ret = make_database_dir(); + if (ret < 0) + return ret; if (argc != 1) { table_mask = 0; for (i = 1; i < argc; i++) { for (j = 0; j < NUM_AFS_TABLES; j++) { - struct table_info *ti = afs_tables + j; + struct afs_table *t = &afs_tables[j]; - if (ti->flags & TBLFLAG_SKIP_CREATE) - continue; - if (strcmp(argv[i], ti->desc->name)) + if (strcmp(argv[i], t->name)) continue; table_mask |= (1 << j); break; diff --git a/afs.h b/afs.h index ab2db3aa..1399b2ab 100644 --- a/afs.h +++ b/afs.h @@ -26,11 +26,31 @@ struct afs_info { uint8_t audio_format_id; }; -enum afs_table_flags {TBLFLAG_SKIP_CREATE}; +enum afs_events { + AFSI_CHANGE, + AFHI_CHANGE, + AUDIO_FILE_RENAME, + AUDIO_FILE_ADD, + AUDIO_FILE_REMOVE, + AUDIO_FILE_STREAMED, + ATTRIBUTE_ADD, + ATTRIBUTE_RENAME, + ATTRIBUTE_DELETE, + LYRICS_DELETE, + IMAGE_DELETE, + LYRICS_RENAME, + IMAGE_RENAME, -struct table_info { - const struct osl_table_description *desc; - enum afs_table_flags flags; +}; + +struct afs_table { + void (*init)(struct afs_table *t); + const char *name; + int (*open)(const char *base_dir); + void (*close)(void); + int (*create)(const char *); + int (*event_handler)(enum afs_events event, struct para_buffer *pb, void *data); + /* int *(check)() */ }; enum play_mode {PLAY_MODE_MOOD, PLAY_MODE_PLAYLIST}; @@ -92,8 +112,7 @@ int close_audio_file(struct audio_file_data *afd); int for_each_matching_row(struct pattern_match_data *pmd); /* score */ -int score_init(struct table_info *ti, const char *db); -void score_shutdown(enum osl_close_flags flags); +void score_init(struct afs_table *t); int admissible_file_loop(void *data, osl_rbtree_loop_func *func); int admissible_file_loop_reverse(void *data, osl_rbtree_loop_func *func); int score_get_best(struct osl_row **aft_row, long *score); @@ -105,15 +124,13 @@ int score_delete(const struct osl_row *aft_row); int row_belongs_to_score_table(const struct osl_row *aft_row); /* attribute */ -int attribute_init(struct table_info *ti, const char *db); -void attribute_shutdown(enum osl_close_flags flags); +void attribute_init(struct afs_table *t); void get_attribute_bitmap(const uint64_t *atts, char *buf); /* needed by com_ls() */ int get_attribute_bitnum_by_name(const char *att_name, unsigned char *bitnum); int get_attribute_text(uint64_t *atts, const char *delim, char **text); /* aft */ -int aft_init(struct table_info *ti, const char *db); -void aft_shutdown(enum osl_close_flags flags); +void aft_init(struct afs_table *t); int aft_get_row_of_path(const char *path, struct osl_row **row); int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data *afd); int load_afsi(struct afs_info *afsi, struct osl_object *obj); @@ -128,7 +145,6 @@ int aft_check_callback(const struct osl_object *query, struct osl_object *result /* mood */ int change_current_mood(char *mood_name); -void close_current_mood(void); int mood_update_audio_file(const struct osl_row *aft_row, struct afs_info *old_afsi); int reload_current_mood(void); int mood_delete_audio_file(const struct osl_row *aft_row); @@ -138,7 +154,6 @@ int mood_check_callback(__a_unused const struct osl_object *query, /* playlist */ int playlist_open(char *name); -void playlist_close(void); int playlist_update_audio_file(struct osl_row *aft_row); int playlist_check_callback(__a_unused const struct osl_object *query, struct osl_object *result); @@ -148,8 +163,7 @@ int playlist_check_callback(__a_unused const struct osl_object *query, #define DECLARE_BLOB_SYMBOLS(table_name, cmd_prefix) \ - int table_name ## _init(struct table_info *ti, const char *db); \ - void table_name ## _shutdown(enum osl_close_flags flags); \ + void table_name ## _init(struct afs_table *t); \ int cmd_prefix ## _get_name_by_id(uint32_t id, char **name); \ int cmd_prefix ## _get_def_by_id(uint32_t id, struct osl_object *def); \ int cmd_prefix ## _get_name_and_def_by_row(const struct osl_row *row, \ diff --git a/aft.c b/aft.c index 5112affa..c63ab471 100644 --- a/aft.c +++ b/aft.c @@ -8,12 +8,12 @@ #include "para.h" #include "error.h" +#include "string.h" #include #include #include "afh.h" #include "afs.h" #include "net.h" -#include "string.h" #include "vss.h" static struct osl_table *audio_file_table; @@ -2182,29 +2182,27 @@ int aft_check_callback(__a_unused const struct osl_object *query, struct osl_obj * * \sa osl_close_table(). */ -void aft_shutdown(enum osl_close_flags flags) +static void aft_close(void) { - osl_close_table(audio_file_table, flags); + osl_close_table(audio_file_table, OSL_MARK_CLEAN); audio_file_table = NULL; } /** * Open the audio file table. * - * \param ti Gets initialized by this function. - * \param db The database directory. + * \param dir The database directory. * - * \return Positive on success, negative on errors. + * \return Standard. * * \sa osl_open_table(). */ -int aft_init(struct table_info *ti, const char *db) +static int aft_open(const char *dir) { int ret; - audio_file_table_desc.dir = db; - ti->desc = &audio_file_table_desc; - ret = osl_open_table(ti->desc, &audio_file_table); + audio_file_table_desc.dir = dir; + ret = osl_open_table(&audio_file_table_desc, &audio_file_table); if (ret >= 0) { unsigned num; osl_get_num_rows(audio_file_table, &num); @@ -2217,3 +2215,17 @@ int aft_init(struct table_info *ti, const char *db) return 1; return ret; } + +static int aft_create(const char *dir) +{ + audio_file_table_desc.dir = dir; + return osl_create_table(&audio_file_table_desc); +} + +void aft_init(struct afs_table *t) +{ + t->name = audio_file_table_desc.name; + t->open = aft_open; + t->close = aft_close; + t->create = aft_create; +} diff --git a/attribute.c b/attribute.c index e0e0bd86..48f108c7 100644 --- a/attribute.c +++ b/attribute.c @@ -7,9 +7,9 @@ /** \file attribute.c Attribute handling functions. */ #include "para.h" #include "error.h" +#include "string.h" #include "afh.h" #include "afs.h" -#include "string.h" #include "net.h" static struct osl_table *attribute_table; @@ -532,9 +532,9 @@ err: * * \sa osl_close_table(). */ -void attribute_shutdown(enum osl_close_flags flags) +void attribute_close(void) { - osl_close_table(attribute_table, flags); + osl_close_table(attribute_table, OSL_MARK_CLEAN); attribute_table = NULL; } @@ -548,13 +548,12 @@ void attribute_shutdown(enum osl_close_flags flags) * * \sa osl_open_table(). */ -int attribute_init(struct table_info *ti, const char *db) +static int attribute_open(const char *dir) { int ret; - attribute_table_desc.dir = db; - ti->desc = &attribute_table_desc; - ret = osl_open_table(ti->desc, &attribute_table); + attribute_table_desc.dir = dir; + ret = osl_open_table(&attribute_table_desc, &attribute_table); greatest_att_bitnum = -1; /* no atts available */ if (ret >= 0) { find_greatest_att_bitnum(); @@ -565,3 +564,18 @@ int attribute_init(struct table_info *ti, const char *db) return 1; return ret; } + +static int attribute_create(const char *dir) +{ + attribute_table_desc.dir = dir; + return osl_create_table(&attribute_table_desc); +} + + +void attribute_init(struct afs_table *t) +{ + t->name = attribute_table_desc.name; + t->open = attribute_open; + t->close = attribute_close; + t->create = attribute_create; +} diff --git a/blob.c b/blob.c index 9282b5f5..3c877744 100644 --- a/blob.c +++ b/blob.c @@ -9,9 +9,9 @@ #include #include "para.h" #include "error.h" +#include "string.h" #include "afh.h" #include "afs.h" -#include "string.h" #include "net.h" static struct osl_column_description blob_cols[] = { @@ -452,41 +452,62 @@ static int blob_get_name_and_def_by_row(struct osl_table *table, row, name, def); \ } -/** Define the \p shutdown function for this blob type. */ -#define DEFINE_BLOB_SHUTDOWN(table_name) \ - void table_name ## _shutdown(enum osl_close_flags flags) \ +/** Define the \p close function for this blob type. */ +#define DEFINE_BLOB_CLOSE(table_name) \ + void table_name ## _close(void) \ { \ - osl_close_table(table_name ## _table, flags); \ + osl_close_table(table_name ## _table, OSL_MARK_CLEAN); \ table_name ## _table = NULL; \ } -static int blob_init(struct osl_table **table, +/** Define the \p create function for this blob type. */ +#define DEFINE_BLOB_CREATE(table_name) \ + int table_name ## _create(const char *dir) \ + { \ + table_name ## _table_desc.dir = dir; \ + return osl_create_table(&table_name ## _table_desc); \ + } + +static int blob_open(struct osl_table **table, struct osl_table_description *desc, - struct table_info *ti, const char *db) + const char *dir) { int ret; - desc->dir = db; - ti->desc = desc; - ret = osl_open_table(ti->desc, table); + desc->dir = dir; + ret = osl_open_table(desc, table); if (ret >= 0) return ret; *table = NULL; - if (ret >= 0 || is_errno(-ret, -ENOENT)) + if (ret >= 0 || is_errno(-ret, ENOENT)) return 1; return ret; } +#define DEFINE_BLOB_OPEN(table_name) \ + int table_name ## _open(const char *dir) \ + { \ + return blob_open(&table_name ## _table, \ + &table_name ## _table_desc, dir); \ + } + + /** Define the \p init function for this blob type. */ #define DEFINE_BLOB_INIT(table_name) \ - int table_name ## _init(struct table_info *ti, const char *db) \ + void table_name ## _init(struct afs_table *t) \ { \ - return blob_init(&table_name ## _table, \ - &table_name ## _table_desc, ti, db); \ + t->name = table_name ## _table_desc.name; \ + t->open = table_name ## _open; \ + t->close = table_name ## _close; \ + t->create = table_name ## _create;\ } /** Define all functions for this blob type. */ #define DEFINE_BLOB_FUNCTIONS(table_name, cmd_prefix) \ + DEFINE_BLOB_OPEN(table_name) \ + DEFINE_BLOB_CLOSE(table_name) \ + DEFINE_BLOB_CREATE(table_name) \ + DEFINE_BLOB_INIT(table_name) \ DEFINE_BLOB_COMMAND(ls, table_name, cmd_prefix) \ DEFINE_BLOB_COMMAND(cat, table_name, cmd_prefix) \ DEFINE_BLOB_COMMAND(add, table_name, cmd_prefix) \ @@ -495,8 +516,6 @@ static int blob_init(struct osl_table **table, DEFINE_GET_NAME_BY_ID(table_name, cmd_prefix); \ DEFINE_GET_DEF_BY_ID(table_name, cmd_prefix); \ DEFINE_GET_NAME_AND_DEF_BY_ROW(table_name, cmd_prefix); \ - DEFINE_BLOB_SHUTDOWN(table_name); \ - DEFINE_BLOB_INIT(table_name); /** \cond doxygen isn't smart enough to recognize these */ DEFINE_BLOB_FUNCTIONS(lyrics, lyr); diff --git a/mood.c b/mood.c index bf6c40e1..64cfe835 100644 --- a/mood.c +++ b/mood.c @@ -9,10 +9,10 @@ #include #include "para.h" #include "error.h" +#include "string.h" #include "afh.h" #include "afs.h" #include "list.h" -#include "string.h" /** * Contains statistical data of the currently admissible audio files. @@ -1020,7 +1020,7 @@ out: * Free all resources of the current mood which were allocated during * mood_open(). */ -void close_current_mood(void) +static void close_current_mood(void) { destroy_mood(current_mood); current_mood = NULL; @@ -1047,7 +1047,7 @@ int reload_current_mood(void) if (!current_mood) return 1; - score_shutdown(0); +// score_close(0); mood_name = para_strdup(current_mood->name); close_current_mood(); ret = change_current_mood(mood_name); diff --git a/playlist.c b/playlist.c index ba99fad2..ca427bc7 100644 --- a/playlist.c +++ b/playlist.c @@ -1,8 +1,8 @@ #include "para.h" #include "error.h" +#include "string.h" #include "afh.h" #include "afs.h" -#include "string.h" /** \file playlist.c Functions for loading and saving playlists. */ diff --git a/score.c b/score.c index ad147bba..e233f735 100644 --- a/score.c +++ b/score.c @@ -7,10 +7,10 @@ /** \file score.c Scoring functions to determine the audio file streaming order. */ #include "para.h" #include "error.h" +#include "string.h" #include "afh.h" #include "afs.h" #include "list.h" -#include "string.h" static struct osl_table *score_table; @@ -330,33 +330,36 @@ int row_belongs_to_score_table(const struct osl_row *aft_row) return ret; } -/** - * Close the score table. - * - * \param flags Options passed to osl_close_table(). - * - * \sa score_init(). - */ -void score_shutdown(enum osl_close_flags flags) +/* Close the score table. */ +static void score_close(void) { - osl_close_table(score_table, flags | OSL_FREE_VOLATILE); + osl_close_table(score_table, OSL_FREE_VOLATILE); score_table = NULL; } /** - * Init the scoring subsystem. + * Open the score table. * - * \param ti Gets filled in by the function. - * \param db The database directory. + * \param dir The database directory. * * \return The return value of the underlying call to osl_open_table(). * * \sa score_shutdown(). */ -int score_init(struct table_info *ti, const char *db) +static int score_open(const char *dir) +{ + score_table_desc.dir = dir; + return osl_open_table(&score_table_desc, &score_table); +} + +/** + * Initialize the scoring subsystem. + * + * \param t Members Gets filled in by the function. + */ +void score_init(struct afs_table *t) { - score_table_desc.dir = db; - ti->desc = &score_table_desc; - ti->flags = TBLFLAG_SKIP_CREATE; - return osl_open_table(ti->desc, &score_table); + t->name = score_table_desc.name; + t->open = score_open; + t->close = score_close; } diff --git a/server.ggo b/server.ggo index f0e5bb04..b64aaa3c 100644 --- a/server.ggo +++ b/server.ggo @@ -156,21 +156,17 @@ option "afs_socket" s default="/var/paraslash/afs_command_socket" optional -option "mood" m -#~~~~~~~~~~~~~~ - -"Mood to load on startup." - - string typestr="mood_name" - optional - -option "playlist" P -#~~~~~~~~~~~~~~ +option "afs_initial_mode" i +#~~~~~~~~~~~~~~~~~~~~~~~~~~ -"Playlist to load on startup. Ignored if ---mood is given as well." +"Mood or playlist to load on startup. Must be +prefixed with either 'p:' or 'm:' to indicate +whether a playlist or a mood should be +loaded. Example: + --afs_initial_mode p:foo +loads the playlist named 'foo'." - string typestr="playlist_name" + string typestr="name" optional section "mysql selector" -- 2.39.2