#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; /* * Hashmap callbacks. */ static uint64_t term_cache_hash_fn ( const void *item, uint64_t seed0, uint64_t seed1) { return ((const LSUP_KeyedTerm *) item)->key; } static int term_cache_cmp_fn (const void *a, const void *b, void *udata) { return ((const LSUP_KeyedTerm *) a)->key - ((const LSUP_KeyedTerm *) b)->key; } static void term_cache_free_fn (void *item) { LSUP_term_free (((LSUP_KeyedTerm *) item)->term); } /* * API */ 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_env_is_init) return rc; #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; } // Initialize term cache. LSUP_term_cache = hashmap_new ( sizeof(LSUP_KeyedTerm), 0, LSUP_HASH_SEED, 0, term_cache_hash_fn, term_cache_cmp_fn, term_cache_free_fn, NULL); // Create and cache default literal datatype key. LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL); uint32_t dtype_hash = LSUP_term_hash (LSUP_default_datatype ); LSUP_tcache_add (dtype_hash, LSUP_default_datatype); // 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); if (UNLIKELY (!LSUP_default_env)) return LSUP_ERROR; // RAM disk store. if (LSUP_mdbstore_setup (LSUP_MDB_RAMDISK_PATH, true) != LSUP_OK) { log_error ("Error setting up RAM disk store files."); return LSUP_DB_ERR; } 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."); return LSUP_DB_ERR; } log_info ("Initialized RAM disk back end at %s.", LSUP_MDB_RAMDISK_PATH); // Set automatic teardown TODO Is this a good idea? atexit (LSUP_done); LSUP_env_is_init = true; return LSUP_OK; } 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 (env); } void LSUP_done (void) { if (!LSUP_env_is_init) return; LSUP_env_free (LSUP_default_env); regfree (LSUP_uri_ptn); free (LSUP_uri_ptn); // Free ID cache, including default literal datatype. hashmap_free (LSUP_term_cache); LSUP_env_is_init = false; }