environment.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include <unistd.h>
  2. #include "term.h"
  3. #include "environment.h"
  4. /**
  5. * Static handles.
  6. */
  7. #define DEFAULT_CTX_LABEL "urn:lsup:default"
  8. /** @brief Environment "singleton".
  9. */
  10. LSUP_Env *LSUP_default_env = NULL;
  11. /*
  12. * Hashmap callbacks.
  13. */
  14. static uint64_t term_cache_hash_fn (
  15. const void *item, uint64_t seed0, uint64_t seed1)
  16. { return ((const LSUP_KeyedTerm *) item)->key; }
  17. static int term_cache_cmp_fn (const void *a, const void *b, void *udata)
  18. {
  19. return
  20. ((const LSUP_KeyedTerm *) a)->key -
  21. ((const LSUP_KeyedTerm *) b)->key;
  22. }
  23. static void term_cache_free_fn (void *item)
  24. { LSUP_term_free (((LSUP_KeyedTerm *) item)->term); }
  25. /*
  26. * API
  27. */
  28. LSUP_Env *
  29. LSUP_env_new (
  30. const char *default_ctx, const char *mdb_path,
  31. const LSUP_NSMap *nsmap)
  32. {
  33. LSUP_Env *env;
  34. CALLOC_GUARD (env, NULL);
  35. // Default store context.
  36. LSUP_Term *default_ctx_uri = LSUP_iriref_new (default_ctx, NULL);
  37. env->default_ctx = LSUP_term_serialize (default_ctx_uri);
  38. LSUP_term_free (default_ctx_uri);
  39. log_info ("Set up default context.");
  40. // Set up store if not existing.
  41. if (LSUP_mdbstore_setup (mdb_path, false) != LSUP_OK) return NULL;
  42. env->mdb_store = LSUP_mdbstore_new (mdb_path, env->default_ctx);
  43. if (UNLIKELY (!env->mdb_store)) return NULL;
  44. log_info ("Initialized persistent back end at %s.", mdb_path);
  45. // Get default namespace from store.
  46. RCNL (LSUP_mdbstore_nsm_get (env->mdb_store, &env->nsm));
  47. return env;
  48. }
  49. LSUP_rc
  50. LSUP_init (void)
  51. {
  52. LSUP_rc rc = LSUP_NOACTION;
  53. if (LSUP_env_is_init) return rc;
  54. #ifdef DEBUG
  55. // In debug mode, always use max logging.
  56. int loglevel = LOG_TRACE;
  57. #else
  58. char *_loglevel = getenv ("LSUP_LOGLEVEL");
  59. int loglevel = (_loglevel == NULL) ? LOG_INFO : atoi (_loglevel);
  60. #endif
  61. log_set_level (loglevel);
  62. // URI validation pattern.
  63. MALLOC_GUARD (LSUP_uri_ptn, LSUP_MEM_ERR);
  64. /* Uncomment in case a change in the URI regex results in an error.
  65. int regex_rc = regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED);
  66. if (regex_rc != 0) {
  67. char err_msg[128];
  68. size_t err_msg_sz = regerror (regex_rc, LSUP_uri_ptn, err_msg, 128);
  69. log_error (
  70. "Error compiling regular expression pattern: %s.",
  71. err_msg);
  72. return LSUP_ERROR;
  73. }
  74. */
  75. if (regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED) != 0) {
  76. log_error ("Error compiling regular expression pattern.");
  77. return LSUP_ERROR;
  78. }
  79. // Initialize term cache.
  80. LSUP_term_cache = hashmap_new (
  81. sizeof(LSUP_KeyedTerm), 0, LSUP_HASH_SEED, 0,
  82. term_cache_hash_fn, term_cache_cmp_fn, term_cache_free_fn, NULL);
  83. // Create and cache default literal datatype key.
  84. LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL);
  85. uint32_t dtype_hash = LSUP_term_hash (LSUP_default_datatype );
  86. LSUP_tcache_add (dtype_hash, LSUP_default_datatype);
  87. // Default permanent store path.
  88. char *mdb_path = getenv ("LSUP_MDB_STORE_PATH");
  89. if (!mdb_path) {
  90. mdb_path = DEFAULT_ENV_PATH;
  91. log_warn (
  92. "`LSUP_MDB_STORE_PATH' environment variable is not "
  93. "set. The default location %s will be used as the graph "
  94. "store.", mdb_path
  95. );
  96. }
  97. // Default permanent store.
  98. LSUP_default_env = LSUP_env_new (
  99. DEFAULT_CTX_LABEL, mdb_path, NULL);
  100. if (UNLIKELY (!LSUP_default_env)) return LSUP_ERROR;
  101. // RAM disk store.
  102. if (LSUP_mdbstore_setup (LSUP_MDB_RAMDISK_PATH, true) != LSUP_OK) {
  103. log_error ("Error setting up RAM disk store files.");
  104. return LSUP_DB_ERR;
  105. }
  106. LSUP_default_env->mdb_store_ramdisk = LSUP_mdbstore_new (
  107. LSUP_MDB_RAMDISK_PATH, LSUP_default_env->default_ctx);
  108. if (UNLIKELY (!LSUP_default_env->mdb_store_ramdisk)) {
  109. log_error ("Error setting up RAM disk store.");
  110. return LSUP_DB_ERR;
  111. }
  112. log_info ("Initialized RAM disk back end at %s.", LSUP_MDB_RAMDISK_PATH);
  113. // Set automatic teardown TODO Is this a good idea?
  114. atexit (LSUP_done);
  115. LSUP_env_is_init = true;
  116. return LSUP_OK;
  117. }
  118. void
  119. LSUP_env_free (LSUP_Env *env)
  120. {
  121. LSUP_mdbstore_free (env->mdb_store);
  122. LSUP_mdbstore_free (env->mdb_store_ramdisk);
  123. LSUP_buffer_free (env->default_ctx);
  124. LSUP_nsmap_free (env->nsm);
  125. free (env);
  126. }
  127. void
  128. LSUP_done (void)
  129. {
  130. if (!LSUP_env_is_init) return;
  131. LSUP_env_free (LSUP_default_env);
  132. regfree (LSUP_uri_ptn);
  133. free (LSUP_uri_ptn);
  134. // Free ID cache, including default literal datatype.
  135. hashmap_free (LSUP_term_cache);
  136. LSUP_env_is_init = false;
  137. }