1 /* Copyright (C) 2003, 2004, 2005, 2006, 2011, 2013 MORIOKA Tomohiko
2 This file is part of the CONCORD Library.
4 The CONCORD Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The CONCORD Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the CONCORD Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 #include <sys/types.h>
27 #include "concord-name.h"
29 #include "concord-bdb.h"
31 COS_Feature concord_opened_feature_list = NULL;
32 COS_Feature concord_opened_feature_list_last = NULL;
33 size_t concord_opened_feature_list_length = 0;
34 size_t concord_opened_feature_list_limit = 96;
36 COS_Feature_INDEX concord_opened_index_list = NULL;
37 COS_Feature_INDEX concord_opened_index_list_last = NULL;
38 size_t concord_opened_index_list_length = 0;
39 size_t concord_opened_index_list_limit = 32;
43 CONCORD_String_size (const CONCORD_String s)
49 CONCORD_String_data (const CONCORD_String s)
54 CONCORD_Genre concord_ds_open_genre (CONCORD_DS ds, const char* name);
58 concord_genre_open_feature (CONCORD_Genre genre, const char* name);
62 concord_genre_open_index (CONCORD_Genre genre, const char* index);
65 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name);
69 concord_default_read_object (const unsigned char* string, size_t length);
74 COS_Object_Header header;
75 CONCORD_Backend_Type type;
77 CONCORD_NAME_TABLE* genre_names;
81 CONCORD_Object object_nil;
82 CONCORD_Object (*read_object) (const unsigned char* str, size_t length);
86 concord_default_read_object (const unsigned char* str, size_t length)
88 unsigned char* buf = malloc (length + 1);
92 strncpy ((char*)buf, (char*)str, length);
94 return (CONCORD_Object)buf;
98 concord_open_ds (CONCORD_Backend_Type type, const char* location,
99 int subtype, int modemask)
101 CONCORD_DS ds = COS_ALLOCATE_OBJECT (DS);
102 size_t len = strlen (location);
108 ds->subtype = ( (subtype != 0) ? subtype : DB_HASH );
109 ds->modemask = modemask;
110 ds->location = (char*)malloc (len + 1);
111 if (ds->location == NULL)
112 goto location_failure;
114 strcpy (ds->location, location);
116 ds->genre_names = concord_make_name_table ();
117 if (ds->genre_names == NULL)
125 ds->object_nil = NULL;
126 ds->read_object = &concord_default_read_object;
132 concord_close_ds (CONCORD_DS ds)
134 if (ds->location != NULL)
136 if (ds->genre_names != NULL)
137 concord_destroy_name_table (ds->genre_names);
143 concord_ds_location (CONCORD_DS ds)
149 concord_ds_set_object_failure (CONCORD_DS ds, CONCORD_Object object_nil)
151 ds->object_nil = object_nil;
156 concord_ds_set_read_object_function (CONCORD_DS ds,
157 CONCORD_Object (*read_object)
158 (const unsigned char* str,
161 ds->read_object = read_object;
166 concord_ds_get_genre (CONCORD_DS ds, const char* name)
170 genre = concord_name_table_get (ds->genre_names, name);
174 genre = concord_ds_open_genre (ds, name);
178 if (concord_name_table_put (ds->genre_names, name, genre))
180 concord_close_genre (genre);
187 concord_ds_foreach_genre_name (CONCORD_DS ds,
188 int (*func) (CONCORD_DS ds, char* name))
190 char* dname = ds->location;
194 if ( (dir = opendir (dname)) == NULL)
197 while ( (de = readdir (dir)) != NULL )
199 if ( (strcmp (de->d_name, ".") != 0) &&
200 (strcmp (de->d_name, "..") != 0) )
202 int i, need_to_decode = 0;
207 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
218 name = (char*) alloca (i);
219 cp = (unsigned char*)de->d_name;
220 np = (unsigned char*)name;
222 while ( (ch = *cp++) != '\0')
238 if ( ('0' <= ch) && (ch <= '9') )
239 hex[index++] = ch - '0';
240 else if ( ('A' <= ch) && (ch <= 'F') )
241 hex[index++] = ch - 'A' + 10;
242 else if ( ('a' <= ch) && (ch <= 'f') )
243 hex[index++] = ch - 'a' + 10;
255 *np++ = (hex[0] << 4) | hex[1];
269 return closedir (dir);
272 return closedir (dir);
278 COS_Object_Header header;
281 CONCORD_NAME_TABLE* feature_names;
282 CONCORD_NAME_TABLE* index_names;
286 concord_ds_open_genre (CONCORD_DS ds, const char* name)
289 size_t len = strlen (name);
294 genre = COS_ALLOCATE_OBJECT (Genre);
299 genre->name = (char*)malloc (len + 1);
300 if (genre->name == NULL)
305 strcpy (genre->name, name);
307 genre->feature_names = concord_make_name_table ();
308 if (genre->feature_names == NULL)
315 genre->index_names = concord_make_name_table ();
316 if (genre->index_names == NULL)
318 free (genre->feature_names);
327 concord_close_genre (CONCORD_Genre genre)
334 if (genre->name == NULL)
342 if (genre->feature_names != NULL)
343 concord_destroy_name_table (genre->feature_names);
345 if (genre->index_names != NULL)
346 concord_destroy_name_table (genre->index_names);
353 concord_genre_get_name (CONCORD_Genre genre)
359 concord_genre_get_data_source (CONCORD_Genre genre)
365 concord_genre_foreach_feature_name (CONCORD_Genre genre,
366 int (*func) (CONCORD_Genre genre,
370 = alloca (strlen (genre->ds->location)
371 + 1 + strlen (genre->name) + sizeof ("/feature") + 1);
375 strcpy (dname, genre->ds->location);
377 strcat (dname, genre->name);
378 strcat (dname, "/feature");
380 if ( (dir = opendir (dname)) == NULL)
383 while ( (de = readdir (dir)) != NULL )
385 if ( (strcmp (de->d_name, ".") != 0) &&
386 (strcmp (de->d_name, "..") != 0) )
388 int i, need_to_decode = 0;
393 for (cp = (unsigned char*)de->d_name, i = 0; *cp != '\0'; i++)
404 name = (char*) alloca (i);
405 cp = (unsigned char*)de->d_name;
406 np = (unsigned char*)name;
408 while ( (ch = *cp++) != '\0')
424 if ( ('0' <= ch) && (ch <= '9') )
425 hex[index++] = ch - '0';
426 else if ( ('A' <= ch) && (ch <= 'F') )
427 hex[index++] = ch - 'A' + 10;
428 else if ( ('a' <= ch) && (ch <= 'f') )
429 hex[index++] = ch - 'a' + 10;
441 *np++ = (hex[0] << 4) | hex[1];
454 if (func (genre, name))
455 return closedir (dir);
458 return closedir (dir);
462 concord_genre_get_feature_0 (CONCORD_Genre genre, const char* name)
464 CONCORD_Feature feature;
466 feature = concord_name_table_get (genre->feature_names, name);
470 feature = concord_genre_open_feature (genre, name);
474 if (concord_name_table_put (genre->feature_names, name, feature))
476 concord_close_feature (feature);
483 concord_genre_get_feature (CONCORD_Genre genre, const char* name)
485 CONCORD_Genre g_feature
486 = concord_ds_get_genre (genre->ds, "feature");
488 if (g_feature != NULL)
490 CONCORD_Feature p_true_name
491 = concord_genre_get_feature_0 (g_feature, "true-name");
493 if (g_feature != NULL)
495 CONCORD_String_Tank s_true_name;
497 = concord_obj_get_feature_value_string (name,
502 char* t_name = alloca (s_true_name.size + 1);
504 strncpy (t_name, s_true_name.data, s_true_name.size);
505 t_name[s_true_name.size] = '\0';
506 return concord_genre_get_feature_0 (genre, t_name);
510 return concord_genre_get_feature_0 (genre, name);
514 concord_genre_get_index (CONCORD_Genre genre, const char* name)
518 index = concord_name_table_get (genre->index_names, name);
522 index = concord_genre_open_index (genre, name);
526 if (concord_name_table_put (genre->index_names, name, index))
528 concord_close_index (index);
536 concord_genre_open_feature (CONCORD_Genre genre, const char* feature)
538 CONCORD_Feature table;
539 size_t len = strlen (feature);
544 table = COS_ALLOCATE_OBJECT (Feature);
548 table->genre = genre;
551 table->name = (char*)malloc (len + 1);
552 if (table->name == NULL)
557 strcpy (table->name, feature);
558 table->value_table = NULL;
564 concord_close_feature (CONCORD_Feature feature)
571 if (feature->db == NULL)
574 status = CONCORD_BDB_close (feature->db);
576 if (feature->name == NULL)
580 free (feature->name);
588 concord_feature_get_name (CONCORD_Feature feature)
590 return feature->name;
594 concord_feature_get_genre (CONCORD_Feature feature)
596 return feature->genre;
600 concord_feature_setup_db (CONCORD_Feature feature, int writable)
609 if ((feature->access & DB_CREATE) == 0)
611 if (feature->db != NULL)
613 CONCORD_BDB_close (feature->db);
623 if (feature->db == NULL)
625 CONCORD_Genre genre = feature->genre;
627 if ( concord_opened_feature_list_length
628 >= concord_opened_feature_list_limit )
630 CONCORD_Feature top_feature = concord_opened_feature_list;
632 CONCORD_BDB_close (top_feature->db);
633 top_feature->db = NULL;
634 concord_opened_feature_list = top_feature->next;
635 top_feature->next = NULL;
636 concord_opened_feature_list_length--;
639 = CONCORD_BDB_open (genre->ds->location, genre->name,
640 "feature", feature->name,
642 access, genre->ds->modemask);
643 if (feature->db == NULL)
645 feature->access = access;
646 if ( concord_opened_feature_list == NULL )
648 concord_opened_feature_list = feature;
649 concord_opened_feature_list_last = feature;
653 concord_opened_feature_list_last->next = feature;
654 concord_opened_feature_list_last = feature;
656 concord_opened_feature_list_length++;
662 concord_feature_sync (CONCORD_Feature feature)
666 if (feature->db == NULL)
669 status = CONCORD_BDB_close (feature->db);
676 concord_obj_put_feature_value_str (const char* object_id,
677 CONCORD_Feature feature,
678 unsigned char* value)
682 if (concord_feature_setup_db (feature, 1))
684 return CONCORD_BDB_put (feature->db, object_id, value);
688 concord_obj_get_feature_value_string (const char* object_id,
689 CONCORD_Feature feature,
690 CONCORD_String value)
694 if (concord_feature_setup_db (feature, 0))
696 status = CONCORD_BDB_get (feature->db, object_id, value);
701 concord_obj_get_feature_value (const char* object_id,
702 CONCORD_Feature feature)
707 if (concord_feature_setup_db (feature, 0))
708 return feature->genre->ds->object_nil;
709 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
711 return feature->genre->ds->object_nil;
712 return (*feature->genre->ds->read_object)(valdatum.data, valdatum.size);
716 concord_obj_gets_feature_value (const char* object_id,
717 CONCORD_Feature feature,
718 unsigned char* dst, size_t size)
723 if (concord_feature_setup_db (feature, 0))
725 status = CONCORD_BDB_get (feature->db, object_id, &valdatum);
728 if (size < valdatum.size)
730 strncpy ((char*)dst, valdatum.data, valdatum.size);
731 dst[valdatum.size] = '\0';
736 concord_feature_foreach_obj_string (CONCORD_Feature feature,
737 int (*func)(CONCORD_String object_id,
738 CONCORD_Feature feature,
739 CONCORD_String value))
741 CONCORD_String_Tank key, value;
745 if (concord_feature_setup_db (feature, 0))
750 status = feature->db->cursor (feature->db, NULL, &dbcp, 0);
751 for (status = dbcp->c_get (dbcp, &key, &value, DB_FIRST);
753 status = dbcp->c_get (dbcp, &key, &value, DB_NEXT))
755 int ret = func (&key, feature, &value);
760 dbcp->c_close (dbcp);
766 concord_genre_open_index (CONCORD_Genre genre, const char* index)
769 size_t len = strlen (index);
774 table = COS_ALLOCATE_OBJECT (Feature_INDEX);
778 table->genre = genre;
781 table->name = (char*)malloc (len + 1);
782 if (table->name == NULL)
787 strcpy (table->name, index);
788 table->decoding_table = NULL;
794 concord_close_index (CONCORD_INDEX table)
801 if (table->db == NULL)
804 status = CONCORD_BDB_close (table->db);
806 if (table->name == NULL)
818 concord_index_get_name (CONCORD_INDEX index)
824 concord_index_get_genre (CONCORD_INDEX index)
830 concord_index_setup_db (CONCORD_INDEX index, int writable)
839 if ((index->access & DB_CREATE) == 0)
841 if (index->db != NULL)
843 CONCORD_BDB_close (index->db);
853 if (index->db == NULL)
855 CONCORD_Genre genre = index->genre;
857 if ( concord_opened_index_list_length
858 >= concord_opened_index_list_limit )
860 CONCORD_INDEX top_index = concord_opened_index_list;
862 CONCORD_BDB_close (top_index->db);
863 top_index->db = NULL;
864 concord_opened_index_list = top_index->next;
865 top_index->next = NULL;
866 concord_opened_index_list_length--;
869 = CONCORD_BDB_open (genre->ds->location, genre->name,
870 "index", index->name,
872 access, genre->ds->modemask);
873 if (index->db == NULL)
875 index->access = access;
876 if ( concord_opened_index_list == NULL )
878 concord_opened_index_list = index;
879 concord_opened_index_list_last = index;
883 concord_opened_index_list_last->next = index;
884 concord_opened_index_list_last = index;
886 concord_opened_index_list_length++;
892 concord_index_sync (CONCORD_INDEX index)
896 if (index->db == NULL)
899 status = CONCORD_BDB_close (index->db);
906 concord_index_strid_put_obj (CONCORD_INDEX index,
907 const char* strid, char* object_id)
912 if (concord_index_setup_db (index, 1))
915 return CONCORD_BDB_put (index->db, strid, (unsigned char*)object_id);
919 concord_index_strid_get_obj_string (CONCORD_INDEX index,
921 CONCORD_String object_id)
926 if (concord_index_setup_db (index, 0))
929 return CONCORD_BDB_get (index->db, strid, object_id);