]> arthur.barton.de Git - netatalk.git/commitdiff
Add a configurable hold time option to FCE file modification event generation, defaul...
authorFrank Lahm <franklahm@googlemail.com>
Sat, 13 Aug 2011 20:21:12 +0000 (22:21 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Sat, 13 Aug 2011 20:21:12 +0000 (22:21 +0200)
New option "fceholdfmod" to change it.

NEWS
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/fce_api.c
etc/afpd/fce_api_internal.h
include/atalk/fce_api.h
include/atalk/globals.h

diff --git a/NEWS b/NEWS
index 06d9875af9c8b295f2f5b0b6079976a0bd12d0d2..4a67eca9043294739edb7989e6ffff9360e7113f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Changes in 2.2.1
        The previous behaviour was to enable ACL support for a volume if
        1) it was compiled in and 2) the volume supported ACLs. There was no way
        to disable ACLs for a volume.
        The previous behaviour was to enable ACL support for a volume if
        1) it was compiled in and 2) the volume supported ACLs. There was no way
        to disable ACLs for a volume.
+* UPD: afpd: add a configurable hold time option to FCE file modification event
+       generation, default is 60 s, new option "fceholdfmod" to change it
 * FIX: afpd: increase BerkeleyDB locks and lockobjs
 * FIX: afpd: create special folder as root
 * FIX: afpd: fix compilation error if --enable-ddp is used
 * FIX: afpd: increase BerkeleyDB locks and lockobjs
 * FIX: afpd: create special folder as root
 * FIX: afpd: fix compilation error if --enable-ddp is used
index c59272ff0c7a03b0586deecf02e39f7d0126c14d..295e03df7d8dcbc7b9249f34b726b6724831269b 100644 (file)
@@ -697,7 +697,7 @@ void afp_over_dsi(AFPObj *obj)
         }
         pending_request(dsi);
 
         }
         pending_request(dsi);
 
-        vol_fce_tm_event();
+        fce_pending_events(obj);
     }
 
     /* error */
     }
 
     /* error */
index 028a1efb2c6702d006783b0c20d0a198d41e53f1..b40f61debbeb58ca7a9e6917a8de300291728b85 100644 (file)
@@ -193,6 +193,7 @@ void afp_options_init(struct afp_options *options)
     options->tcp_rcvbuf = 0;    /* 0 means don't change OS default */
     options->dsireadbuf = 12;
        options->mimicmodel = NULL;
     options->tcp_rcvbuf = 0;    /* 0 means don't change OS default */
     options->dsireadbuf = 12;
        options->mimicmodel = NULL;
+    options->fce_fmodwait = 60; /* put fmod events 60 seconds on hold */
 }
 
 /* parse an afpd.conf line. i'm doing it this way because it's
 }
 
 /* parse an afpd.conf line. i'm doing it this way because it's
@@ -502,6 +503,9 @@ int afp_options_parseline(char *buf, struct afp_options *options)
                fce_set_events(c);
        }
 
                fce_set_events(c);
        }
 
+    if ((c = getoption(buf, "-fceholdfmod")))
+        options->fce_fmodwait = atoi(c);
+
     if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
        options->mimicmodel = opt;
 
     if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
        options->mimicmodel = opt;
 
index b2dead294445229bb3984c6018fd22a62744879d..00a04248406cfab1f1e90676fc3d5c93cf8bc75f 100644 (file)
@@ -80,6 +80,7 @@ static const char *skip_files[] =
        ".DS_Store",\r
        NULL\r
 };\r
        ".DS_Store",\r
        NULL\r
 };\r
+static struct fce_close_event last_close_event;\r
 \r
 /*\r
  *\r
 \r
 /*\r
  *\r
@@ -230,13 +231,22 @@ static int pack_fce_packet(struct fce_packet *packet, unsigned char *buf)
  * */\r
 static void send_fce_event( char *path, int mode )\r
 {    \r
  * */\r
 static void send_fce_event( char *path, int mode )\r
 {    \r
+    static int first_event = FCE_TRUE;\r
+\r
     struct fce_packet packet;\r
     void *data = &packet;\r
     static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */\r
     struct fce_packet packet;\r
     void *data = &packet;\r
     static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */\r
+    time_t now = time(NULL);\r
 \r
     LOG(log_debug, logtype_afpd, "send_fce_event: start");\r
 \r
 \r
     LOG(log_debug, logtype_afpd, "send_fce_event: start");\r
 \r
-    time_t now = time(NULL);\r
+    /* initialized ? */\r
+    if (first_event == FCE_TRUE) {\r
+        first_event = FCE_FALSE;\r
+        fce_init_udp();\r
+        /* Notify listeners the we start from the beginning */\r
+        send_fce_event( "", FCE_CONN_START );\r
+    }\r
 \r
     /* build our data packet */\r
     ssize_t data_len = build_fce_packet( &packet, path, mode, ++event_id );\r
 \r
     /* build our data packet */\r
     ssize_t data_len = build_fce_packet( &packet, path, mode, ++event_id );\r
@@ -327,6 +337,23 @@ static int add_udp_socket(const char *target_ip, const char *target_port )
     return AFP_OK;\r
 }\r
 \r
     return AFP_OK;\r
 }\r
 \r
+static void save_close_event(const char *path)\r
+{\r
+    time_t now = time(NULL);\r
+\r
+    /* Check if it's a close for the same event as the last one */\r
+    if (last_close_event.time   /* is there any saved event ? */\r
+        && (strcmp(path, last_close_event.path) != 0)) {\r
+        /* no, so send the saved event out now */\r
+        send_fce_event(last_close_event.path, FCE_FILE_MODIFY);\r
+    }\r
+\r
+    LOG(log_debug, logtype_afpd, "save_close_event: %s", path);\r
+\r
+    last_close_event.time = now;\r
+    strncpy(last_close_event.path, path, MAXPATHLEN);\r
+}\r
+\r
 /*\r
  *\r
  * Dispatcher for all incoming file change events\r
 /*\r
  *\r
  * Dispatcher for all incoming file change events\r
@@ -334,6 +361,8 @@ static int add_udp_socket(const char *target_ip, const char *target_port )
  * */\r
 static int register_fce(const char *u_name, int is_dir, int mode)\r
 {\r
  * */\r
 static int register_fce(const char *u_name, int is_dir, int mode)\r
 {\r
+    static int first_event = FCE_TRUE;\r
+\r
     if (udp_sockets == 0)\r
         /* No listeners configured */\r
         return AFP_OK;\r
     if (udp_sockets == 0)\r
         /* No listeners configured */\r
         return AFP_OK;\r
@@ -341,11 +370,10 @@ static int register_fce(const char *u_name, int is_dir, int mode)
     if (u_name == NULL)\r
         return AFPERR_PARAM;\r
 \r
     if (u_name == NULL)\r
         return AFPERR_PARAM;\r
 \r
-    static int first_event = FCE_TRUE;\r
-\r
        /* do some initialization on the fly the first time */\r
        if (first_event) {\r
                fce_initialize_history();\r
        /* do some initialization on the fly the first time */\r
        if (first_event) {\r
                fce_initialize_history();\r
+        first_event = FCE_FALSE;\r
        }\r
 \r
        /* handle files which should not cause events (.DS_Store atc. ) */\r
        }\r
 \r
        /* handle files which should not cause events (.DS_Store atc. ) */\r
@@ -384,26 +412,29 @@ static int register_fce(const char *u_name, int is_dir, int mode)
 \r
        LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );\r
 \r
 \r
        LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );\r
 \r
-\r
-    /* we do initilization on the fly, no blocking calls in here \r
-     * (except when using FQDN in broken DNS environment)\r
-     */\r
-    if (first_event == FCE_TRUE)\r
-    {\r
-        fce_init_udp();\r
-        \r
-        /* Notify listeners the we start from the beginning */\r
-        send_fce_event( "", FCE_CONN_START );\r
-        \r
-        first_event = FCE_FALSE;\r
+    if (mode & FCE_FILE_MODIFY) {\r
+        save_close_event(full_path_buffer);\r
+        return AFP_OK;\r
     }\r
 \r
     }\r
 \r
-       /* Handle UDP transport */\r
     send_fce_event( full_path_buffer, mode );\r
 \r
     return AFP_OK;\r
 }\r
 \r
     send_fce_event( full_path_buffer, mode );\r
 \r
     return AFP_OK;\r
 }\r
 \r
+static void check_saved_close_events(int fmodwait)\r
+{\r
+    time_t now = time(NULL);\r
+\r
+    /* check if configured holdclose time has passed */\r
+    if (last_close_event.time && ((last_close_event.time + fmodwait) < now)) {\r
+        LOG(log_debug, logtype_afpd, "check_saved_close_events: sending event: %s", last_close_event.path);\r
+        /* yes, send event */\r
+        send_fce_event(&last_close_event.path[0], FCE_FILE_MODIFY);\r
+        last_close_event.path[0] = 0;\r
+        last_close_event.time = 0;\r
+    }\r
+}\r
 \r
 /******************** External calls start here **************************/\r
 \r
 \r
 /******************** External calls start here **************************/\r
 \r
@@ -412,6 +443,12 @@ static int register_fce(const char *u_name, int is_dir, int mode)
  * */\r
 #ifndef FCE_TEST_MAIN\r
 \r
  * */\r
 #ifndef FCE_TEST_MAIN\r
 \r
+void fce_pending_events(AFPObj *obj)\r
+{\r
+    vol_fce_tm_event();\r
+    check_saved_close_events(obj->options.fce_fmodwait);\r
+}\r
+\r
 int fce_register_delete_file( struct path *path )\r
 {\r
     int ret = AFP_OK;\r
 int fce_register_delete_file( struct path *path )\r
 {\r
     int ret = AFP_OK;\r
index a23cfdf8eae76390e4b8b8c633c0346e31d16d64..ef3255e004a6dade81e675509de0fd81a9dbf2b0 100644 (file)
@@ -36,6 +36,11 @@ struct fce_history
        struct timeval tv;\r
 };\r
 \r
        struct timeval tv;\r
 };\r
 \r
+struct fce_close_event {\r
+    time_t time;\r
+       char path[MAXPATHLEN + 1];\r
+};\r
+\r
 #define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN)\r
 \r
 int fce_handle_coalescation( char *path, int is_dir, int mode );\r
 #define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN)\r
 \r
 int fce_handle_coalescation( char *path, int is_dir, int mode );\r
index b6111e4c6c660f889cccad484dd07270cc510a56..9175afe90be69dffbc8bffd14e721762c45031a0 100755 (executable)
@@ -10,6 +10,8 @@
 #ifndef _FCE_API_H
 #define        _FCE_API_H
 
 #ifndef _FCE_API_H
 #define        _FCE_API_H
 
+#include <atalk/globals.h>
+
 /* fce_packet.mode */
 #define FCE_FILE_MODIFY     1
 #define FCE_FILE_DELETE     2
 /* fce_packet.mode */
 #define FCE_FILE_MODIFY     1
 #define FCE_FILE_DELETE     2
@@ -42,6 +44,8 @@ struct fce_packet
 struct path;
 struct ofork;
 
 struct path;
 struct ofork;
 
+void fce_pending_events(AFPObj *obj);
+
 int fce_register_delete_file( struct path *path );
 int fce_register_delete_dir( char *name );
 int fce_register_new_dir( struct path *path );
 int fce_register_delete_file( struct path *path );
 int fce_register_delete_dir( char *name );
 int fce_register_new_dir( struct path *path );
index 14dab835dcc8195787db677de188b13174de6b2d..299a5bf5d99748c69ac299a1aed3fa3c91c001f2 100644 (file)
@@ -66,6 +66,7 @@ struct afp_options {
     int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
     int sleep;                  /* Maximum time allowed to sleep (in tickles) */
     int disconnected;           /* Maximum time in disconnected state (in tickles) */
     int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
     int sleep;                  /* Maximum time allowed to sleep (in tickles) */
     int disconnected;           /* Maximum time in disconnected state (in tickles) */
+    int fce_fmodwait;           /* number of seconds FCE file mod events are put on hold */
     unsigned int tcp_sndbuf, tcp_rcvbuf;
     unsigned char passwdbits, passwdminlen, loginmaxfail;
     u_int32_t server_quantum;
     unsigned int tcp_sndbuf, tcp_rcvbuf;
     unsigned char passwdbits, passwdminlen, loginmaxfail;
     u_int32_t server_quantum;