1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * rdf_init.c - Redland library initialisation / termination and memory
4  *              management
5  *
6  * Copyright (C) 2000-2012, David Beckett http://www.dajobe.org/
7  * Copyright (C) 2000-2005, University of Bristol, UK http://www.bristol.ac.uk/
8  *
9  * This package is Free Software and part of Redland http://librdf.org/
10  *
11  * It is licensed under the following three licenses as alternatives:
12  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
13  *   2. GNU General Public License (GPL) V2 or any newer version
14  *   3. Apache License, V2.0 or any newer version
15  *
16  * You may not use this file except in compliance with at least one of
17  * the above three licenses.
18  *
19  * See LICENSE.html or LICENSE.txt at the top of this package for the
20  * complete terms and further detail along with the license texts for
21  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
22  *
23  *
24  */
25 
26 
27 #ifdef HAVE_CONFIG_H
28 #include <rdf_config.h>
29 #endif
30 
31 #ifdef WIN32
32 #include <win32_rdf_config.h>
33 #endif
34 
35 #include <stdio.h>
36 #include <string.h>
37 #ifdef WITH_THREADS
38 #include <pthread.h>
39 #endif
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h> /* for getpid() */
45 #endif
46 
47 /* for gettimeofday */
48 #if TIME_WITH_SYS_TIME
49 #include <sys/time.h>
50 #include <time.h>
51 #else
52 #if HAVE_SYS_TIME_H
53 #include <sys/time.h>
54 #else
55 #include <time.h>
56 #endif
57 #endif
58 
59 #include <redland.h>
60 /* for getpid */
61 #include <sys/types.h>
62 #ifdef HAVE_UNISTD
63 #include <unistd.h>
64 #endif
65 
66 #ifdef MODULAR_LIBRDF
67 #include <ltdl.h>
68 #endif
69 
70 #ifndef STANDALONE
71 
72 const char * const librdf_short_copyright_string = "Copyright 2000-2012 David Beckett. Copyright 2000-2005 University of Bristol";
73 
74 const char * const librdf_copyright_string = "Copyright (C) 2000-2012 David Beckett - http://www.dajobe.org/\nCopyright (C) 2000-2005 University of Bristol - http://www.bristol.ac.uk/";
75 
76 const char * const librdf_license_string = "LGPL 2.1 or newer, GPL 2 or newer, Apache 2.0 or newer.\nSee http://librdf.org/LICENSE.html for full terms.";
77 
78 const char * const librdf_home_url_string = "http://librdf.org/";
79 
80 
81 /**
82  * librdf_version_string:
83  *
84  * Library full version as a string.
85  *
86  * See also #librdf_version_decimal.
87  */
88 const char * const librdf_version_string = VERSION;
89 
90 /**
91  * librdf_version_major:
92  *
93  * Library major version number as a decimal integer.
94  */
95 const unsigned int librdf_version_major = LIBRDF_VERSION_MAJOR;
96 
97 /**
98  * librdf_version_minor:
99  *
100  * Library minor version number as a decimal integer.
101  */
102 const unsigned int librdf_version_minor = LIBRDF_VERSION_MINOR;
103 
104 /**
105  * librdf_version_release:
106  *
107  * Library release version number as a decimal integer.
108  */
109 const unsigned int librdf_version_release = LIBRDF_VERSION_RELEASE;
110 
111 /**
112  * librdf_version_decimal:
113  *
114  * Library full version as a decimal integer.
115  *
116  * See also #librdf_version_string.
117  */
118 const unsigned int librdf_version_decimal = LIBRDF_VERSION_DECIMAL;
119 
120 
121 
122 
123 /**
124  * librdf_new_world:
125  *
126  * Create a new Redland execution environment.
127  *
128  * Once this constructor is called to build a #librdf_world object
129  * several functions may be called to set some parameters such as
130  * librdf_world_set_error(), librdf_world_set_warning(),
131  * librdf_world_set_logger(), librdf_world_set_digest(),
132  * librdf_world_set_feature().
133  *
134  * The world object needs initializing using librdf_world_open()
135  * whether or not the above functions are called.  It will be
136  * automatically called by all object constructors in Redland 1.0.6
137  * or later, but for earlier versions it MUST be called before using
138  * any other part of Redland.
139  *
140  * Returns: a new #librdf_world or NULL on failure
141  */
142 librdf_world*
librdf_new_world(void)143 librdf_new_world(void)
144 {
145   librdf_world *world;
146 #ifdef HAVE_GETTIMEOFDAY
147   struct timeval tv;
148   struct timezone tz;
149 #endif
150 
151   world = LIBRDF_CALLOC(librdf_world*, 1, sizeof(*world));
152 
153   if(!world)
154     return NULL;
155 
156 #ifdef HAVE_GETTIMEOFDAY
157   if(!gettimeofday(&tv, &tz)) {
158     world->genid_base = LIBRDF_GOOD_CAST(unsigned long, tv.tv_sec);
159   } else
160     world->genid_base = 1;
161 #else
162   world->genid_base = 1;
163 #endif
164   world->genid_counter = 1;
165 
166 #ifdef MODULAR_LIBRDF
167   world->ltdl_opened = !(lt_dlinit());
168   if (world->ltdl_opened)
169     lt_dlsetsearchpath(REDLAND_MODULE_PATH);
170 #ifdef LIBRDF_DEBUG
171   else
172     LIBRDF_DEBUG1("lt_dlinit() failed\n");
173 #endif
174 #endif
175 
176   return world;
177 
178 }
179 
180 
181 /**
182  * librdf_free_world:
183  * @world: redland world object
184  *
185  * Terminate the library and frees all allocated resources.
186  **/
187 void
librdf_free_world(librdf_world * world)188 librdf_free_world(librdf_world *world)
189 {
190   if(!world)
191     return;
192 
193   librdf_finish_serializer(world);
194   librdf_finish_parser(world);
195 
196   librdf_finish_storage(world);
197   librdf_finish_query(world);
198   librdf_finish_model(world);
199   librdf_finish_statement(world);
200 
201   librdf_finish_concepts(world);
202 
203   librdf_finish_node(world);
204   librdf_finish_uri(world);
205 
206   /* Uses rdf_hash so free before destroying hashes */
207   librdf_finish_raptor(world);
208 
209   librdf_finish_hash(world);
210 
211   librdf_finish_digest(world);
212 
213 #ifdef WITH_THREADS
214 
215   if(world->hash_datums_mutex) {
216     pthread_mutex_destroy(world->hash_datums_mutex);
217     SYSTEM_FREE(world->hash_datums_mutex);
218     world->hash_datums_mutex = NULL;
219   }
220 
221   if(world->statements_mutex) {
222     pthread_mutex_destroy(world->statements_mutex);
223     SYSTEM_FREE(world->statements_mutex);
224     world->statements_mutex = NULL;
225   }
226 
227   if(world->nodes_mutex) {
228     pthread_mutex_destroy(world->nodes_mutex);
229     SYSTEM_FREE(world->nodes_mutex);
230     world->nodes_mutex = NULL;
231   }
232 
233   if(world->mutex) {
234     pthread_mutex_destroy(world->mutex);
235     SYSTEM_FREE(world->mutex);
236     world->mutex = NULL;
237   }
238 
239 
240 #endif
241 
242 #ifdef MODULAR_LIBRDF
243   if (world->ltdl_opened)
244     lt_dlexit();
245 #endif
246 
247   LIBRDF_FREE(librdf_world, world);
248 }
249 
250 
251 /**
252  * librdf_world_init_mutex:
253  * @world: redland world object
254  *
255  * INTERNAL - Create the world mutex.
256  */
257 void
librdf_world_init_mutex(librdf_world * world)258 librdf_world_init_mutex(librdf_world* world)
259 {
260 #ifdef WITH_THREADS
261   world->mutex = (pthread_mutex_t *) SYSTEM_MALLOC(sizeof(pthread_mutex_t));
262   pthread_mutex_init(world->mutex, NULL);
263 
264   world->nodes_mutex = (pthread_mutex_t *) SYSTEM_MALLOC(sizeof(pthread_mutex_t));
265   pthread_mutex_init(world->nodes_mutex, NULL);
266 
267   world->statements_mutex = (pthread_mutex_t *) SYSTEM_MALLOC(sizeof(pthread_mutex_t));
268   pthread_mutex_init(world->statements_mutex, NULL);
269 
270   world->hash_datums_mutex = (pthread_mutex_t *) SYSTEM_MALLOC(sizeof(pthread_mutex_t));
271   pthread_mutex_init(world->hash_datums_mutex, NULL);
272 
273 #else
274 #endif
275 }
276 
277 
278 /**
279  * librdf_world_open:
280  * @world: redland world object
281  *
282  * Open a created redland world environment.
283  **/
284 void
librdf_world_open(librdf_world * world)285 librdf_world_open(librdf_world *world)
286 {
287   int rc = 0;
288 
289   if(world->opened++)
290     return;
291 
292   librdf_world_init_mutex(world);
293 
294   /* Digests second, lots of things use these */
295   librdf_init_digest(world);
296 
297   /* Hash next, needed for URIs */
298   librdf_init_hash(world);
299 
300   /* Initialize raptor; uses rdf_hash for bnode mapping */
301   librdf_init_raptor(world);
302 
303   librdf_init_uri(world);
304   librdf_init_node(world);
305 
306   librdf_init_concepts(world);
307 
308   librdf_init_statement(world);
309   librdf_init_model(world);
310   librdf_init_storage(world);
311 
312   librdf_init_parser(world);
313   librdf_init_serializer(world);
314 
315   rc = librdf_init_query(world);
316   if(rc)
317     goto failed;
318 
319   return;
320 
321 failed:
322   /* should return an error state */
323   return;
324 }
325 
326 
327 /**
328  * librdf_world_set_rasqal:
329  * @world: librdf_world object
330  * @rasqal_world_ptr: rasqal_world object
331  *
332  * Set the #rasqal_world instance to be used with this #librdf_world.
333  *
334  * If no rasqal_world instance is set with this function,
335  * librdf_world_open() creates a new instance.
336  *
337  * Ownership of the rasqal_world is not taken. If the rasqal library
338  * instance is set with this function, librdf_free_world() will not
339  * free it.
340  *
341  **/
342 void
librdf_world_set_rasqal(librdf_world * world,rasqal_world * rasqal_world_ptr)343 librdf_world_set_rasqal(librdf_world* world, rasqal_world* rasqal_world_ptr)
344 {
345   LIBRDF_ASSERT_OBJECT_POINTER_RETURN(world, librdf_world);
346   world->rasqal_world_ptr = rasqal_world_ptr;
347   world->rasqal_world_allocated_here = 0;
348 }
349 
350 
351 /**
352  * librdf_world_get_rasqal:
353  * @world: librdf_world object
354  *
355  * Get the #rasqal_world instance used by this #librdf_world.
356  *
357  * Return value: rasqal_world object or NULL on failure (e.g. not initialized)
358  **/
359 rasqal_world*
librdf_world_get_rasqal(librdf_world * world)360 librdf_world_get_rasqal(librdf_world* world)
361 {
362   LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, librdf_world, NULL);
363   return world->rasqal_world_ptr;
364 }
365 
366 
367 /**
368  * librdf_world_set_error:
369  * @world: redland world object
370  * @user_data: user data to pass to function
371  * @error_handler: pointer to the function
372  *
373  * Set the world error handling function.
374  *
375  * The function will receive callbacks when the world fails.
376  * librdf_world_set_logger() provides richer access to all log messages
377  * and should be used in preference.
378  **/
379 void
librdf_world_set_error(librdf_world * world,void * user_data,librdf_log_level_func error_handler)380 librdf_world_set_error(librdf_world* world, void *user_data,
381                        librdf_log_level_func error_handler)
382 {
383   world->error_user_data = user_data;
384   world->error_handler = error_handler;
385 }
386 
387 
388 /**
389  * librdf_world_set_warning:
390  * @world: redland world object
391  * @user_data: user data to pass to function
392  * @warning_handler: pointer to the function
393  *
394  * Set the world warning handling function.
395  *
396  * The function will receive callbacks when the world gives a warning.
397  * librdf_world_set_logger() provides richer access to all log messages
398  * and should be used in preference.
399  **/
400 void
librdf_world_set_warning(librdf_world * world,void * user_data,librdf_log_level_func warning_handler)401 librdf_world_set_warning(librdf_world* world, void *user_data,
402                          librdf_log_level_func warning_handler)
403 {
404   world->warning_user_data = user_data;
405   world->warning_handler = warning_handler;
406 }
407 
408 
409 
410 /**
411  * librdf_world_set_logger:
412  * @world: redland world object
413  * @user_data: user data to pass to function
414  * @log_handler: pointer to the function
415  *
416  * Set the world log handling function.
417  *
418  * The function will receive callbacks when redland generates a log message
419  **/
420 void
librdf_world_set_logger(librdf_world * world,void * user_data,librdf_log_func log_handler)421 librdf_world_set_logger(librdf_world* world, void *user_data,
422                         librdf_log_func log_handler)
423 {
424   world->log_user_data = user_data;
425   world->log_handler = log_handler;
426 }
427 
428 
429 
430 /**
431  * librdf_world_set_digest:
432  * @world: redland world object
433  * @name: Digest factory name
434  *
435  * Set the default content digest name.
436  *
437  * Sets the digest factory for various modules that need to make
438  * digests of their objects.
439  */
440 void
librdf_world_set_digest(librdf_world * world,const char * name)441 librdf_world_set_digest(librdf_world* world, const char *name)
442 {
443   world->digest_factory_name = (char*)name;
444 }
445 
446 
447 /**
448  * librdf_world_get_feature:
449  * @world: #librdf_world object
450  * @feature: #librdf_uri feature property
451  *
452  * Get the value of a world feature.
453  *
454  * Return value: new #librdf_node feature value or NULL if no such feature
455  * exists or the value is empty.
456  **/
457 librdf_node*
librdf_world_get_feature(librdf_world * world,librdf_uri * feature)458 librdf_world_get_feature(librdf_world* world, librdf_uri *feature)
459 {
460   return NULL; /* none retrievable */
461 }
462 
463 
464 /**
465  * librdf_world_set_feature:
466  * @world: #librdf_world object
467  * @feature: #librdf_uri feature property
468  * @value: #librdf_node feature property value
469  *
470  * Set the value of a world feature.
471  *
472  * Return value: non 0 on failure (negative if no such feature)
473  **/
474 int
librdf_world_set_feature(librdf_world * world,librdf_uri * feature,librdf_node * value)475 librdf_world_set_feature(librdf_world* world, librdf_uri* feature,
476                          librdf_node* value)
477 {
478   librdf_uri* genid_base;
479   librdf_uri* genid_counter;
480   int rc= -1;
481 
482   genid_counter = librdf_new_uri(world,
483                                  (const unsigned char*)LIBRDF_WORLD_FEATURE_GENID_COUNTER);
484   genid_base = librdf_new_uri(world,
485                               (const unsigned char*)LIBRDF_WORLD_FEATURE_GENID_BASE);
486 
487   if(librdf_uri_equals(feature, genid_base)) {
488     if(!librdf_node_is_resource(value))
489       rc=1;
490     else {
491       long lid = atol((const char*)librdf_node_get_literal_value(value));
492       if(lid < 1)
493         lid = 1;
494 
495 #ifdef WITH_THREADS
496       pthread_mutex_lock(world->mutex);
497 #endif
498       world->genid_base = LIBRDF_GOOD_CAST(unsigned long, lid);
499 #ifdef WITH_THREADS
500       pthread_mutex_unlock(world->mutex);
501 #endif
502       rc = 0;
503     }
504   } else if(librdf_uri_equals(feature, genid_counter)) {
505     if(!librdf_node_is_resource(value))
506       rc = 1;
507     else {
508       long lid = atol((const char*)librdf_node_get_literal_value(value));
509       if(lid < 1)
510         lid = 1;
511 
512 #ifdef WITH_THREADS
513       pthread_mutex_lock(world->mutex);
514 #endif
515       world->genid_counter = LIBRDF_GOOD_CAST(unsigned long, lid);
516 #ifdef WITH_THREADS
517       pthread_mutex_unlock(world->mutex);
518 #endif
519       rc = 0;
520     }
521   }
522 
523   librdf_free_uri(genid_base);
524   librdf_free_uri(genid_counter);
525 
526   return rc;
527 }
528 
529 
530 /* Internal */
531 unsigned char*
librdf_world_get_genid(librdf_world * world)532 librdf_world_get_genid(librdf_world* world)
533 {
534   unsigned long id, tmpid, counter, tmpcounter, pid, tmppid;
535   size_t length;
536   unsigned char *buffer;
537 
538   /* This is read-only and thread safe */
539   tmpid = (id = world->genid_base);
540 
541 #ifdef WITH_THREADS
542   pthread_mutex_lock(world->mutex);
543 #endif
544   tmpcounter = (counter = world->genid_counter++);
545 #ifdef WITH_THREADS
546   pthread_mutex_unlock(world->mutex);
547 #endif
548 
549   /* Add the process ID to the seed to differentiate between
550    * simultaneously executed child processes.
551    */
552   pid = LIBRDF_GOOD_CAST(unsigned long, getpid());
553   if(!pid)
554     pid = 1;
555   tmppid = pid;
556 
557 
558   /* min length 1 + "r" + min length 1 + "r" + min length 1 + "r" \0 */
559   length = 7;
560 
561   while(tmpid /= 10)
562     length++;
563   while(tmpcounter /= 10)
564     length++;
565   while(tmppid /= 10)
566     length++;
567 
568   buffer = LIBRDF_MALLOC(unsigned char*, length);
569   if(!buffer)
570     return NULL;
571 
572   sprintf((char*)buffer, "r%lur%lur%lu", id, pid, counter);
573   return buffer;
574 }
575 
576 
577 
578 /* OLD INTERFACES BELOW HERE */
579 
580 /* For old interfaces below ONLY */
581 #ifndef NO_STATIC_DATA
582 static librdf_world* RDF_World;
583 #endif
584 
585 #ifndef REDLAND_DISABLE_DEPRECATED
586 /**
587  * librdf_init_world:
588  * @digest_factory_name: Name of digest factory to use
589  * @not_used2: Not used
590  *
591  * Initialise the library
592  * @deprecated: Do not use.
593  *
594  * Use librdf_new_world() and librdf_world_open() on #librdf_world object
595  *
596  * See librdf_world_set_digest() for documentation on arguments.
597  **/
598 void
librdf_init_world(char * digest_factory_name,void * not_used2)599 librdf_init_world(char *digest_factory_name, void* not_used2)
600 {
601 #ifndef NO_STATIC_DATA
602   RDF_World = librdf_new_world();
603   if(!RDF_World)
604     return;
605 
606   if(digest_factory_name)
607     librdf_world_set_digest(RDF_World, digest_factory_name);
608   librdf_world_open(RDF_World);
609 #else
610   /* fail if NO_STATIC_DATA is defined */
611   abort();
612 #endif
613 }
614 
615 
616 /**
617  * librdf_destroy_world:
618  *
619  * Terminate the library
620  * @deprecated: Do not use.
621  *
622  * Use librdf_free_world() on #librdf_world object
623  *
624  * Terminates and frees the resources.
625  **/
626 void
librdf_destroy_world(void)627 librdf_destroy_world(void)
628 {
629 #ifndef NO_STATIC_DATA
630   librdf_free_world(RDF_World);
631 #else
632   /* fail if NO_STATIC_DATA is defined */
633   abort();
634 #endif
635 }
636 #endif
637 
638 /**
639  * librdf_basename:
640  * @name: path
641  *
642  * Get the basename of a path
643  *
644  * Return value: filename part of a pathname
645  **/
646 const char*
librdf_basename(const char * name)647 librdf_basename(const char *name)
648 {
649   const char *p;
650   if((p = strrchr(name, '/')))
651     name = p+1;
652   else if((p = strrchr(name, '\\')))
653     name = p+1;
654 
655   return name;
656 }
657 
658 
659 /**
660  * librdf_free_memory:
661  * @ptr: pointer to free
662  *
663  * Free memory allocated in the library.
664  *
665  * Required for some runtimes where memory must be freed within the same
666  * shared object it was allocated in.
667  **/
668 void
librdf_free_memory(void * ptr)669 librdf_free_memory(void *ptr)
670 {
671   raptor_free_memory(ptr);
672 }
673 
674 
675 /**
676  * librdf_alloc_memory:
677  * @size: alloc size
678  *
679  * Allocate memory inside the library similar to malloc().
680  *
681  * Required for some runtimes where memory must be freed within the same
682  * shared object it was allocated in.
683  *
684  * Return value: pointer to memory or NULL on failure
685  **/
686 void*
librdf_alloc_memory(size_t size)687 librdf_alloc_memory(size_t size)
688 {
689   return raptor_alloc_memory(size);
690 }
691 
692 /**
693  * librdf_calloc_memory:
694  * @nmemb: number of members
695  * @size: size of member
696  *
697  * Allocate zeroed array of items inside the library similar to calloc().
698  *
699  * Required for some runtimes where memory must be freed within the same
700  * shared object it was allocated in.
701  *
702  * Return value: pointer to memory or NULL on failure
703  **/
704 void*
librdf_calloc_memory(size_t nmemb,size_t size)705 librdf_calloc_memory(size_t nmemb, size_t size)
706 {
707   return raptor_calloc_memory(nmemb, size);
708 }
709 
710 
711 #endif /* STANDALONE */
712 
713 
714 /* TEST CODE */
715 
716 
717 #ifdef STANDALONE
718 
719 /* one more prototype */
720 int main(int argc, char *argv[]);
721 
722 
723 int
main(int argc,char * argv[])724 main(int argc, char *argv[])
725 {
726   librdf_world *world;
727   rasqal_world *rasqal_world;
728   unsigned char* id;
729   const char *program=librdf_basename((const char*)argv[0]);
730 
731   /* Minimal setup-cleanup test without opening the world */
732   fprintf(stdout, "%s: Creating new world\n", program);
733   world = librdf_new_world();
734   if(!world) {
735     fprintf(stderr, "%s: librdf_new_world failed\n", program);
736     return 1;
737   }
738   fprintf(stdout, "%s: Deleting world\n", program);
739   librdf_free_world(world);
740 
741 
742   /* Test setting and getting a the rasqal world */
743   fprintf(stdout, "%s: Setting and getting rasqal_world\n", program);
744   world = librdf_new_world();
745   if(!world) {
746     fprintf(stderr, "%s: librdf_new_world failed\n", program);
747     return 1;
748   }
749 
750   rasqal_world = rasqal_new_world();
751   if(!rasqal_world) {
752     fprintf(stderr, "%s: rasqal_new_world failed\n", program);
753     return 1;
754   }
755 
756   librdf_world_set_rasqal(world, rasqal_world);
757   if (librdf_world_get_rasqal(world) != rasqal_world) {
758     fprintf(stderr, "%s: librdf_world_set_rasqal/librdf_world_get_rasqal failed\n", program);
759     return 1;
760   }
761   rasqal_free_world(rasqal_world);
762   librdf_free_world(world);
763 
764 
765   /* Test id generation */
766   fprintf(stdout, "%s: Creating new world\n", program);
767   world = librdf_new_world();
768   if(!world) {
769     fprintf(stderr, "%s: librdf_new_world failed\n", program);
770     return 1;
771   }
772 
773   fprintf(stdout, "%s: Generating an identifier\n", program);
774   id = librdf_world_get_genid(world);
775   if(id == NULL || strlen((const char*)id) < 6) {
776     fprintf(stderr, "%s: librdf_world_get_genid failed\n", program);
777     return 1;
778   }
779   fprintf(stdout, "%s: New identifier is: '%s'\n", program, id);
780   LIBRDF_FREE(char*, id);
781 
782   fprintf(stdout, "%s: Deleting world\n", program);
783   librdf_free_world(world);
784 
785   /* keep gcc -Wall happy */
786   return(0);
787 }
788 
789 #endif
790