MERGE command
authorChristian Thaeter <ct@pipapo.org>
Sat, 27 Oct 2007 02:30:01 +0000 (04:30 +0200)
committerChristian Thaeter <ct@pipapo.org>
Sat, 27 Oct 2007 02:30:01 +0000 (04:30 +0200)
src/rxpd.h
src/rxpd_connection_cmd.c
tests/20simplecommands.tests
tests/50listsyncronization.tests

index f26d346..745c40b 100644 (file)
@@ -53,6 +53,7 @@
   RXPD_CMD(SAVE,        "a list to disk")                       \
   RXPD_CMD(FETCH,       "a list from a remote server")          \
   RXPD_CMD(UPDATE,      "atimes from other lists")              \
+  RXPD_CMD(MERGE,       "new rules from from other lists")      \
   RXPD_CMD(EXPIRE,      "aged rules from a list")               \
   RXPD_CMD(DUMP,        "rules in a list")                      \
   RXPD_CMD(LIST,        "all existing lists")                   \
index 50e591d..7e8a418 100644 (file)
@@ -552,6 +552,79 @@ rxpd_connection_cmd_UPDATE (struct rxpd_connection* self)
   rxpd_buffer_printf (&self->out, "#OK:\n");
 }
 
+
+void
+rxpd_connection_cmd_MERGE (struct rxpd_connection* self)
+{
+  RXPD_FILENAME_REQUIRED;
+
+  struct rxpd_base* base = self->socket->base;
+
+  pth_rwlock_acquire (&self->file->lock, PTH_RWLOCK_RW, FALSE, NULL);
+
+  char* line;
+  while ((line = rxpd_buffer_readline (&self->in)))
+    {
+      /* for each line which is a listname */
+      struct rxpd_file* source;
+      source = (struct rxpd_file*) psplay_find (&base->files, line);
+      if (source)
+        {
+          pth_rwlock_acquire (&source->lock, PTH_RWLOCK_RD, FALSE, NULL);
+
+          LList source_start = llist_head (&source->rules);
+          LList file_start = llist_head (&self->file->rules);
+          LList source_itr = NULL;
+          LList file_itr = NULL;
+
+          /* find next line which is in source and self->file */
+          while (source_itr != &source->rules)
+            {
+              LLIST_FORRANGE (source_start, &source->rules, n)
+                {
+                  LLIST_FORRANGE (file_start, &self->file->rules, m)
+                    {
+                      struct rxpd_rule* rule_n = (struct rxpd_rule*)n;
+                      struct rxpd_rule* rule_m = (struct rxpd_rule*)m;
+                      if (strcmp (rule_n->string, rule_m->string) == 0)
+                        {
+                          source_itr = &rule_n->node;
+                          file_itr = &rule_m->node;
+                          goto leave_loop;
+                        }
+                    }
+                }
+              /* not found, place the itr's at the end of their lists */
+              source_itr = &source->rules;
+              file_itr = &self->file->rules;
+            leave_loop:
+              /* copy all rules from source_start to source_itr before file_itr */
+
+              LLIST_FORRANGE (source_start, source_itr, n)
+                {
+                  struct rxpd_rule* rule = rxpd_rule_copy ((struct rxpd_rule*)n);
+                  if (!rule)
+                    rxpd_die ("rule copy failed\n");
+
+                  llist_insert_prev (file_itr, &rule->node);
+                }
+
+              /*iterate for mismatch*/
+              file_start = llist_next (file_itr);
+              source_start = llist_next (source_itr);
+            }
+
+          pth_rwlock_release (&source->lock);
+        }
+      else
+        rxpd_buffer_printf (&self->out, "#ERROR: unknown file '%s'\n", line);
+    }
+
+  pth_rwlock_release (&self->file->lock);
+
+  rxpd_buffer_printf (&self->out, "#OK:\n");
+}
+
 /* Template
 void
 rxpd_connection_cmd_ (struct rxpd_connection* self)
index 2bbacea..28602d8 100644 (file)
@@ -44,6 +44,7 @@ out: # LOAD a list from disk.
 out: # SAVE a list to disk.
 out: # FETCH a list from a remote server.
 out: # UPDATE atimes from other lists.
+out: # MERGE new rules from from other lists.
 out: # EXPIRE aged rules from a list.
 out: # DUMP rules in a list.
 out: # LIST all existing lists.
@@ -52,6 +53,7 @@ out: # HELP is what you see right now.
 out: # SHUTDOWN the daemon.
 out: #
 out: # general syntax is: 'COMMAND:listname\n..data..'
+out: # see http://www.pipapo.org/pipawiki/RegexPolicyDaemon
 END
 
 
index 9bb221e..2537530 100644 (file)
@@ -67,3 +67,117 @@ in: CHECK:example
 in: MirBSD
 out: accept:MirBSD
 END
+
+
+TEST "merge, setup source" <<END
+in: APPEND:source
+in: # line 1
+in: # line 2
+END
+
+TEST "merge, to new list" <<END
+in: MERGE:dest
+in: source
+out: #OK:
+END
+
+TEST "merge, check new list" <<END
+in: DUMP:dest
+out: # line 1
+out: # line 2
+END
+
+
+TEST "merge, setup lines at end" <<END
+in: APPEND:source
+in: # line 3
+in: # line 4
+END
+
+TEST "merge, lines at end" <<END
+in: MERGE:dest
+in: source
+out: #OK:
+END
+
+TEST "merge, check lines at end" <<END
+in: DUMP:dest
+out: # line 1
+out: # line 2
+out: # line 3
+out: # line 4
+END
+
+
+TEST "merge, setup lines at begin" <<END
+in: PREPEND:source
+in: # line -1
+in: # line 0
+END
+
+TEST "merge, lines at begin" <<END
+in: MERGE:dest
+in: source
+out: #OK:
+END
+
+TEST "merge, check lines at begin" <<END
+in: DUMP:dest
+out: # line -1
+out: # line 0
+out: # line 1
+out: # line 2
+out: # line 3
+out: # line 4
+END
+
+
+TEST "merge, setup remove lines" <<END
+in: REMOVE:source
+in: # line 0
+in: # line 1
+END
+
+TEST "merge, remove lines" <<END
+in: MERGE:dest
+in: source
+out: #OK:
+END
+
+# merge is add only and shall not delete anything
+TEST "merge, check remove lines" <<END
+in: DUMP:dest
+out: # line -1
+out: # line 0
+out: # line 1
+out: # line 2
+out: # line 3
+out: # line 4
+END
+
+
+TEST "merge, setup replace lines" <<END
+in: REPLACE:source
+in: # line 2
+in: # line -1.1
+in: # line 2
+in: # line 0.1
+END
+
+TEST "merge, replace lines" <<END
+in: MERGE:dest
+in: source
+out: #OK:
+END
+
+TEST "merge, check remove lines" <<END
+in: DUMP:dest
+out: # line -1
+out: # line 0
+out: # line 1
+out: # line -1.1
+out: # line 2
+out: # line 0.1
+out: # line 3
+out: # line 4
+END