예제 #1
0
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy)
{
  switch_status_t status = SWITCH_STATUS_SUCCESS;

  switch_assert(conn_pool != NULL);
  switch_assert(conn != NULL);

  switch_mutex_lock(conn_pool->mutex);
  if (destroy || conn_pool->size > conn_pool->max_connections) {
#ifdef MONGO_POOL_DEBUG
    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn);
#endif
    mongo_connection_destroy(&conn);
    conn_pool->size--;
  } else {
#ifdef MONGO_POOL_DEBUG
    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn);
#endif
    status = switch_queue_push(conn_pool->connections, conn);
  }

  switch_mutex_unlock(conn_pool->mutex);

#ifdef MONGO_POOL_DEBUG
  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif

  return status;
}
예제 #2
0
static void switch_scheduler_execute(switch_scheduler_task_container_t *tp)
{
	switch_event_t *event;
	//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing task %u %s (%s)\n", tp->task.task_id, tp->desc, switch_str_nil(tp->task.group));

	tp->func(&tp->task);

	if (tp->task.repeat) {
		tp->task.runtime = switch_epoch_time_now(NULL) + tp->task.repeat;
	}

	if (tp->task.runtime > tp->executed) {
		tp->executed = 0;
		if (switch_event_create(&event, SWITCH_EVENT_RE_SCHEDULE) == SWITCH_STATUS_SUCCESS) {
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Desc", tp->desc);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Group", switch_str_nil(tp->task.group));
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" SWITCH_INT64_T_FMT, tp->task.runtime);
			switch_queue_push(globals.event_queue, event);
			event = NULL;
		}
	} else {
		tp->destroyed = 1;
	}
}
예제 #3
0
SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(switch_memory_pool_t **pool, const char *file, const char *func, int line)
{
	switch_assert(pool != NULL);

#ifdef DEBUG_ALLOC2
	switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "%p Free Pool %s\n", (void *) *pool, apr_pool_tag(*pool, NULL));
#endif

#ifdef INSTANTLY_DESTROY_POOLS
#ifdef USE_MEM_LOCK
	switch_mutex_lock(memory_manager.mem_lock);
#endif
	apr_pool_destroy(*pool);
#ifdef USE_MEM_LOCK
	switch_mutex_unlock(memory_manager.mem_lock);
#endif
#else
	if ((memory_manager.pool_thread_running != 1) || (switch_queue_push(memory_manager.pool_queue, *pool) != SWITCH_STATUS_SUCCESS)) {
#ifdef USE_MEM_LOCK
		switch_mutex_lock(memory_manager.mem_lock);
#endif
		apr_pool_destroy(*pool);
#ifdef USE_MEM_LOCK
		switch_mutex_unlock(memory_manager.mem_lock);
#endif
	}
#endif

	*pool = NULL;

	return SWITCH_STATUS_SUCCESS;
}
예제 #4
0
SWITCH_DECLARE(uint32_t) switch_scheduler_add_task(time_t task_runtime,
												   switch_scheduler_func_t func,
												   const char *desc, const char *group, uint32_t cmd_id, void *cmd_arg, switch_scheduler_flag_t flags)
{
	switch_scheduler_task_container_t *container, *tp;
	switch_event_t *event;
	switch_time_t now = switch_epoch_time_now(NULL);
	switch_ssize_t hlen = -1;

	switch_mutex_lock(globals.task_mutex);
	switch_zmalloc(container, sizeof(*container));
	switch_assert(func);

	if (task_runtime < now) {
		container->task.repeat = (uint32_t)task_runtime;
		task_runtime += now;
	}

	container->func = func;
	container->task.created = now;
	container->task.runtime = task_runtime;
	container->task.group = strdup(group ? group : "none");
	container->task.cmd_id = cmd_id;
	container->task.cmd_arg = cmd_arg;
	container->flags = flags;
	container->desc = strdup(desc ? desc : "none");
	container->task.hash = switch_ci_hashfunc_default(container->task.group, &hlen);

	for (tp = globals.task_list; tp && tp->next; tp = tp->next);

	if (tp) {
		tp->next = container;
	} else {
		globals.task_list = container;
	}

	for (container->task.task_id = 0; !container->task.task_id; container->task.task_id = ++globals.task_id);

	switch_mutex_unlock(globals.task_mutex);

	tp = container;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added task %u %s (%s) to run at %" SWITCH_INT64_T_FMT "\n",
					  tp->task.task_id, tp->desc, switch_str_nil(tp->task.group), tp->task.runtime);

	if (switch_event_create(&event, SWITCH_EVENT_ADD_SCHEDULE) == SWITCH_STATUS_SUCCESS) {
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tp->task.task_id);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Desc", tp->desc);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Group", switch_str_nil(tp->task.group));
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" SWITCH_INT64_T_FMT, tp->task.runtime);
		switch_queue_push(globals.event_queue, event);
		event = NULL;
	}
	return container->task.task_id;
}
예제 #5
0
SWITCH_DECLARE(switch_status_t) switch_log_shutdown(void)
{
	switch_status_t st;

	THREAD_RUNNING = -1;
	switch_queue_push(LOG_QUEUE, NULL);
	while (THREAD_RUNNING) {
		switch_cond_next();
	}

	switch_thread_join(&st, thread);

	switch_core_memory_reclaim_logger();

	return SWITCH_STATUS_SUCCESS;
}
void AsyncIOServer::RecvHandle(Client* client) {
	switch_mutex_lock(client->clientMutex);
//	if( client->recvHandleCount == 0 ) {

	// 增加计数器
	client->recvHandleCount++;

	// 增加到处理队列
	switch_queue_push(mpHandleQueue, client);
//
//	} else {
//		// 已经有包在处理则返回
//	}
	switch_mutex_unlock(client->clientMutex);

//	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AsyncIOServer::RecvHandle( "
//			"client : %p, "
//			"recvHandleCount : %d "
//			") \n",
//			client,
//			client->recvHandleCount
//			);
}
예제 #7
0
static int task_thread_loop(int done)
{
	switch_scheduler_task_container_t *tofree, *tp, *last = NULL;


	switch_mutex_lock(globals.task_mutex);

	for (tp = globals.task_list; tp; tp = tp->next) {
		if (done) {
			tp->destroyed = 1;
		} else if (!tp->destroyed) {
			int64_t now = switch_epoch_time_now(NULL);
			if (now >= tp->task.runtime && !tp->in_thread) {
				int32_t diff = (int32_t) (now - tp->task.runtime);
				if (diff > 1) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Task was executed late by %d seconds %u %s (%s)\n",
									  diff, tp->task.task_id, tp->desc, switch_str_nil(tp->task.group));
				}
				tp->executed = now;
				if (switch_test_flag(tp, SSHF_OWN_THREAD)) {
					switch_thread_t *thread;
					switch_threadattr_t *thd_attr;
					switch_core_new_memory_pool(&tp->pool);
					switch_threadattr_create(&thd_attr, tp->pool);
					switch_threadattr_detach_set(thd_attr, 1);
					tp->in_thread = 1;
					switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool);
				} else {
					tp->running = 1;
					switch_mutex_unlock(globals.task_mutex);
					switch_scheduler_execute(tp);
					switch_mutex_lock(globals.task_mutex);
					tp->running = 0;
				}
			}
		}
	}
	switch_mutex_unlock(globals.task_mutex);
	switch_mutex_lock(globals.task_mutex);
	for (tp = globals.task_list; tp;) {
		if (tp->destroyed && !tp->in_thread) {
			switch_event_t *event;

			tofree = tp;
			tp = tp->next;
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting task %u %s (%s)\n",
							  tofree->task.task_id, tofree->desc, switch_str_nil(tofree->task.group));


			if (switch_event_create(&event, SWITCH_EVENT_DEL_SCHEDULE) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-ID", "%u", tofree->task.task_id);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Desc", tofree->desc);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Task-Group", switch_str_nil(tofree->task.group));
				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Task-Runtime", "%" SWITCH_INT64_T_FMT, tofree->task.runtime);
				switch_queue_push(globals.event_queue, event);
				event = NULL;
			}

			if (last) {
				last->next = tofree->next;
			} else {
				globals.task_list = tofree->next;
			}
			switch_safe_free(tofree->task.group);
			if (tofree->task.cmd_arg && switch_test_flag(tofree, SSHF_FREE_ARG)) {
				free(tofree->task.cmd_arg);
			}
			switch_safe_free(tofree->desc);
			free(tofree);
		} else {
			last = tp;
			tp = tp->next;
		}
	}
	switch_mutex_unlock(globals.task_mutex);

	return done;
}
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
	local_stream_source_t *source = obj;
	switch_file_handle_t fh = { 0 };
	local_stream_context_t *cp;
	char file_buf[128] = "", path_buf[512] = "", last_path[512], png_buf[512] = "", tmp_buf[512] = "";
	switch_timer_t timer = { 0 };
	int fd = -1;
	switch_buffer_t *audio_buffer;
	switch_byte_t *dist_buf;
	switch_size_t used;
	int skip = 0;
	switch_memory_pool_t *temp_pool = NULL;
	uint32_t dir_count = 0, do_shuffle = 0;
	char *p;

	switch_mutex_lock(globals.mutex);
	THREADS++;
	switch_mutex_unlock(globals.mutex);

	if (!source->prebuf) {
		source->prebuf = DEFAULT_PREBUFFER_SIZE;
	}

	if (source->shuffle) {
		do_shuffle = 1;
	}

	switch_queue_create(&source->video_q, 500, source->pool);
	switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0);
	dist_buf = switch_core_alloc(source->pool, source->prebuf + 10);

	switch_thread_rwlock_create(&source->rwlock, source->pool);

	if (RUNNING) {
		switch_mutex_lock(globals.mutex);
		switch_core_hash_insert(globals.source_hash, source->name, source);
		switch_mutex_unlock(globals.mutex);
		source->ready = 1;
	}

	while (RUNNING && !source->stopped) {
		const char *fname;

		if (temp_pool) {
			switch_core_destroy_memory_pool(&temp_pool);
		}

		if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool");
			goto done;
		}

		if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location);
			goto done;
		}

		if (fd > -1) {
			dir_count = 0;
			while (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
				dir_count++;
			}
			lseek(fd, 0, SEEK_SET);
		} else {
			dir_count = switch_dir_count(source->dir_handle);
		}

		if (do_shuffle) {
			skip = do_rand(dir_count);
			do_shuffle = 0;
		}

		switch_yield(1000000);

		while (RUNNING && !source->stopped) {
			switch_size_t olen;
			uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
			const char *artist = NULL, *title = NULL;

			if (fd > -1) {
				char *pb;
				if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
					if ((pb = strchr(path_buf, '\r')) || (pb = strchr(path_buf, '\n'))) {
						*pb = '\0';
					}
				} else {
					close(fd);
					fd = -1;
					continue;
				}
			} else {
				if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
					break;
				}

				switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);

				if (switch_stristr(".loc", path_buf)) {
					if ((fd = open(path_buf, O_RDONLY)) < 0) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
						switch_yield(1000000);
					}
					continue;
				}
			}

			if (dir_count > 1 && !strcmp(last_path, path_buf)) {
				continue;
			}

			if (skip > 0) {
				skip--;
				continue;
			}

			switch_set_string(last_path, path_buf);

			fname = path_buf;
			fh.prebuf = source->prebuf;
			fh.pre_buffer_datalen = source->prebuf;

			if (switch_core_file_open(&fh,
									  (char *) fname,
									  source->channels, source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
				switch_yield(1000000);
				continue;
			}

			if (switch_core_file_has_video(&fh)) {
				flush_video_queue(source->video_q);
			}

			if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
				switch_dir_close(source->dir_handle);
				source->dir_handle = NULL;
				goto done;
			}

			switch_img_free(&source->cover_art);
			switch_set_string(tmp_buf, path_buf);
			if ((p = strrchr(tmp_buf, '/'))) {
				*p++ = '\0';
				switch_snprintf(png_buf, sizeof(png_buf), "%s/art/%s.png", tmp_buf, p);				
				if (switch_file_exists(png_buf, source->pool) == SWITCH_STATUS_SUCCESS) {
					source->cover_art = switch_img_read_png(png_buf, SWITCH_IMG_FMT_I420);
				}
			}

			source->serno++;
			switch_safe_free(source->banner_txt);
			title = artist = NULL;
			
			switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, &artist);
			switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_TITLE, &title);
			
			if (title && (source->cover_art || switch_core_file_has_video(&fh))) {
				const char *format = "#cccccc:#333333:FreeSans.ttf:3%:";

				if (artist) {
					source->banner_txt = switch_mprintf("%s%s (%s)", format, title, artist);
				} else {
					source->banner_txt = switch_mprintf("%s%s", format, title);
				}
			}

			while (RUNNING && !source->stopped) {
				int is_open;
				switch_file_handle_t *use_fh = &fh;

				switch_core_timer_next(&timer);
				olen = source->samples;
				
				if (source->chime_total) {

					if (source->chime_counter > 0) {
						source->chime_counter -= (int32_t)source->samples;
					}

					if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) {
						char *val;

						val = source->chime_list[source->chime_cur++];

						if (source->chime_cur >= source->chime_total) {
							source->chime_cur = 0;
						}

						if (switch_core_file_open(&source->chime_fh,
												  (char *) val,
												  source->channels,
												  source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val);
						}


						if (switch_core_file_has_video(&source->chime_fh)) {
							flush_video_queue(source->video_q);
						}

					}

					if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
						use_fh = &source->chime_fh;
					}
				}

			retry:

				source->has_video = switch_core_file_has_video(use_fh) || source->cover_art || source->banner_txt;

				is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);

				if (source->hup) {
					source->hup = 0;
					if (is_open) {
						is_open = 0;

						switch_core_file_close(use_fh);
						flush_video_queue(source->video_q);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							switch_core_file_close(&fh);
							use_fh = &fh;							
						}
						goto retry;
					}
				}
				
				if (is_open) {
					if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
						switch_frame_t vid_frame = { 0 };

						if (use_fh == &source->chime_fh && switch_core_file_has_video(&fh)) {
							if (switch_core_file_read_video(&fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
								switch_img_free(&vid_frame.img);
							}
						}

						if (switch_core_file_read_video(use_fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
							if (vid_frame.img) {
								int flush = 1;

								source->has_video = 1;
								
								if (source->total) {
									if (switch_queue_trypush(source->video_q, vid_frame.img) == SWITCH_STATUS_SUCCESS) {
										flush = 0;
									}
								}

								if (flush) {
									switch_img_free(&vid_frame.img);
									flush_video_queue(source->video_q);
								}
							}
						}
					} else {
						source->has_video = 0;
					}

					if (use_fh == &source->chime_fh) {
						olen = source->samples;
						switch_core_file_read(&fh, abuf, &olen);
						olen = source->samples;
					}

					if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
						switch_core_file_close(use_fh);
						flush_video_queue(source->video_q);

						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							use_fh = &fh;
						} else {
							is_open = 0;
						}
					} else {
						if (use_fh == &source->chime_fh && source->chime_max) {
							source->chime_max_counter += (int32_t)source->samples;
							if (source->chime_max_counter >= source->chime_max) {
								source->chime_max_counter = 0;
								switch_core_file_close(use_fh);
								flush_video_queue(source->video_q);
								source->chime_counter = source->rate * source->chime_freq;
								use_fh = &fh;
								goto retry;
							}
						}
						
						if (source->total) {
							switch_buffer_write(audio_buffer, abuf, olen * 2 * source->channels);
						} else {
							switch_buffer_zero(audio_buffer);
						}
					}
				}

				used = switch_buffer_inuse(audio_buffer);

				if (!used && !is_open) {
					break;
				}

				if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
					void *pop;

					used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);

					if (!source->total) {
						flush_video_queue(source->video_q);
					} else {
						uint32_t bused = 0;

						switch_mutex_lock(source->mutex);
						for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
							
							if (source->has_video) {
								switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
							} else {
								switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
							}
							
							if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
								continue;
							}
							
							switch_mutex_lock(cp->audio_mutex);
							bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
							if (bused > source->samples * 768) {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", 
												  cp->func, cp->file, cp->line, bused, (long)source->samples);
								switch_buffer_zero(cp->audio_buffer);
							} else {
								switch_buffer_write(cp->audio_buffer, dist_buf, used);
							}
							switch_mutex_unlock(cp->audio_mutex);
						}
						switch_mutex_unlock(source->mutex);

						
						while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
							switch_image_t *img = (switch_image_t *) pop;
							switch_image_t *imgcp = NULL;

							if (source->total == 1) {
								switch_queue_push(source->context_list->video_q, img);
							} else {
								if (source->context_list) {
									switch_mutex_lock(source->mutex);
									for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
										if (cp->video_q) {
											imgcp = NULL;
											switch_img_copy(img, &imgcp);
											if (imgcp) {
												if (switch_queue_trypush(cp->video_q, imgcp) != SWITCH_STATUS_SUCCESS) {
													flush_video_queue(cp->video_q);
												}
											}
										}
									}
									switch_mutex_unlock(source->mutex);
								}
								switch_img_free(&img);
							}
						}
					}
				}
			}

			switch_core_timer_destroy(&timer);
			if (RUNNING && source->shuffle) {
				skip = do_rand(dir_count);
			}
		}

		switch_dir_close(source->dir_handle);
		source->dir_handle = NULL;

		if (source->full_reload) {
			if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name);
				if (source->part_reload) {
					switch_xml_t cfg, xml, directory, param;
					if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
					}
					if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) {
						for (param = switch_xml_child(directory, "param"); param; param = param->next) {
							char *var = (char *) switch_xml_attr_soft(param, "name");
							char *val = (char *) switch_xml_attr_soft(param, "value");
							if (!strcasecmp(var, "shuffle")) {
								source->shuffle = switch_true(val);
							} else if (!strcasecmp(var, "chime-freq")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_freq = tmp;
								}
							} else if (!strcasecmp(var, "chime-max")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_max = tmp;
								}
							} else if (!strcasecmp(var, "chime-list")) {
								char *list_dup = switch_core_strdup(source->pool, val);
								source->chime_total =
									switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0])));
							} else if (!strcasecmp(var, "interval")) {
								int tmp = atoi(val);
								if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
									source->interval = tmp;
								} else {
									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
													  "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
								}
							}
							if (source->chime_max) {
								source->chime_max *= source->rate;
							}
							if (source->chime_total) {
								source->chime_counter = source->rate * source->chime_freq;
							}
						}
					}
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
					source->part_reload = 0;
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
				launch_streams(source->name);
				goto done;
			}
		}
	}

  done:

	switch_safe_free(source->banner_txt);
	
	if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&fh);
	}

	if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&source->chime_fh);
	}

	source->ready = 0;
	switch_mutex_lock(globals.mutex);
	switch_core_hash_delete(globals.source_hash, source->name);
	switch_mutex_unlock(globals.mutex);

	switch_thread_rwlock_wrlock(source->rwlock);
	switch_thread_rwlock_unlock(source->rwlock);

	switch_buffer_destroy(&audio_buffer);

	flush_video_queue(source->video_q);

	if (fd > -1) {
		close(fd);
	}

	if (temp_pool) {
		switch_core_destroy_memory_pool(&temp_pool);
	}

	switch_core_destroy_memory_pool(&source->pool);

	switch_mutex_lock(globals.mutex);
	THREADS--;
	switch_mutex_unlock(globals.mutex);

	return NULL;
}