SYNC command
authorChristian Thaeter <ct@pipapo.org>
Thu, 25 Oct 2007 19:52:24 +0000 (21:52 +0200)
committerChristian Thaeter <ct@pipapo.org>
Thu, 25 Oct 2007 19:52:24 +0000 (21:52 +0200)
src/rxpd.h
src/rxpd_connection_cmd.c

index 64bb1c2..2acf2b7 100644 (file)
@@ -52,6 +52,7 @@
   RXPD_CMD(LOAD,        "a list from disk")                     \
   RXPD_CMD(SAVE,        "a list to disk")                       \
   RXPD_CMD(FETCH,       "a list from a remote server")          \
+  RXPD_CMD(SYNC,        "atimes 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 becc429..ce38ad0 100644 (file)
@@ -223,7 +223,6 @@ rxpd_connection_cmd_REPLACE (struct rxpd_connection* self)
     rxpd_buffer_printf (&self->out, "#OK:\n");
   else
     rxpd_buffer_printf (&self->out, "#ERROR: no rule matching '%s'\n", self->tmp_str);
-
 }
 
 void
@@ -461,11 +460,102 @@ rxpd_connection_cmd_EXPIRE (struct rxpd_connection* self)
     rxpd_buffer_printf (&self->out, "#ERROR: no age given\n");
 }
 
+void
+rxpd_connection_cmd_SYNC (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);
+
+          /* find first line which is in source and self->file, this is our start */
+          LList source_itr = NULL;
+          LList file_itr = NULL;
+          LLIST_FOREACH (&source->rules, n)
+            {
+              struct rxpd_rule* rule_n = (struct rxpd_rule*)n;
+              LLIST_FOREACH (&self->file->rules, m)
+                {
+                  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;
+                      rxpd_log (base, LOG_DEBUG, "starting at '%s'\n", rule_n->string);
+                      goto leave_loop;
+                    }
+                }
+            }
+        leave_loop:
+          if (!source_itr)
+            {
+              rxpd_log (base, LOG_DEBUG, "no common line found between '%s' and '%s'\n",
+                        (const char*)self->file->node.key, line);
+              pth_rwlock_release (&source->lock);
+              break;
+            }
+
+          /* Now we go for each rule in source which has a atime find the matching rule in self->file and update its atime */
+          /* This algorihm assumes that lists stay ordered (insertions/deletions are supported, but not reordering) */
+          /* advantage is that the cost is O(N+M) instead O(N*M) */
+          LLIST_FORRANGE (source_itr, &source->rules, n)
+            {
+              struct rxpd_rule* rule_n = (struct rxpd_rule*)n;
+              if (rule_n->atime != (time_t)-1)
+                {
+                  LLIST_FORRANGE (file_itr, &self->file->rules, m)
+                    {
+                      struct rxpd_rule* rule_m = (struct rxpd_rule*)m;
+                      if (strcmp (rule_n->string, rule_m->string) == 0)
+                        {
+                          /* found the rule */
+                          if (rule_m->atime != (time_t)-1 && rule_m->atime < rule_n->atime)
+                            {
+                              rxpd_log (base, LOG_DEBUG,
+                                        "updating atime of rule '%s' from %ld to %ld\n",
+                                        rule_m->string,
+                                        rule_m->atime,
+                                        rule_n->atime
+                                        );
+                              rule_m->atime = rule_n->atime;
+                            }
+
+                          file_itr = llist_next (m);
+                          break;
+                        }
+                    }
+                }
+            }
+
+          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)
 {
-  struct rxpd_base* base = self->socket->base;
-  rxpd_die ("Unimplemented\n");
+  RXPD_FILENAME_REQUIRED;
+  //struct rxpd_base* base = self->socket->base;
+  rxpd_buffer_printf (&self->out, "#ERROR: Unimplemented\n");
 }
 */