X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=f41bfadea25385c4ab1c9a169a15b0c755440c98;hp=944d904dd14aaab70fa8689e8be82ac5f707fd62;hb=62c0894fbb589dd45e69b7d9ef1fd152a9960d62;hpb=3cdcb449fc23f0bebe34343dc26b4e34b82175d5 diff --git a/aft.c b/aft.c index 944d904d..f41bfade 100644 --- a/aft.c +++ b/aft.c @@ -50,46 +50,28 @@ static struct ls_data status_item_ls_data; /** The different sorting methods of the ls command. */ enum ls_sorting_method { - /** -sp (default) */ - LS_SORT_BY_PATH, - /** -ss */ - LS_SORT_BY_SCORE, - /** -sl */ - LS_SORT_BY_LAST_PLAYED, - /** -sn */ - LS_SORT_BY_NUM_PLAYED, - /** -sf */ - LS_SORT_BY_FREQUENCY, - /** -sc */ - LS_SORT_BY_CHANNELS, - /** -si */ - LS_SORT_BY_IMAGE_ID, - /** -sy */ - LS_SORT_BY_LYRICS_ID, - /** -sb */ - LS_SORT_BY_BITRATE, - /** -sd */ - LS_SORT_BY_DURATION, - /** -sa */ - LS_SORT_BY_AUDIO_FORMAT, - /** -sh */ - LS_SORT_BY_HASH, + LS_SORT_BY_PATH, /**< -s=p (default) */ + LS_SORT_BY_SCORE, /**< -s=s */ + LS_SORT_BY_LAST_PLAYED, /**< -s=l */ + LS_SORT_BY_NUM_PLAYED, /**< -s=n */ + LS_SORT_BY_FREQUENCY, /**< -s=f */ + LS_SORT_BY_CHANNELS, /**< -s=c */ + LS_SORT_BY_IMAGE_ID, /**< -s=i */ + LS_SORT_BY_LYRICS_ID, /**< -s=y */ + LS_SORT_BY_BITRATE, /**< -s=b */ + LS_SORT_BY_DURATION, /**< -s=d */ + LS_SORT_BY_AUDIO_FORMAT, /**< -s=a */ + LS_SORT_BY_HASH, /**< -s=h */ }; /** The different listing modes of the ls command. */ enum ls_listing_mode { - /** Default listing mode. */ - LS_MODE_SHORT, - /** -l or -ll */ - LS_MODE_LONG, - /** -lv */ - LS_MODE_VERBOSE, - /** -lm */ - LS_MODE_MBOX, - /** -lc */ - LS_MODE_CHUNKS, - /** -lp */ - LS_MODE_PARSER, + LS_MODE_SHORT, /**< Default listing mode. */ + LS_MODE_LONG, /**< -l or -l=l */ + LS_MODE_VERBOSE, /** -l=v */ + LS_MODE_MBOX, /** -l=m */ + LS_MODE_CHUNKS, /** -l=c */ + LS_MODE_PARSER, /** -l=p */ }; /** @@ -414,7 +396,7 @@ static void save_chunk_table(struct afh_info *afhi, char *buf) { uint32_t n; - if (!afhi->chunk_table) + if (!afhi->chunk_table || afhi->chunks_total == 0) return; for (n = 0; n <= afhi->chunks_total; n++) write_u32(buf + 4 * n, afhi->chunk_table[n]); @@ -983,7 +965,18 @@ out: WRITE_STATUS_ITEM(pb, SI_file_size, "%ld\n", statbuf.st_size / 1024); } -static int make_status_items(void) +/** + * Deallocate and invalidate the status item strings. + * + * This needs to be a public function so that afs.c can call it on shutdown. + */ +void free_status_items(void) +{ + freep(&status_items); + freep(&parser_friendly_status_items); +} + +static void make_status_items(void) { const struct lls_command *cmd = SERVER_CMD_CMD_PTR(LS); char *argv[] = {"ls", "--admissible", "--listing-mode=verbose"}; @@ -992,8 +985,9 @@ 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; + return; ret = lls_parse(ARRAY_SIZE(argv), argv, cmd, &opts.lpr, NULL); assert(ret >= 0); time(¤t_time); @@ -1001,25 +995,24 @@ 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) { + PARA_WARNING_LOG("could not create status items: %s\n", + para_strerror(-ret)); + free_status_items(); + } lls_free_parse_result(opts.lpr, cmd); - return ret; } /** @@ -1042,17 +1035,33 @@ int open_and_update_audio_file(struct audio_file_data *afd) struct afsi_change_event_data aced; struct osl_object map, chunk_table_obj; struct ls_data *d = &status_item_ls_data; + unsigned char *tmp_hash; again: ret = score_get_best(¤t_aft_row, &d->score); if (ret < 0) return ret; - ret = get_hash_of_row(current_aft_row, &d->hash); + /* + * get_hash_of_row() and get_audio_file_path_of_row() initialize + * their pointer argument to point to memory-mapped files. These pointers + * become stale after a new audio file has been added or after the + * server process received SIGHUP. For in both cases libosl unmaps and + * remaps the underlying database files, and this remapping may well + * change the starting address of the mapping. To avoid stale pointer + * references we create copies on the heap. + */ + ret = get_hash_of_row(current_aft_row, &tmp_hash); if (ret < 0) return ret; + if (!d->hash) + d->hash = para_malloc(HASH_SIZE); + memcpy(d->hash, tmp_hash, HASH_SIZE); + free(d->path); ret = get_audio_file_path_of_row(current_aft_row, &d->path); if (ret < 0) return ret; PARA_NOTICE_LOG("%s\n", d->path); + d->path = para_strdup(d->path); + ret = get_afsi_object_of_row(current_aft_row, &afsi_obj); if (ret < 0) return ret; @@ -2525,10 +2534,12 @@ static int aft_open(const char *dir) 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; - if (ret == -OSL_ERRNO_TO_PARA_ERROR(E_OSL_NOENT)) + if (ret == -OSL_ERRNO_TO_PARA_ERROR(E_OSL_NOENT)) { + PARA_WARNING_LOG("no audio file table\n"); return 1; + } + PARA_NOTICE_LOG("failed to open audio file table\n"); return ret; } @@ -2586,7 +2597,8 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb, ret = get_audio_file_path_of_row(current_aft_row, &path); if (ret < 0) return ret; - status_item_ls_data.path = path; + free(status_item_ls_data.path); + status_item_ls_data.path = para_strdup(path); make_status_items(); return 1; } case AFHI_CHANGE: { @@ -2610,6 +2622,10 @@ static int aft_event_handler(enum afs_events event, struct para_buffer *pb, * current status items are affected and simply recreate them * every time. */ + ret = get_afhi_of_row(current_aft_row, + &status_item_ls_data.afhi); + if (ret < 0) + return ret; make_status_items(); return 0; } default: