blob: 1628ba35f8d93a3ca5b41279fe3f2bb6b4ac8701 [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* etch_runtime.h -- runtime methods.
*/
#include "etch_runtime.h"
#include "etch_cache.h"
#include "etch_default_value_factory.h"
#include "etch_mem.h"
#include "etch_mutex.h"
#include "etchinternal_single_linked_list.h"
#include "apr_pools.h"
#include "apr_thread_mutex.h"
#include "etch_encoding.h"
#define MAX_SHUTDOWN_HOOKS_SIZE 5
// global data
apr_pool_t* g_etch_main_pool = NULL;
apr_thread_mutex_t* g_etch_main_pool_mutex = NULL;
static etch_runtime_shutdown_hook_func shutdown_hooks[5] =
{NULL,NULL,NULL,NULL,NULL};
static uint16 etch_runtime_version_major = 1;
static uint16 etch_runtime_version_minor = 1;
static uint16 etch_runtime_version_revision = 2;
//TODO
etch_global_constants etchgc;
/**
* etch_instantiate_global_constants()
* instantiate global constants. these are constants which can't be statically intialized.
* some of these may need to be freed in etch_free_global_constants in order that tests
* can show all memory freed. any etch objects instantiated here may need to have their
* is_static marker set in order that they remain instantiated throughout execution.
*/
void etch_instantiate_global_constants()
{
etchgc.etch_charsetname_us_ascii = L"us-ascii";
etchgc.etch_charsetname_utf8 = L"utf-8";
etchgc.etch_charsetname_utf16 = L"utf-16";
etchgc.pctd = "%d";
}
/* runtime data */
struct etch_runtime_t
{
uint32 count; /* ref counting value */
unsigned char state; /* state or runtime*/
etch_config_t* config;
unsigned char config_owned;
etch_log_t* logger;
};
/* init runtime data */
static struct etch_runtime_t etch_runtime = {
0,
0,
NULL,
0,
NULL
};
static etch_status_t etch_statics_create()
{
etch_instantiate_global_constants();
return ETCH_SUCCESS;
}
int etch_runtime_mem_abort(int retcode)
{
printf("*** APR MEMORY ERROR! Code=%d***\n", retcode);
// sleep 1 s
apr_sleep(1000 * 1000);
return APR_SUCCESS;
}
etch_status_t etch_runtime_initialize(etch_config_t* config)
{
etch_status_t etch_status = ETCH_SUCCESS;
apr_status_t apr_status = APR_SUCCESS;
if(etch_runtime.count++ > 0) {
return ETCH_SUCCESS;
}
if(etch_runtime.state == 0) {
// initialize apr
apr_status = apr_initialize();
if(apr_status != APR_SUCCESS) {
// log error
return -1;
}
// create apr memory pool
apr_status = apr_pool_create(&g_etch_main_pool, NULL);
//printf("1 creating apr pool %p\n",g_etch_main_pool);
if(apr_status != APR_SUCCESS) {
// log error
// shutdown apr
apr_terminate();
return ETCH_ERROR;
}
/* set pool abort function */
apr_pool_abort_set(etch_runtime_mem_abort, g_etch_main_pool);
/* set apr pool tag */
apr_pool_tag(g_etch_main_pool, "etch_apr_pool");
apr_status = apr_thread_mutex_create(&g_etch_main_pool_mutex, APR_THREAD_MUTEX_NESTED, g_etch_main_pool);
if(apr_status != APR_SUCCESS) {
// log error
// shutdown apr
apr_terminate();
return ETCH_ERROR;
}
etch_status = etch_encoding_initialize();
if(etch_status != ETCH_SUCCESS) {
apr_terminate();
return ETCH_ERROR;
}
// set configuration
if(config == NULL) {
etch_status = etch_config_create(&config);
if(etch_status != ETCH_SUCCESS) {
// error
}
etch_runtime.config_owned = 1;
}
etch_runtime.config = config;
// create logger
etch_status = etch_log_create(&etch_runtime.logger, etch_runtime.config);
if(etch_status != ETCH_SUCCESS) {
// error opening logger
}
// create etch cache
etch_status = etch_cache_create();
if(etch_status != ETCH_SUCCESS) {
// error opening logger
}
// create etch statics
etch_status = etch_statics_create();
if(etch_status != ETCH_SUCCESS) {
// error opening logger
}
// set initialized flag
etch_runtime.state = 1;
}
return ETCH_SUCCESS;
}
etch_status_t etch_runtime_get_version(uint16* major, uint16* minor, uint16* revision)
{
etch_status_t rv = ETCH_SUCCESS;
if(major == NULL || minor == NULL || revision == NULL) {
return ETCH_EINVAL;
}
*major = etch_runtime_version_major;
*minor = etch_runtime_version_minor;
*revision = etch_runtime_version_revision;
return rv;
}
etch_status_t etch_runtime_get_config(etch_config_t** config)
{
if(config == NULL) {
return ETCH_EINVAL;
}
*config = etch_runtime.config;
return ETCH_SUCCESS;
}
etch_status_t etch_runtime_get_logger(etch_log_t** logger)
{
if(logger == NULL) {
return ETCH_EINVAL;
}
*logger = etch_runtime.logger;
return ETCH_SUCCESS;
}
etch_status_t etch_runtime_shutdown()
{
int i = 0;
etch_status_t etch_status;
if(etch_runtime.count > 0) {
if(etch_runtime.count-- > 1) {
return ETCH_SUCCESS;
}
}
if(etch_runtime.state == 1) {
// destroy etch statics
for(; i < MAX_SHUTDOWN_HOOKS_SIZE; i++) {
if(shutdown_hooks[i]){
shutdown_hooks[i]();
}
}
etchvf_free_builtins();
// destroy cache
etch_cache_destroy();
// destroy logger
if(etch_runtime.logger != NULL) {
etch_log_destroy(etch_runtime.logger);
etch_runtime.logger = NULL;
}
// destroy config
if(etch_runtime.config_owned) {
etch_config_destroy(etch_runtime.config);
etch_runtime.config = NULL;
etch_runtime.config_owned = 0;
}
etch_status = etch_encoding_shutdown();
if(etch_status != ETCH_SUCCESS) {
apr_terminate();
return ETCH_ERROR;
}
/* destroy apr memory pool mutex */
apr_thread_mutex_destroy(g_etch_main_pool_mutex);
/* destroy apr memory pool */
//printf("1 destroying apr pool %p\n",g_etch_main_pool);
apr_pool_destroy(g_etch_main_pool);
g_etch_main_pool = NULL;
/* terminate apr */
apr_terminate();
/* set shutdown flag */
etch_runtime.state = 0;
}
return ETCH_SUCCESS;
}
etch_status_t etch_runtime_shutdown_hook_add(etch_runtime_shutdown_hook_func func)
{
int i = 0;
for(; i < MAX_SHUTDOWN_HOOKS_SIZE; i++)
{
if(shutdown_hooks[i] == NULL)
{
shutdown_hooks[i] = func;
return ETCH_SUCCESS;
}
}
return ETCH_ERROR;
}