X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=5d4e64773e8a7e7011ef88bb69771a21bd285a1b;hp=4433730647f1e95452fdfbd1853b563abf5e43fe;hb=f787a626b8885247948e3c47ae886b1e3a7c2a3a;hpb=d31995b3074bb19aa4da66ce5c4774ca9ed101a1 diff --git a/aft.c b/aft.c index 44337306..5d4e6477 100644 --- a/aft.c +++ b/aft.c @@ -22,9 +22,31 @@ #include "sideband.h" #include "command.h" -static struct osl_table *audio_file_table; +/* Data about one audio file. Needed for ls and stat output. */ +struct ls_data { + /* Usual audio format handler information. */ + struct afh_info afhi; + /* Audio file selector information. */ + struct afs_info afsi; + /* The full path of the audio file. */ + char *path; + /* The score value (if -a was given). */ + long score; + /* The hash value of the audio file data. */ + unsigned char *hash; +}; + +/* + * The internal state of the audio file table is described by the following + * variables which are private to aft.c. + */ +static struct osl_table *audio_file_table; /* NULL if table not open */ +static struct osl_row *current_aft_row; /* NULL if no audio file open */ +static unsigned char current_hash[HASH_SIZE]; /* only used on sighup */ + static char *status_items; static char *parser_friendly_status_items; +static struct ls_data status_item_ls_data; /** The different sorting methods of the ls command. */ enum ls_sorting_method { @@ -70,20 +92,6 @@ enum ls_listing_mode { LS_MODE_PARSER, }; -/* Data about one audio file. Needed for ls and stat output. */ -struct ls_data { - /* Usual audio format handler information. */ - struct afh_info afhi; - /* Audio file selector information. */ - struct afs_info afsi; - /* The full path of the audio file. */ - char *path; - /* The score value (if -a was given). */ - long score; - /* The hash value of the audio file data. */ - unsigned char *hash; -}; - /** * The size of the individual output fields of the ls command. * @@ -954,9 +962,6 @@ out: return ret; } -static struct ls_data status_item_ls_data; -static struct osl_row *current_aft_row; - static void make_inode_status_items(struct para_buffer *pb) { struct stat statbuf = {.st_size = 0}; @@ -978,6 +983,12 @@ out: WRITE_STATUS_ITEM(pb, SI_file_size, "%ld\n", statbuf.st_size / 1024); } +void free_status_items(void) +{ + freep(&status_items); + freep(&parser_friendly_status_items); +} + static int make_status_items(void) { const struct lls_command *cmd = SERVER_CMD_CMD_PTR(LS); @@ -987,6 +998,7 @@ static int make_status_items(void) time_t current_time; int ret; + free_status_items(); if (!status_item_ls_data.path) /* no audio file open */ return 0; ret = lls_parse(ARRAY_SIZE(argv), argv, cmd, &opts.lpr, NULL); @@ -996,23 +1008,20 @@ static int make_status_items(void) if (ret < 0) goto out; make_inode_status_items(&pb); - free(status_items); status_items = pb.buf; memset(&pb, 0, sizeof(pb)); pb.max_size = shm_get_shmmax() - 1; pb.flags = PBF_SIZE_PREFIX; ret = print_list_item(&status_item_ls_data, &opts, &pb, current_time); - if (ret < 0) { - free(status_items); - status_items = NULL; - return ret; - } + if (ret < 0) + goto out; make_inode_status_items(&pb); - free(parser_friendly_status_items); parser_friendly_status_items = pb.buf; ret = 1; out: + if (ret < 0) + free_status_items(); lls_free_parse_result(opts.lpr, cmd); return ret; } @@ -1590,7 +1599,7 @@ ACTION: Table modifications to be done by the callback. +----+----+---+------+---------------------------------------------------+ | N | N | Y | Y | (new file) create new entry (force has no effect) +----+----+---+------+---------------------------------------------------+ -| N | N | N | Y | (new file) create new entry +| N | N | N | Y | (new file) create new entry +----+----+---+------+---------------------------------------------------+ Notes: @@ -2471,28 +2480,30 @@ int aft_check_attributes(uint64_t att_mask, struct para_buffer *pb) return audio_file_loop(&acad, check_atts_of_audio_file); } -/** - * Close the audio file table. - * - * \param flags Usual flags that are passed to osl_close_table(). - * - * \sa \ref osl_close_table(). +/* + * This sets audio_file_table to NULL, but leaves current_aft_row unmodified, + * though stale (pointing to unmapped memory). If the table is being closed + * because we received SIGHUP, the table will be reopened after the config file + * has been reloaded. We remember the hash of the current audio file here so + * that aft_open() can initialize current_aft_row by looking up the saved hash. */ static void aft_close(void) { + int ret; + unsigned char *p; + + if (current_aft_row) { + ret = get_hash_of_row(current_aft_row, &p); + if (ret < 0) { + PARA_WARNING_LOG("hash lookup failure\n"); + current_aft_row = NULL; + } else + memcpy(current_hash, p, HASH_SIZE); + } osl_close_table(audio_file_table, OSL_MARK_CLEAN); audio_file_table = NULL; } -/** - * Open the audio file table. - * - * \param dir The database directory. - * - * \return Standard. - * - * \sa \ref osl_open_table(). - */ static int aft_open(const char *dir) { int ret; @@ -2503,7 +2514,20 @@ static int aft_open(const char *dir) unsigned num; osl_get_num_rows(audio_file_table, &num); PARA_INFO_LOG("audio file table contains %u files\n", num); - return ret; + if (!current_aft_row) { + PARA_DEBUG_LOG("no current aft row\n"); + return 1; + } + /* SIGHUP case, update current_aft_row */ + ret = aft_get_row_of_hash(current_hash, ¤t_aft_row); + if (ret < 0) { /* not fatal */ + PARA_WARNING_LOG("current hash lookup failure: %s\n", + para_strerror(-ret)); + current_aft_row = NULL; + return 1; + } + PARA_NOTICE_LOG("current audio file hash lookup: success\n"); + return 1; } PARA_NOTICE_LOG("failed to open audio file table\n"); audio_file_table = NULL; @@ -2559,6 +2583,16 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb, status_item_ls_data.afsi.last_played = old_last_played; make_status_items(); return 1; + } case AUDIO_FILE_RENAME: { + char *path; + if (data != current_aft_row) + return 0; + ret = get_audio_file_path_of_row(current_aft_row, &path); + if (ret < 0) + return ret; + status_item_ls_data.path = path; + make_status_items(); + return 1; } case AFHI_CHANGE: { if (data != current_aft_row) return 0; @@ -2567,6 +2601,10 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb, return ret; make_status_items(); return 1; + } case AUDIO_FILE_REMOVE: { + if (data == current_aft_row) + current_aft_row = NULL; + return 0; } case BLOB_RENAME: case BLOB_REMOVE: @@ -2577,6 +2615,7 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb, * every time. */ make_status_items(); + return 0; } default: return 0; }