summaryrefslogtreecommitdiffstats
path: root/common/collection/collection.c
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-07-15 17:28:54 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-07-16 17:29:13 -0400
commit5258186325dd9c566e68ef3217202d4ecf78b30e (patch)
tree63b39cfbaa94f289cb934a62b4f3ad22e3cb2224 /common/collection/collection.c
parentccff2c2124b9ff085fb8473610a35daf1ab875cd (diff)
downloadsssd-5258186325dd9c566e68ef3217202d4ecf78b30e.tar.gz
sssd-5258186325dd9c566e68ef3217202d4ecf78b30e.tar.xz
sssd-5258186325dd9c566e68ef3217202d4ecf78b30e.zip
COLLECTION Improving searches
Addressing ticket #71. The searches were not taking advantage of the hashes, now they are.
Diffstat (limited to 'common/collection/collection.c')
-rw-r--r--common/collection/collection.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/common/collection/collection.c b/common/collection/collection.c
index 113d9f037..31b47a052 100644
--- a/common/collection/collection.c
+++ b/common/collection/collection.c
@@ -140,7 +140,7 @@ static int col_validate_property(const char *property)
check = property;
while (*check != '\0') {
- if ((!isalnum(*check)) && (!ispunct(*check))) {
+ if (((!isalnum(*check)) && (!ispunct(*check))) || (*check == '.')) {
invalid = 1;
break;
}
@@ -227,7 +227,7 @@ static int col_allocate_item(struct collection_item **ci, const char *property,
item->property_len = 0;
while (property[item->property_len] != 0) {
- item->phash = item->phash ^ property[item->property_len];
+ item->phash = item->phash ^ toupper(property[item->property_len]);
item->phash *= FNV1a_prime;
item->property_len++;
}
@@ -301,7 +301,7 @@ static int col_find_property(struct collection_item *collection,
/* Create hash of the string to search */
while(refprop[i] != 0) {
- ps.hash = ps.hash ^ refprop[i];
+ ps.hash = ps.hash ^ toupper(refprop[i]);
ps.hash *= FNV1a_prime;
i++;
}
@@ -1125,6 +1125,7 @@ struct path_data {
struct find_name {
const char *name_to_find;
int name_len_to_find;
+ uint64_t hash;
int type_to_match;
char *given_name;
int given_len;
@@ -1197,6 +1198,7 @@ static int col_match_item(struct collection_item *current,
TRACE_FLOW_STRING("col_match_item", "Entry");
if (traverse_data->type_to_match & current->type) {
+
/* Check if there is any value to match */
if ((traverse_data->name_to_find == NULL) ||
(*(traverse_data->name_to_find) == '\0')) {
@@ -1205,6 +1207,14 @@ static int col_match_item(struct collection_item *current,
return COL_MATCH;
}
+ /* Check the hashes - if they do not match return */
+ if (traverse_data->hash != current->phash) {
+ TRACE_INFO_STRING("col_match_item","Returning NO match!");
+ return COL_NOMATCH;
+ }
+
+ /* We will do the actual string comparison only if the hashes matched */
+
/* Start comparing the two strings from the end */
find_str = traverse_data->name_to_find + traverse_data->name_len_to_find;
start = current->property;
@@ -1463,6 +1473,9 @@ static int col_find_item_and_do(struct collection_item *ci,
int error = EOK;
struct find_name *traverse_data = NULL;
unsigned depth = 0;
+ int count = 0;
+ const char *last_part;
+ char *dot;
TRACE_FLOW_STRING("col_find_item_and_do", "Entry.");
@@ -1483,7 +1496,7 @@ static int col_find_item_and_do(struct collection_item *ci,
}
/* Prepare data for traversal */
errno = 0;
- traverse_data= (struct find_name *)malloc(sizeof(struct find_name));
+ traverse_data = (struct find_name *)malloc(sizeof(struct find_name));
if (traverse_data == NULL) {
error = errno;
TRACE_ERROR_NUMBER("Failed to allocate traverse data memory - returning error!", errno);
@@ -1493,7 +1506,45 @@ static int col_find_item_and_do(struct collection_item *ci,
TRACE_INFO_STRING("col_find_item_and_do", "Filling in traverse data.");
traverse_data->name_to_find = property_to_find;
- traverse_data->name_len_to_find = strlen(property_to_find);
+
+ if (property_to_find != NULL) {
+
+ traverse_data->name_len_to_find = strlen(property_to_find);
+
+ /* Check if the search string ends with dot - this is ellegal */
+ if (traverse_data->name_to_find[traverse_data->name_len_to_find - 1] == '.') {
+ TRACE_ERROR_NUMBER("Search string is invalid.", EINVAL);
+ free(traverse_data);
+ return EINVAL;
+ }
+
+ /* Find last dot if any */
+ dot = strrchr(traverse_data->name_to_find, '.');
+ if (dot != NULL) {
+ dot++;
+ last_part = dot;
+ }
+ else last_part = traverse_data->name_to_find;
+
+ TRACE_INFO_STRING("Last item", last_part);
+
+ /* Create hash of the last part */
+ traverse_data->hash = FNV1a_base;
+
+ /* Create hash of the string to search */
+ while(last_part[count] != 0) {
+ traverse_data->hash = traverse_data->hash ^ toupper(last_part[count]);
+ traverse_data->hash *= FNV1a_prime;
+ count++;
+ }
+ }
+ else {
+ /* We a looking for a first element of a given type */
+ TRACE_INFO_STRING("No search string", "");
+ traverse_data->name_len_to_find = 0;
+ }
+
+
traverse_data->type_to_match = type;
traverse_data->given_name = NULL;
traverse_data->given_len = 0;