diff --git a/daemon/cli.c b/daemon/cli.c index 4907fe37d..06bc89596 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -113,8 +113,14 @@ static void cli_incoming_media_reload_file(str *instr, struct cli_writer *cw, co static void cli_incoming_media_reload_files(str *instr, struct cli_writer *cw, const cli_handler_t *); static void cli_incoming_media_reload_db(str *instr, struct cli_writer *cw, const cli_handler_t *); static void cli_incoming_media_reload_dbs(str *instr, struct cli_writer *cw, const cli_handler_t *); + +static void cli_incoming_media_evict_file(str *instr, struct cli_writer *cw, const cli_handler_t *); +static void cli_incoming_media_evict_files(str *instr, struct cli_writer *cw, const cli_handler_t *); +static void cli_incoming_media_evict_db(str *instr, struct cli_writer *cw, const cli_handler_t *); +static void cli_incoming_media_evict_dbs(str *instr, struct cli_writer *cw, const cli_handler_t *); #endif + static const cli_handler_t cli_set_handlers[] = { { "maxopenfiles", cli_incoming_set_maxopenfiles, NULL }, { "maxsessions", cli_incoming_set_maxsessions, NULL }, @@ -192,8 +198,16 @@ static const cli_handler_t cli_media_reload_handlers[] = { { "dbs", cli_incoming_media_reload_dbs, NULL }, { NULL, }, }; +static const cli_handler_t cli_media_evict_handlers[] = { + { "file", cli_incoming_media_evict_file, NULL }, + { "files", cli_incoming_media_evict_files, NULL }, + { "db", cli_incoming_media_evict_db, NULL }, + { "dbs", cli_incoming_media_evict_dbs, NULL }, + { NULL, }, +}; static const cli_handler_t cli_media_handlers[] = { { "reload", cli_generic_handler, cli_media_reload_handlers }, + { "evict", cli_generic_handler, cli_media_evict_handlers }, { NULL, }, }; #endif @@ -1819,4 +1833,45 @@ static void cli_incoming_media_reload_dbs(str *instr, struct cli_writer *cw, con unsigned int num = media_player_reload_db_medias(); cw->cw_printf(cw, "%u media entries reloaded\n", num); } + +static void cli_incoming_media_evict_file(str *instr, struct cli_writer *cw, const cli_handler_t *handler) { + if (instr->len == 0) { + cw->cw_printf(cw, "More parameters required.\n"); + return ; + } + + bool ok = media_player_evict_file(instr); + if (ok) + cw->cw_printf(cw, "Success\n"); + else + cw->cw_printf(cw, "Failed to evict '" STR_FORMAT "'", STR_FMT(instr)); +} + +static void cli_incoming_media_evict_files(str *instr, struct cli_writer *cw, const cli_handler_t *handler) { + unsigned int num = media_player_evict_files(); + cw->cw_printf(cw, "%u media files evicted\n", num); +} + +static void cli_incoming_media_evict_db(str *instr, struct cli_writer *cw, const cli_handler_t *handler) { + if (instr->len == 0) { + cw->cw_printf(cw, "More parameters required.\n"); + return ; + } + + unsigned long long id = str_to_ui(instr, 0); + if (id == 0 || id == ULLONG_MAX) + cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(instr)); + else { + bool ok = media_player_evict_db_media(id); + if (ok) + cw->cw_printf(cw, "Success\n"); + else + cw->cw_printf(cw, "Failed to evict '" STR_FORMAT "'\n", STR_FMT(instr)); + } +} + +static void cli_incoming_media_evict_dbs(str *instr, struct cli_writer *cw, const cli_handler_t *handler) { + unsigned int num = media_player_evict_db_medias(); + cw->cw_printf(cw, "%u DB media entries evicted\n", num); +} #endif diff --git a/daemon/media_player.c b/daemon/media_player.c index 981b0059a..c93e2e538 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -2252,3 +2252,105 @@ enum thread_looper_action media_player_refresh_db(void) { return TLA_CONTINUE; } + +#ifdef WITH_TRANSCODING +// media_player_media_files_names_lock must be held +// media_player_media_files_lock must not be held +static bool __media_player_evict_file(str *name) { + str *key; + struct media_player_media_file *val; + + { + // short lock: remove from containers, unlock, then free + LOCK(&media_player_media_files_lock); + if (!t_hash_table_is_set(media_player_media_files)) + return false; + bool ret = t_hash_table_steal_extended(media_player_media_files, name, &key, &val); + if (!ret) + return false; + t_queue_delete_link(&media_player_media_files_names, val->str_link); + } + + obj_put(val); + g_free(key); + + return true; +} +#endif + +bool media_player_evict_file(str *name) { +#ifdef WITH_TRANSCODING + RWLOCK_W(&media_player_media_files_names_lock); + return __media_player_evict_file(name); +#else + return false; +#endif +} + +unsigned int media_player_evict_files(void) { + unsigned int ret = 0; + +#ifdef WITH_TRANSCODING + while (true) { + // intermittently release lock as this is low priority + RWLOCK_W(&media_player_media_files_names_lock); + if (!media_player_media_files_names.head) + return ret; + str *name = media_player_media_files_names.head->data; + if (__media_player_evict_file(name)) + ret++; + } +#endif + + return ret; +} + +#ifdef WITH_TRANSCODING +// media_player_db_media_ids_lock must be held +// media_player_db_media_lock must not be held +static bool __media_player_evict_db_media(unsigned long long id) { + struct media_player_media_file *val; + + { + // short lock: remove from containers, unlock, then free + LOCK(&media_player_db_media_lock); + if (!t_hash_table_is_set(media_player_db_media)) + return false; + bool ret = t_hash_table_steal_extended(media_player_db_media, GUINT_TO_POINTER(id), NULL, &val); + if (!ret) + return false; + g_queue_delete_link(&media_player_db_media_ids, val->gen_link); + } + + obj_put(val); + + return true; +} +#endif + +bool media_player_evict_db_media(unsigned long long id) { +#ifdef WITH_TRANSCODING + RWLOCK_W(&media_player_db_media_ids_lock); + return __media_player_evict_db_media(id); +#else + return false; +#endif +} + +unsigned int media_player_evict_db_medias(void) { + unsigned int ret = 0; + +#ifdef WITH_TRANSCODING + while (true) { + // intermittently release lock as this is low priority + RWLOCK_W(&media_player_db_media_ids_lock); + if (!media_player_db_media_ids.head) + return ret; + unsigned long long id = GPOINTER_TO_UINT(media_player_db_media_ids.head->data); + if (__media_player_evict_db_media(id)) + ret++; + } +#endif + + return ret; +} diff --git a/include/media_player.h b/include/media_player.h index 23927973f..87c3dffd3 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -157,6 +157,10 @@ unsigned int media_player_reload_db_medias(void); enum thread_looper_action media_player_refresh_timer(void); bool media_player_preload_db(char **); enum thread_looper_action media_player_refresh_db(void); +bool media_player_evict_file(str *name); +unsigned int media_player_evict_files(void); +bool media_player_evict_db_media(unsigned long long); +unsigned int media_player_evict_db_medias(void); struct send_timer *send_timer_new(struct packet_stream *); void send_timer_push(struct send_timer *, struct codec_packet *); diff --git a/utils/rtpengine-ctl b/utils/rtpengine-ctl index 0c0bfb58d..143446924 100755 --- a/utils/rtpengine-ctl +++ b/utils/rtpengine-ctl @@ -169,6 +169,11 @@ sub showusage { print " files : reload all media files currently in memory\n"; print " db : reload one media entry from database into memory\n"; print " dbs : reload all media entries from database currently in memory\n"; + print " evict