You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2018/05/16 20:14:05 UTC

[07/12] qpid-dispatch git commit: DISPATCH-990: Reject add of vhost that has pattern conflict.

DISPATCH-990: Reject add of vhost that has pattern conflict.

Add self test showing how conflicts are managed.


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/9c0a09d7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/9c0a09d7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/9c0a09d7

Branch: refs/heads/master
Commit: 9c0a09d793795acbc165df37a45f8fa86329da0f
Parents: f17631c
Author: Chuck Rolke <cr...@redhat.com>
Authored: Mon May 14 12:31:13 2018 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Mon May 14 12:31:13 2018 -0400

----------------------------------------------------------------------
 python/qpid_dispatch_internal/dispatch.py       |  2 +-
 .../policy/policy_local.py                      | 12 ++--
 src/dispatch.c                                  |  4 +-
 src/policy.c                                    | 14 +++-
 src/policy.h                                    |  8 ++-
 tests/parse_tree_tests.c                        | 67 ++++++++++++++++++++
 6 files changed, 93 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/python/qpid_dispatch_internal/dispatch.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/dispatch.py b/python/qpid_dispatch_internal/dispatch.py
index 609396e..c819122 100644
--- a/python/qpid_dispatch_internal/dispatch.py
+++ b/python/qpid_dispatch_internal/dispatch.py
@@ -78,7 +78,7 @@ class QdDll(ctypes.PyDLL):
         self._prototype(self.qd_dispatch_policy_c_counts_alloc, c_long, [], check=False)
         self._prototype(self.qd_dispatch_policy_c_counts_free, None, [c_long], check=False)
         self._prototype(self.qd_dispatch_policy_c_counts_refresh, None, [c_long, py_object])
-        self._prototype(self.qd_dispatch_policy_host_pattern_add, None, [self.qd_dispatch_p, c_char_p])
+        self._prototype(self.qd_dispatch_policy_host_pattern_add, ctypes.c_bool, [self.qd_dispatch_p, c_char_p])
         self._prototype(self.qd_dispatch_policy_host_pattern_remove, None, [self.qd_dispatch_p, c_char_p])
         self._prototype(self.qd_dispatch_policy_host_pattern_lookup, c_char_p, [self.qd_dispatch_p, c_char_p])
         

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py b/python/qpid_dispatch_internal/policy/policy_local.py
index ce47e21..6f8dbb3 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -531,6 +531,11 @@ class PolicyLocal(object):
         if len(warnings) > 0:
             for warning in warnings:
                 self._manager.log_warning(warning)
+        # Reject if parse tree optimized name collision
+        if self.use_hostname_patterns:
+            agent = self._manager.get_agent()
+            if not agent.qd.qd_dispatch_policy_host_pattern_add(agent.dispatch, name):
+                raise PolicyError("Policy '%s' optimized pattern conflicts with existing pattern" % name)
         if name not in self.rulesetdb:
             if name not in self.statsdb:
                 self.statsdb[name] = AppStats(name, self._manager, candidate)
@@ -539,13 +544,6 @@ class PolicyLocal(object):
             self.statsdb[name].update_ruleset(candidate)
             self._manager.log_info("Updated policy rules for vhost %s" % name)
         # TODO: ruleset lock
-        if self.use_hostname_patterns:
-            agent = self._manager.get_agent()
-            if name in self.rulesetdb:
-                # an update. remove existing hostname pattern
-                agent.qd.qd_dispatch_policy_host_pattern_remove(agent.dispatch, name)
-            # add new pattern
-            agent.qd.qd_dispatch_policy_host_pattern_add(agent.dispatch, name)
         self.rulesetdb[name] = {}
         self.rulesetdb[name].update(candidate)
 

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/src/dispatch.c
----------------------------------------------------------------------
diff --git a/src/dispatch.c b/src/dispatch.c
index 6f82471..3c2629a 100644
--- a/src/dispatch.c
+++ b/src/dispatch.c
@@ -270,9 +270,9 @@ void qd_dispatch_policy_c_counts_refresh(long ccounts, qd_entity_t *entity)
     qd_policy_c_counts_refresh(ccounts, entity);
 }
 
-void qd_dispatch_policy_host_pattern_add(qd_dispatch_t *qd, char *hostPattern)
+bool qd_dispatch_policy_host_pattern_add(qd_dispatch_t *qd, char *hostPattern)
 {
-    qd_policy_host_pattern_add(qd->policy, hostPattern);
+    return qd_policy_host_pattern_add(qd->policy, hostPattern);
 }
 
 void qd_dispatch_policy_host_pattern_remove(qd_dispatch_t *qd, char *hostPattern)

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/src/policy.c
----------------------------------------------------------------------
diff --git a/src/policy.c b/src/policy.c
index 77523ce..dec645e 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -834,14 +834,22 @@ bool qd_policy_approve_link_name(const char *username,
 
 
 // Add a hostname to the lookup parse_tree
-void qd_policy_host_pattern_add(qd_policy_t *policy, char *hostPattern)
+bool qd_policy_host_pattern_add(qd_policy_t *policy, char *hostPattern)
 {
     sys_mutex_lock(policy->tree_lock);
     void *oldp = qd_parse_tree_add_pattern_str(policy->hostname_tree, hostPattern, hostPattern);
     sys_mutex_unlock(policy->tree_lock);
     if (oldp) {
-        qd_log(policy->log_source, QD_LOG_INFO, "vhost hostname pattern '%s' replaced existing pattern", hostPattern);
+        qd_log(policy->log_source,
+               QD_LOG_WARNING,
+               "vhost hostname pattern '%s' failed to replace optimized pattern '%s'",
+               hostPattern, oldp);
+        sys_mutex_lock(policy->tree_lock);
+        void *recovered = qd_parse_tree_add_pattern_str(policy->hostname_tree, (char *)oldp, oldp);
+        sys_mutex_unlock(policy->tree_lock);
+        assert (recovered && !strcmp((char *)recovered, hostPattern));
     }
+    return oldp == 0;
 }
 
 
@@ -852,7 +860,7 @@ void qd_policy_host_pattern_remove(qd_policy_t *policy, char *hostPattern)
     void *oldp = qd_parse_tree_remove_pattern_str(policy->hostname_tree, hostPattern);
     sys_mutex_unlock(policy->tree_lock);
     if (!oldp) {
-        qd_log(policy->log_source, QD_LOG_INFO, "vhost hostname pattern '%s' for removal not found", hostPattern);
+        qd_log(policy->log_source, QD_LOG_WARNING, "vhost hostname pattern '%s' for removal not found", hostPattern);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/src/policy.h
----------------------------------------------------------------------
diff --git a/src/policy.h b/src/policy.h
index 57a64fe..98500ec 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -179,10 +179,16 @@ bool qd_policy_approve_link_name(const char *username,
                                 );
 
 /** Add a hostname to the lookup parse_tree
+ * Note that the parse_tree may store an 'optimised' pattern for a given
+ * pattern. Thus the patterns a user puts in may collide with existing
+ * patterns even though the text of the host patterns is different.
+ * This function does not allow new patterns with thier optimizations 
+ * to overwrite existing patterns that may have been optimised.
  * @param[in] policy qd_policy_t
  * @param[in] hostPattern the hostname pattern with possible parse_tree wildcards
+ * @return True if the possibly optimised pattern was added to the lookup parse tree
  */
-void qd_policy_host_pattern_add(qd_policy_t *policy, char *hostPattern);
+bool qd_policy_host_pattern_add(qd_policy_t *policy, char *hostPattern);
 
 /** Remove a hostname from the lookup parse_tree
  * @param[in] policy qd_policy_t

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/9c0a09d7/tests/parse_tree_tests.c
----------------------------------------------------------------------
diff --git a/tests/parse_tree_tests.c b/tests/parse_tree_tests.c
index 5800b4a..1dba5ba 100644
--- a/tests/parse_tree_tests.c
+++ b/tests/parse_tree_tests.c
@@ -98,6 +98,72 @@ static char *test_add_and_match_str(void *context)
     return NULL;
 }
 
+static char *test_usurpation_recovery_str(void *context)
+{
+    const char *A = "#";
+    const char *B = "#.#.#.#";
+    qd_parse_tree_t *node = qd_parse_tree_new(QD_PARSE_TREE_ADDRESS);
+    void *payload;
+    void *usurped;
+    void *deposed;
+
+    // rightful owner is ensconsced
+    if (qd_parse_tree_add_pattern_str(node, A, (void *)A))
+        return "Add returned existing value (1)";
+
+    // matches on A or B both return A
+    if (!qd_parse_tree_retrieve_match_str(node, A, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(A, (char *)payload))
+        return "Got bad pattern";
+
+    if (!qd_parse_tree_retrieve_match_str(node, B, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(A, (char *)payload))
+        return "Got bad pattern";
+
+    // usurper comes along
+    usurped = qd_parse_tree_add_pattern_str(node, B, (void *)B);
+    if (!usurped || strcmp(A, (char *)usurped))
+        return "Usurper should have grabbed '#' optimized match";
+
+    // matches on A or B both return B
+    if (!qd_parse_tree_retrieve_match_str(node, A, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(B, (char *)payload))
+        return "Got bad pattern";
+
+    if (!qd_parse_tree_retrieve_match_str(node, B, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(B, (char *)payload))
+        return "Got bad pattern";
+
+    // Restore rightful owner
+    deposed = qd_parse_tree_add_pattern_str(node, usurped, usurped);
+    if (!deposed || strcmp(B, (char *)deposed))
+        return "Failed to depose B";
+
+    // matches on A or B both return A
+    if (!qd_parse_tree_retrieve_match_str(node, A, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(A, (char *)payload))
+        return "Got bad pattern";
+
+    if (!qd_parse_tree_retrieve_match_str(node, B, &payload))
+        return "Could not get pattern";
+
+    if (!payload || strcmp(A, (char *)payload))
+        return "Got bad pattern";
+
+    qd_parse_tree_free(node);
+    return NULL;
+}
+
 // for pattern match callback
 typedef struct {
     int count;
@@ -633,6 +699,7 @@ int parse_tree_tests(void)
 
     TEST_CASE(test_add_remove, 0);
     TEST_CASE(test_add_and_match_str, 0);
+    TEST_CASE(test_usurpation_recovery_str, 0);
     TEST_CASE(test_normalization, 0);
     TEST_CASE(test_matches, 0);
     TEST_CASE(test_multiple_matches, 0);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org