X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=13e237484a1367cd21d41b18dd2670c15104b421;hp=aae6d66b0bfbd511fb7a7aabbf14f2c1dbab74a7;hb=a6e79f02b6eab623425686f8f3cab5bc942e77d4;hpb=97f53e18953fc2013c0b14f0261ac385e45b0284 diff --git a/aft.c b/aft.c index aae6d66b..13e23748 100644 --- a/aft.c +++ b/aft.c @@ -17,6 +17,7 @@ #include "net.h" #include "vss.h" #include "fd.h" +#include "ipc.h" static struct osl_table *audio_file_table; @@ -98,7 +99,7 @@ struct ls_widths { /** Data passed to the different compare functions (called by qsort()). */ struct ls_data { /** Usual audio format handler information. */ - struct audio_format_info afhi; + struct afh_info afhi; /** Audio file selector information. */ struct afs_info afsi; /** The full path of the audio file. */ @@ -319,14 +320,14 @@ enum afhi_offsets { MIN_AFHI_SIZE = 14 }; -static unsigned sizeof_afhi_buf(const struct audio_format_info *afhi) +static unsigned sizeof_afhi_buf(const struct afh_info *afhi) { if (!afhi) return 0; return strlen(afhi->info_string) + MIN_AFHI_SIZE; } -static void save_afhi(struct audio_format_info *afhi, char *buf) +static void save_afhi(struct afh_info *afhi, char *buf) { if (!afhi) return; @@ -339,7 +340,7 @@ static void save_afhi(struct audio_format_info *afhi, char *buf) PARA_DEBUG_LOG("last byte written: %p\n", buf + AFHI_INFO_STRING_OFFSET + strlen(afhi->info_string)); } -static void load_afhi(const char *buf, struct audio_format_info *afhi) +static void load_afhi(const char *buf, struct afh_info *afhi) { afhi->seconds_total = read_u32(buf + AFHI_SECONDS_TOTAL_OFFSET); afhi->bitrate = read_u32(buf + AFHI_BITRATE_OFFSET); @@ -348,11 +349,13 @@ static void load_afhi(const char *buf, struct audio_format_info *afhi) strcpy(afhi->info_string, buf + AFHI_INFO_STRING_OFFSET); } -static unsigned sizeof_chunk_info_buf(struct audio_format_info *afhi) +//#define SIZEOF_CHUNK_TABLE(afhi) (((afhi)->chunks_total + 1) * sizeof(uint32_t)) + +static unsigned sizeof_chunk_info_buf(struct afh_info *afhi) { if (!afhi) return 0; - return 4 * afhi->chunks_total + 20; + return 4 * (afhi->chunks_total + 1) + 20; } @@ -372,11 +375,25 @@ enum chunk_info_offsets{ CHUNK_TABLE_OFFSET = 20, }; -/* TODO: audio format handlers could just produce this */ -static void save_chunk_info(struct audio_format_info *afhi, char *buf) +static void save_chunk_table(struct afh_info *afhi, char *buf) +{ + int i; + + PARA_DEBUG_LOG("%lu chunks\n", afhi->chunks_total); + for (i = 0; i <= afhi->chunks_total; i++) + write_u32(buf + 4 * i, afhi->chunk_table[i]); +} + +static void load_chunk_table(struct afh_info *afhi, char *buf) { int i; + for (i = 0; i <= afhi->chunks_total; i++) + afhi->chunk_table[i] = read_u32(buf + 4 * i); +} +/* TODO: audio format handlers could just produce this */ +static void save_chunk_info(struct afh_info *afhi, char *buf) +{ if (!afhi) return; write_u32(buf + CHUNKS_TOTAL_OFFSET, afhi->chunks_total); @@ -384,14 +401,12 @@ static void save_chunk_info(struct audio_format_info *afhi, char *buf) write_u32(buf + HEADER_OFFSET_OFFSET, afhi->header_offset); write_u32(buf + CHUNK_TV_TV_SEC_OFFSET, afhi->chunk_tv.tv_sec); write_u32(buf + CHUNK_TV_TV_USEC, afhi->chunk_tv.tv_usec); - for (i = 0; i < afhi->chunks_total; i++) - write_u32(buf + CHUNK_TABLE_OFFSET + 4 * i, afhi->chunk_table[i]); + save_chunk_table(afhi, buf + CHUNK_TABLE_OFFSET); } -static int load_chunk_info(struct osl_object *obj, struct audio_format_info *afhi) +static int load_chunk_info(struct osl_object *obj, struct afh_info *afhi) { char *buf = obj->data; - int i; if (obj->size < CHUNK_TABLE_OFFSET) return -E_BAD_DATA_SIZE; @@ -402,11 +417,10 @@ static int load_chunk_info(struct osl_object *obj, struct audio_format_info *afh afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET); afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC); - if (afhi->chunks_total * 4 + CHUNK_TABLE_OFFSET > obj->size) + if ((afhi->chunks_total + 1) * 4 + CHUNK_TABLE_OFFSET > obj->size) return -E_BAD_DATA_SIZE; - afhi->chunk_table = para_malloc(afhi->chunks_total * sizeof(size_t)); - for (i = 0; i < afhi->chunks_total; i++) - afhi->chunk_table[i] = read_u32(buf + CHUNK_TABLE_OFFSET + 4 * i); + afhi->chunk_table = para_malloc((afhi->chunks_total + 1) * 4); + load_chunk_table(afhi, buf + CHUNK_TABLE_OFFSET); return 1; } @@ -510,7 +524,10 @@ int get_afsi_of_path(const char *path, struct afs_info *afsi) * \param row Pointer to a row in the audio file table. * \param path Result pointer. * - * \return Positive on success, negative on errors. + * The result is a pointer to mmapped data. The caller must not attempt + * to free it. + * + * \return Standard. */ int get_audio_file_path_of_row(const struct osl_row *row, char **path) { @@ -570,7 +587,7 @@ static int get_hash_of_row(const struct osl_row *row, HASH_TYPE **hash) * * \sa get_chunk_table_of_row(). */ -int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi) +int get_afhi_of_row(const struct osl_row *row, struct afh_info *afhi) { struct osl_object obj; int ret = osl_get_object(audio_file_table, row, AFTCOL_AFHI, @@ -581,28 +598,52 @@ int get_afhi_of_row(const struct osl_row *row, struct audio_format_info *afhi) return 1; } -/** - * Get the chunk table of an audio file, given a row of the audio file table. - * - * \param row Pointer to a row of the audio file table. - * \param afhi Result pointer. - * - * \return The return value of the underlying call to osl_open_disk_object(). - * - * \sa get_afhi_of_row(). - */ -static int get_chunk_table_of_row(const struct osl_row *row, struct audio_format_info *afhi) +/* returns shmid on success */ +static int save_afd(struct audio_file_data *afd) { - struct osl_object obj; - int ret = osl_open_disk_object(audio_file_table, row, AFTCOL_CHUNKS, - &obj); + size_t size = sizeof(*afd) + + 4 * (afd->afhi.chunks_total + 1); + + PARA_DEBUG_LOG("size: %zu\n", size); + int shmid, ret = shm_new(size); + void *shm_afd; + char *buf; + if (ret < 0) return ret; - ret = load_chunk_info(&obj, afhi); - osl_close_disk_object(&obj); + shmid = ret; + ret = shm_attach(shmid, ATTACH_RW, &shm_afd); + if (ret < 0) + goto err; + *(struct audio_file_data *)shm_afd = *afd; + buf = shm_afd; + buf += sizeof(*afd); + save_chunk_table(&afd->afhi, buf); + shm_detach(shm_afd); + return shmid; +err: + shm_destroy(shmid); return ret; } +int load_afd(int shmid, struct audio_file_data *afd) +{ + void *shm_afd; + char *buf; + int ret; + + ret = shm_attach(shmid, ATTACH_RO, &shm_afd); + if (ret < 0) + return ret; + *afd = *(struct audio_file_data *)shm_afd; + buf = shm_afd; + buf += sizeof(*afd); + afd->afhi.chunk_table = para_malloc((afd->afhi.chunks_total + 1) * 4); + load_chunk_table(&afd->afhi, buf); + shm_detach(shm_afd); + return 1; +} + /** * Mmap the given audio file and update statistics. * @@ -622,12 +663,16 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data * struct afs_info new_afsi; int ret = get_hash_of_row(aft_row, &aft_hash); struct afsi_change_event_data aced; + struct osl_object map, chunk_table_obj; + char *tmp, *path; if (ret < 0) return ret; - ret = get_audio_file_path_of_row(aft_row, &afd->path); + ret = get_audio_file_path_of_row(aft_row, &path); if (ret < 0) return ret; + strncpy(afd->path, path, sizeof(afd->path) - 1); + afd->path[sizeof(afd->path) - 1] = '\0'; ret = get_afsi_object_of_row(aft_row, &afsi_obj); if (ret < 0) return ret; @@ -637,29 +682,45 @@ int open_and_update_audio_file(struct osl_row *aft_row, struct audio_file_data * ret = get_afhi_of_row(aft_row, &afd->afhi); if (ret < 0) return ret; - ret = get_chunk_table_of_row(aft_row, &afd->afhi); + ret = osl_open_disk_object(audio_file_table, aft_row, + AFTCOL_CHUNKS, &chunk_table_obj); if (ret < 0) return ret; - ret = mmap_full_file(afd->path, O_RDONLY, &afd->map.data, - &afd->map.size, NULL); + ret = mmap_full_file(path, O_RDONLY, &map.data, + &map.size, &afd->fd); if (ret < 0) goto err; - hash_function(afd->map.data, afd->map.size, file_hash); - ret = -E_HASH_MISMATCH; - if (hash_compare(file_hash, aft_hash)) + hash_function(map.data, map.size, file_hash); + ret = hash_compare(file_hash, aft_hash); + para_munmap(map.data, map.size); + if (ret) { + ret = -E_HASH_MISMATCH; goto err; + } new_afsi = afd->afsi; new_afsi.num_played++; new_afsi.last_played = time(NULL); save_afsi(&new_afsi, &afsi_obj); /* in-place update */ + ret = load_chunk_info(&chunk_table_obj, &afd->afhi); + if (ret < 0) + goto err; + ret = get_attribute_text(&afd->afsi.attributes, " ", &tmp); + if (ret < 0) + goto err; + tmp[sizeof(afd->attributes_string) - 1] = '\0'; + strcpy(afd->attributes_string, tmp); /* OK */ + free(tmp); + aced.aft_row = aft_row; aced.old_afsi = &afd->afsi; afs_event(AFSI_CHANGE, NULL, &aced); - - return ret; -err: + ret = save_afd(afd); + if (ret < 0) + goto err; free(afd->afhi.chunk_table); +err: + osl_close_disk_object(&chunk_table_obj); return ret; } @@ -719,16 +780,17 @@ static void get_duration_buf(int seconds, char *buf, short unsigned max_width) seconds % 60); } -static char *make_attribute_line(const char *att_bitmap, struct afs_info *afsi) +static char *make_attribute_lines(const char *att_bitmap, struct afs_info *afsi) { - char *att_text, *att_line; + char *att_text, *att_lines; get_attribute_text(&afsi->attributes, " ", &att_text); if (!att_text) return para_strdup(att_bitmap); - att_line = make_message("%s (%s)", att_bitmap, att_text); + att_lines = make_message("%s\nattributes_txt: %s", + att_bitmap, att_text); free(att_text); - return att_line; + return att_lines; } static char *make_lyrics_line(struct afs_info *afsi) @@ -759,11 +821,11 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, char duration_buf[30]; /* nobody has an audio file long enough to overflow this */ char score_buf[30] = ""; struct afs_info *afsi = &d->afsi; - struct audio_format_info *afhi = &d->afhi; + struct afh_info *afhi = &d->afhi; struct ls_widths *w = &opts->widths; int have_score = opts->flags & LS_FLAG_ADMISSIBLE_ONLY; char asc_hash[2 * HASH_SIZE + 1]; - char *att_line, *lyrics_line, *image_line; + char *att_lines, *lyrics_line, *image_line; if (opts->mode == LS_MODE_SHORT) { para_printf(b, "%s\n", d->path); @@ -812,11 +874,11 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, return 1; } hash_to_asc(d->hash, asc_hash); - att_line = make_attribute_line(att_buf, afsi); + att_lines = make_attribute_lines(att_buf, afsi); lyrics_line = make_lyrics_line(afsi); image_line = make_image_line(afsi); + /* TODO: Merge this with status items */ if (opts->mode == LS_MODE_VERBOSE) { - para_printf(b, "%s: %s\n" /* path */ "%s%s%s" /* score */ @@ -836,7 +898,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, "path" : "file", d->path, have_score? "score: " : "", score_buf, have_score? "\n" : "", - att_line, + att_lines, asc_hash, image_line, lyrics_line, @@ -857,7 +919,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, "Received: from\nTo: bar\nFrom: a\n" "Subject: %s\n\n" /* path */ "%s%s%s" /* score */ - "attributes: %s\n" + "%s" "hash: %s\n" "image_id: %s\n" "lyrics_id: %s\n" @@ -873,7 +935,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, d->path, have_score? "score: " : "", score_buf, have_score? "\n" : "", - att_line, + att_lines, asc_hash, image_line, lyrics_line, @@ -890,7 +952,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, if (lyrics_def.data) osl_close_disk_object(lyrics_def.data); } - free(att_line); + free(att_lines); free(lyrics_line); free(image_line); return 1; @@ -1154,7 +1216,7 @@ out: * full list: list everything, including afsi, afhi, atts as clear text * * */ -int com_afs_ls(int fd, int argc, char * const * const argv) +int com_ls(int fd, int argc, char * const * const argv) { int i, ret; unsigned flags = 0; @@ -1300,7 +1362,7 @@ enum aft_row_offsets { /* never save the afsi, as the server knows it too. Note that afhi might be NULL. * In this case, afhi won't be stored in the buffer */ static void save_audio_file_info(HASH_TYPE *hash, const char *path, - struct audio_format_info *afhi, uint32_t flags, + struct afh_info *afhi, uint32_t flags, uint8_t audio_format_num, struct osl_object *obj) { size_t path_len = strlen(path) + 1; @@ -1548,9 +1610,9 @@ static int add_one_audio_file(const char *path, const void *private_data) int ret, ret2; uint8_t format_num = -1; const struct private_add_data *pad = private_data; - struct audio_format_info afhi, *afhi_ptr = NULL; + struct afh_info afhi, *afhi_ptr = NULL; struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */ - struct osl_object map, obj = {.data = NULL}, query, result; + struct osl_object map, obj = {.data = NULL}, query, result = {.data = NULL}; HASH_TYPE hash[HASH_SIZE]; afhi.header_offset = 0; @@ -1617,7 +1679,7 @@ static int add_one_audio_file(const char *path, const void *private_data) save_audio_file_info(hash, path, afhi_ptr, pad->flags, format_num, &obj); /* Ask afs to consider this entry for adding. */ ret = send_callback_request(com_add_callback, &obj, &result); - if (result.data && result.size) { + if (ret >= 0 && result.data && result.size) { ret2 = send_va_buffer(pad->fd, "%s", (char *)result.data); free(result.data); if (ret >= 0 && ret2 < 0) @@ -1866,7 +1928,7 @@ int com_touch(int fd, int argc, char * const * const argv) if (ret > 0) { send_buffer(fd, (char *)result.data); free(result.data); - } else + } else if (ret < 0) send_va_buffer(fd, "%s\n", PARA_STRERROR(-ret)); return ret; } @@ -1934,7 +1996,7 @@ static int com_rm_callback(const struct osl_object *query, } /* TODO options: -r (recursive) */ -int com_afs_rm(int fd, int argc, char * const * const argv) +int com_rm(int fd, int argc, char * const * const argv) { uint32_t flags = 0; struct osl_object query = {.data = &flags, .size = sizeof(flags)},