#include #include "term.h" #include "environment.h" /** * Static handles. */ #define DEFAULT_CTX_LABEL "urn:lsup:default" /** @brief Environment "singleton". */ LSUP_Env *LSUP_default_env = NULL; LSUP_Env * LSUP_env_new ( const char *default_ctx, const char *mdb_path, const LSUP_NSMap *nsmap) { LSUP_Env *env; CALLOC_GUARD (env, NULL); // Default store context. LSUP_Term *default_ctx_uri = LSUP_iriref_new (default_ctx, NULL); env->default_ctx = LSUP_term_serialize (default_ctx_uri); LSUP_term_free (default_ctx_uri); log_info ("Set up default context."); // Set up store if not existing. if (LSUP_mdbstore_setup (mdb_path, false) != LSUP_OK) return NULL; env->mdb_store = LSUP_mdbstore_new (mdb_path, env->default_ctx); if (UNLIKELY (!env->mdb_store)) return NULL; log_info ("Initialized persistent back end at %s.", mdb_path); // Get default namespace from store. RCNL (LSUP_mdbstore_nsm_get (env->mdb_store, &env->nsm)); return env; } LSUP_rc LSUP_init (void) { LSUP_rc rc = LSUP_NOACTION; if (LSUP_default_env == NULL) { #ifdef DEBUG // In debug mode, always use max logging. int loglevel = LOG_TRACE; #else char *_loglevel = getenv ("LSUP_LOGLEVEL"); int loglevel = (_loglevel == NULL) ? LOG_INFO : atoi (_loglevel); #endif log_set_level (loglevel); // URI validation pattern. MALLOC_GUARD (LSUP_uri_ptn, LSUP_MEM_ERR); /* Uncomment in case a change in the URI regex results in an error. int regex_rc = regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED); if (regex_rc != 0) { char err_msg[128]; size_t err_msg_sz = regerror (regex_rc, LSUP_uri_ptn, err_msg, 128); log_error ( "Error compiling regular expression pattern: %s.", err_msg); return LSUP_ERROR; } */ if (regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED) != 0) { log_error ("Error compiling regular expression pattern."); return LSUP_ERROR; } // Default literal datatype key. LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL); // Default permanent store path. char *mdb_path = getenv ("LSUP_MDB_STORE_PATH"); if (!mdb_path) { mdb_path = DEFAULT_ENV_PATH; log_warn ( "`LSUP_MDB_STORE_PATH' environment variable is not " "set. The default location %s will be used as the graph " "store.", mdb_path ); } // Default permanent store. LSUP_default_env = LSUP_env_new ( DEFAULT_CTX_LABEL, mdb_path, NULL); // RAM disk store. if (LSUP_mdbstore_setup (LSUP_MDB_RAMDISK_PATH, true) != LSUP_OK) log_error ("Error setting up RAM disk store."); LSUP_default_env->mdb_store_ramdisk = LSUP_mdbstore_new ( LSUP_MDB_RAMDISK_PATH, LSUP_default_env->default_ctx); if (UNLIKELY (!LSUP_default_env->mdb_store_ramdisk)) log_error ("Error setting up RAM disk store."); log_info ("Initialized RAM disk back end at %s.", LSUP_MDB_RAMDISK_PATH); if (!LSUP_default_env) rc = LSUP_DB_ERR; // Set automatic teardown TODO Is this a good idea? atexit (LSUP_done); rc = LSUP_OK; } return rc; } void LSUP_env_free (LSUP_Env *env) { LSUP_mdbstore_free (env->mdb_store); LSUP_mdbstore_free (env->mdb_store_ramdisk); LSUP_buffer_free (env->default_ctx); LSUP_nsmap_free (env->nsm); // Free ID cache. struct term_cache_t *entry, *tmp; HASH_ITER (hh, LSUP_term_cache, entry, tmp) { HASH_DEL (LSUP_term_cache, entry); LSUP_term_free (entry->term); free (entry); } free (env); } void LSUP_done (void) { LSUP_env_free (LSUP_default_env); regfree (LSUP_uri_ptn); free (LSUP_uri_ptn); }