Changeset 14651


Ignore:
Timestamp:
Jan 2, 2016, 2:28:59 PM (5 years ago)
Author:
mikedld
Message:

#5663: Rework directory watching in daemon

Implement BSD/Darwin (kqueue) and Windows (ReadDirectoryChanges?) mechanisms
for receiving directory change notifications. Use events instead of polling
for changes. Retry file parsing up to 3 times before giving up.

Huge thanks to missionsix for preparing first two versions of the patch.

Location:
trunk
Files:
8 added
2 deleted
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Transmission.xcodeproj/project.pbxproj

    r14630 r14651  
    294294                A2D307A40D9EC6870051FD27 /* BlocklistDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = A2D307A30D9EC6870051FD27 /* BlocklistDownloader.m */; };
    295295                A2D307B10D9EC9F50051FD27 /* BlocklistStatusWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2D307B00D9EC9F50051FD27 /* BlocklistStatusWindow.xib */; };
    296                 A2D5972A0F5AE49E0001AB3C /* watch.c in Sources */ = {isa = PBXBuildFile; fileRef = A2D597280F5AE49E0001AB3C /* watch.c */; };
    297296                A2D77451154CC25700A62B93 /* WebSeedTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D7744F154CC25700A62B93 /* WebSeedTableView.h */; };
    298297                A2D77452154CC25700A62B93 /* WebSeedTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = A2D77450154CC25700A62B93 /* WebSeedTableView.m */; };
     
    474473                C1639A7D1A55F57200E42033 /* cencode.h in Headers */ = {isa = PBXBuildFile; fileRef = C1639A7B1A55F57200E42033 /* cencode.h */; };
    475474                C1F690FD1AD0627500D95CF0 /* daemon-posix.c in Sources */ = {isa = PBXBuildFile; fileRef = C1F690FC1AD0627500D95CF0 /* daemon-posix.c */; };
     475                C1FEE5771C3223CC00D62832 /* watchdir-common.h in Headers */ = {isa = PBXBuildFile; fileRef = C1FEE5721C3223CC00D62832 /* watchdir-common.h */; };
     476                C1FEE5781C3223CC00D62832 /* watchdir-generic.c in Sources */ = {isa = PBXBuildFile; fileRef = C1FEE5731C3223CC00D62832 /* watchdir-generic.c */; };
     477                C1FEE5791C3223CC00D62832 /* watchdir-kqueue.c in Sources */ = {isa = PBXBuildFile; fileRef = C1FEE5741C3223CC00D62832 /* watchdir-kqueue.c */; };
     478                C1FEE57A1C3223CC00D62832 /* watchdir.c in Sources */ = {isa = PBXBuildFile; fileRef = C1FEE5751C3223CC00D62832 /* watchdir.c */; };
     479                C1FEE57B1C3223CC00D62832 /* watchdir.h in Headers */ = {isa = PBXBuildFile; fileRef = C1FEE5761C3223CC00D62832 /* watchdir.h */; };
    476480                D4AF3B2F0C41F7A500D46B6B /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4AF3B2D0C41F7A500D46B6B /* list.c */; };
    477481                D4AF3B300C41F7A600D46B6B /* list.h in Headers */ = {isa = PBXBuildFile; fileRef = D4AF3B2E0C41F7A500D46B6B /* list.h */; };
     
    10351039                A2D307A30D9EC6870051FD27 /* BlocklistDownloader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BlocklistDownloader.m; path = macosx/BlocklistDownloader.m; sourceTree = "<group>"; };
    10361040                A2D307B00D9EC9F50051FD27 /* BlocklistStatusWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = BlocklistStatusWindow.xib; path = macosx/BlocklistStatusWindow.xib; sourceTree = "<group>"; };
    1037                 A2D597280F5AE49E0001AB3C /* watch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = watch.c; path = daemon/watch.c; sourceTree = "<group>"; };
    1038                 A2D597290F5AE49E0001AB3C /* watch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = watch.h; path = daemon/watch.h; sourceTree = "<group>"; };
    10391041                A2D7744F154CC25700A62B93 /* WebSeedTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebSeedTableView.h; path = macosx/WebSeedTableView.h; sourceTree = "<group>"; };
    10401042                A2D77450154CC25700A62B93 /* WebSeedTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WebSeedTableView.m; path = macosx/WebSeedTableView.m; sourceTree = "<group>"; };
     
    12311233                C1F690FC1AD0627500D95CF0 /* daemon-posix.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "daemon-posix.c"; path = "daemon/daemon-posix.c"; sourceTree = "<group>"; };
    12321234                C1F690FE1AD0628400D95CF0 /* daemon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = daemon.h; path = daemon/daemon.h; sourceTree = "<group>"; };
     1235                C1FEE5721C3223CC00D62832 /* watchdir-common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "watchdir-common.h"; path = "libtransmission/watchdir-common.h"; sourceTree = "<group>"; };
     1236                C1FEE5731C3223CC00D62832 /* watchdir-generic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "watchdir-generic.c"; path = "libtransmission/watchdir-generic.c"; sourceTree = "<group>"; };
     1237                C1FEE5741C3223CC00D62832 /* watchdir-kqueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "watchdir-kqueue.c"; path = "libtransmission/watchdir-kqueue.c"; sourceTree = "<group>"; };
     1238                C1FEE5751C3223CC00D62832 /* watchdir.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = watchdir.c; path = libtransmission/watchdir.c; sourceTree = "<group>"; };
     1239                C1FEE5761C3223CC00D62832 /* watchdir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = watchdir.h; path = libtransmission/watchdir.h; sourceTree = "<group>"; };
    12331240                D4AF3B2D0C41F7A500D46B6B /* list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = list.c; path = libtransmission/list.c; sourceTree = "<group>"; };
    12341241                D4AF3B2E0C41F7A500D46B6B /* list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = list.h; path = libtransmission/list.h; sourceTree = "<group>"; };
     
    18111818                                A2A4EA0A0DE106E8000CE197 /* ConvertUTF.c */,
    18121819                                4DB74F070E8CD75100AEB1A8 /* wildmat.c */,
     1820                                C1FEE5751C3223CC00D62832 /* watchdir.c */,
     1821                                C1FEE5761C3223CC00D62832 /* watchdir.h */,
     1822                                C1FEE5731C3223CC00D62832 /* watchdir-generic.c */,
     1823                                C1FEE5741C3223CC00D62832 /* watchdir-kqueue.c */,
     1824                                C1FEE5721C3223CC00D62832 /* watchdir-common.h */,
    18131825                        );
    18141826                        name = libtransmission;
     
    20132025                                C1F690FC1AD0627500D95CF0 /* daemon-posix.c */,
    20142026                                BEFC1C140C07756200B0BB3C /* remote.c */,
    2015                                 A2D597280F5AE49E0001AB3C /* watch.c */,
    2016                                 A2D597290F5AE49E0001AB3C /* watch.h */,
    20172027                        );
    20182028                        name = daemon;
     
    21232133                                BEFC1E490C07861A00B0BB3C /* metainfo.h in Headers */,
    21242134                                BEFC1E4D0C07861A00B0BB3C /* session.h in Headers */,
     2135                                C1FEE5771C3223CC00D62832 /* watchdir-common.h in Headers */,
    21252136                                BEFC1E4E0C07861A00B0BB3C /* inout.h in Headers */,
    21262137                                BEFC1E520C07861A00B0BB3C /* fdlimit.h in Headers */,
     
    21412152                                A29DF8BB0DB2544C00D04E5A /* torrent.h in Headers */,
    21422153                                A29DF8BE0DB2545F00D04E5A /* verify.h in Headers */,
     2154                                C1FEE57B1C3223CC00D62832 /* watchdir.h in Headers */,
    21432155                                A2AAB6650DE0D08B00E04DDA /* blocklist.h in Headers */,
    21442156                                A2A4E9210DE0F7E9000CE197 /* web.h in Headers */,
     
    27542766                                BEFC1E4F0C07861A00B0BB3C /* inout.c in Sources */,
    27552767                                BEFC1E530C07861A00B0BB3C /* fdlimit.c in Sources */,
     2768                                C1FEE5781C3223CC00D62832 /* watchdir-generic.c in Sources */,
    27562769                                BEFC1E560C07861A00B0BB3C /* completion.c in Sources */,
    27572770                                BEFC1E580C07861A00B0BB3C /* clients.c in Sources */,
     
    27872800                                A209EE5C1144B51E002B02D1 /* history.c in Sources */,
    27882801                                A220EC5B118C8A060022B4BE /* tr-lpd.c in Sources */,
     2802                                C1FEE57A1C3223CC00D62832 /* watchdir.c in Sources */,
    27892803                                A23547E211CD0B090046EAE6 /* cache.c in Sources */,
    27902804                                A284214412DA663E00FBDDBB /* tr-udp.c in Sources */,
    27912805                                A2679294130E00A000CB7464 /* tr-utp.c in Sources */,
    27922806                                A23F29A2132A447400E9A83B /* announcer-http.c in Sources */,
     2807                                C1FEE5791C3223CC00D62832 /* watchdir-kqueue.c in Sources */,
    27932808                                A2AA9BE1132CAC8E00FA131E /* announcer-udp.c in Sources */,
    27942809                                A2D77452154CC25700A62B93 /* WebSeedTableView.m in Sources */,
     
    29672982                        files = (
    29682983                                BEFC1C1A0C07756200B0BB3C /* daemon.c in Sources */,
    2969                                 A2D5972A0F5AE49E0001AB3C /* watch.c in Sources */,
    29702984                                C1F690FD1AD0627500D95CF0 /* daemon-posix.c in Sources */,
    29712985                        );
  • trunk/configure.ac

    r14645 r14651  
    205205dnl file monitoring for the daemon
    206206
    207 AC_CHECK_HEADER([sys/inotify.h],
    208                 [AC_CHECK_FUNC([inotify_init],[have_inotify="yes"],[have_inotify="no"])],
    209                 [have_inotify="no"])
    210207AC_ARG_WITH([inotify],
    211             [AS_HELP_STRING([--with-inotify],[Enable inotify support (default=auto)])],
    212             [want_inotify=${withval}],
    213             [want_inotify=${have_inotify}])
    214 if test "x$want_inotify" = "xyes" ; then
    215     if test "x$have_inotify" = "xyes"; then
    216       AC_DEFINE([WITH_INOTIFY],[1])
    217     else
    218       AC_MSG_ERROR("inotify not found!")
    219     fi
    220 fi
    221 
    222 AC_CHECK_HEADER([sys/event.h],
    223                 [AC_CHECK_FUNC([kqueue],[have_kqueue="yes"],[have_kqueue="no"])],
    224                 [have_kqueue="no"])
     208            [AS_HELP_STRING([--with-inotify], [Enable inotify support (default=auto)])],
     209            [WANT_INOTIFY=${withval}],
     210            [WANT_INOTIFY=auto])
     211HAVE_INOTIFY=0
     212AS_IF([test "x$WANT_INOTIFY" != "xno"],
     213      [AC_CHECK_HEADER([sys/inotify.h],
     214                       [AC_CHECK_FUNC([inotify_init],
     215                                      [HAVE_INOTIFY=1])],
     216                       [AS_IF([test "x$WANT_INOTIFY" = "xyes"],
     217                              [AC_MSG_ERROR("inotify not found!")])])])
     218AM_CONDITIONAL([USE_INOTIFY], [test "x$WANT_INOTIFY" != "xno" -a $HAVE_INOTIFY -eq 1])
     219
    225220AC_ARG_WITH([kqueue],
    226221            [AS_HELP_STRING([--with-kqueue],[Enable kqueue support (default=auto)])],
    227             [want_kqueue=${withval}],
    228             [want_kqueue=${have_kqueue}])
    229 if test "x$want_kqueue" = "xyes" ; then
    230     if test "x$have_kqueue" = "xyes"; then
    231       AC_DEFINE([WITH_KQUEUE],[1])
    232     else
    233       AC_MSG_ERROR("kqueue not found!")
    234     fi
    235 fi
     222            [WITH_KQUEUE=${withval}],
     223            [WITH_KQUEUE=auto])
     224HAVE_KQUEUE=0
     225AS_IF([test "x$WITH_KQUEUE" != "xno"],
     226      [AC_CHECK_HEADER([sys/event.h],
     227                       [AC_CHECK_FUNC([kqueue],
     228                                      [HAVE_KQUEUE=1])],
     229                       [AS_IF([test "x$WANT_KQUEUE" = "xyes"],
     230                              [AC_MSG_ERROR("kqueue not found!")])])])
     231AM_CONDITIONAL([USE_KQUEUE], [test "x$WITH_KQUEUE" != "xno" -a $HAVE_KQUEUE -eq 1])
     232
    236233
    237234AC_CHECK_HEADERS([sys/statvfs.h \
  • trunk/daemon/CMakeLists.txt

    r14643 r14651  
    11project(trdaemon)
    2 
    3 if(WITH_INOTIFY)
    4     add_definitions(-DWITH_INOTIFY)
    5 endif()
    6 
    7 if(WITH_KQUEUE)
    8     add_definitions(-DWITH_KQUEUE)
    9 endif()
    102
    113if(WITH_SYSTEMD)
     
    2315    daemon-posix.c
    2416    daemon-win32.c
    25     watch.c
    2617)
    2718
     
    3425set(${PROJECT_NAME}_HEADERS
    3526    daemon.h
    36     watch.h
    3727)
    3828
  • trunk/daemon/Makefile.am

    r14487 r14651  
    3535    ${LIBM}
    3636
    37 noinst_HEADERS = \
    38     daemon.h \
    39     watch.h
     37noinst_HEADERS = daemon.h
    4038
    41 transmission_daemon_SOURCES = daemon.c watch.c
     39transmission_daemon_SOURCES = daemon.c
    4240transmission_remote_SOURCES = remote.c
    4341
  • trunk/daemon/daemon.c

    r14615 r14651  
    2222#endif
    2323
    24 #include <event2/buffer.h>
    2524#include <event2/event.h>
    2625
     
    3332#include <libtransmission/variant.h>
    3433#include <libtransmission/version.h>
     34#include <libtransmission/watchdir.h>
    3535
    3636#ifdef USE_SYSTEMD_DAEMON
     
    4242
    4343#include "daemon.h"
    44 #include "watch.h"
    4544
    4645#define MY_NAME "transmission-daemon"
     
    186185}
    187186
    188 static void
    189 onFileAdded (tr_session * session, const char * dir, const char * file)
    190 {
    191     char * filename = tr_buildPath (dir, file, NULL);
     187static tr_watchdir_status
     188onFileAdded (tr_watchdir_t   dir,
     189             const char    * name,
     190             void          * context)
     191{
     192    tr_session * session = context;
     193
     194    if (!tr_str_has_suffix (name, ".torrent"))
     195        return TR_WATCHDIR_IGNORE;
     196
     197    char * filename = tr_buildPath (tr_watchdir_get_path (dir), name, NULL);
    192198    tr_ctor * ctor = tr_ctorNew (session);
    193199    int err = tr_ctorSetMetainfoFromFile (ctor, filename);
     
    198204
    199205        if (err == TR_PARSE_ERR)
    200             tr_logAddError ("Error parsing .torrent file \"%s\"", file);
     206            tr_logAddError ("Error parsing .torrent file \"%s\"", name);
    201207        else
    202208        {
     
    204210            const bool test = tr_ctorGetDeleteSource (ctor, &trash);
    205211
    206             tr_logAddInfo ("Parsing .torrent file successful \"%s\"", file);
     212            tr_logAddInfo ("Parsing .torrent file successful \"%s\"", name);
    207213
    208214            if (test && trash)
     
    210216                tr_error * error = NULL;
    211217
    212                 tr_logAddInfo ("Deleting input .torrent file \"%s\"", file);
     218                tr_logAddInfo ("Deleting input .torrent file \"%s\"", name);
    213219                if (!tr_sys_path_remove (filename, &error))
    214220                {
     
    225231        }
    226232    }
     233    else
     234    {
     235        err = TR_PARSE_ERR;
     236    }
    227237
    228238    tr_ctorFree (ctor);
    229239    tr_free (filename);
     240
     241    return err == TR_PARSE_ERR ? TR_WATCHDIR_RETRY : TR_WATCHDIR_ACCEPT;
    230242}
    231243
     
    294306
    295307static void
    296 periodicUpdate (evutil_socket_t fd UNUSED, short what UNUSED, void *watchdir)
    297 {
    298     dtr_watchdir_update (watchdir);
    299 
     308periodicUpdate (evutil_socket_t   fd UNUSED,
     309                short             what UNUSED,
     310                void            * context UNUSED)
     311{
    300312    pumpLogMessages (logfile);
    301 
    302313    reportStatus ();
    303314}
     
    480491    bool boolVal;
    481492    const char * pid_filename;
    482     dtr_watchdir * watchdir = NULL;
    483493    bool pidfile_created = false;
    484494    tr_session * session = NULL;
    485     struct event *status_ev;
     495    struct event * status_ev = NULL;
     496    tr_watchdir_t watchdir = NULL;
    486497
    487498    struct daemon_data * const arg = raw_arg;
     
    559570        {
    560571            tr_logAddInfo ("Watching \"%s\" for new .torrent files", dir);
    561             watchdir = dtr_watchdir_new (mySession, dir, onFileAdded);
     572            if ((watchdir = tr_watchdir_new (dir, &onFileAdded, mySession, ev_base)) == NULL)
     573                goto cleanup;
    562574        }
    563575    }
     
    582594    {
    583595        struct timeval one_sec = { 1, 0 };
    584         status_ev = event_new(ev_base, -1, EV_PERSIST, &periodicUpdate, watchdir);
     596        status_ev = event_new(ev_base, -1, EV_PERSIST, &periodicUpdate, NULL);
    585597        if (status_ev == NULL)
    586598        {
     
    608620    printf ("Closing transmission session...");
    609621
     622    tr_watchdir_free (watchdir);
     623
    610624    if (status_ev)
    611625    {
     
    616630
    617631    tr_sessionSaveSettings (mySession, configDir, settings);
    618     dtr_watchdir_free (watchdir);
    619632    tr_sessionClose (mySession);
    620633    pumpLogMessages (logfile);
  • trunk/libtransmission/CMakeLists.txt

    r14643 r14651  
    6363    variant-json.c
    6464    verify.c
     65    watchdir.c
     66    watchdir-generic.c
     67    watchdir-inotify.c
     68    watchdir-kqueue.c
     69    watchdir-win32.c
    6570    web.c
    6671    webseed.c
     
    7580endforeach()
    7681
     82if(WITH_INOTIFY)
     83    add_definitions(-DWITH_INOTIFY)
     84else()
     85    set_source_files_properties(watchdir-inotify.c PROPERTIES HEADER_FILE_ONLY ON)
     86endif()
     87
     88if(WITH_KQUEUE)
     89    add_definitions(-DWITH_KQUEUE)
     90else()
     91    set_source_files_properties(watchdir-kqueue.c PROPERTIES HEADER_FILE_ONLY ON)
     92endif()
     93
    7794if(WIN32)
    7895    set_source_files_properties(file-posix.c PROPERTIES HEADER_FILE_ONLY ON)
    7996else()
    80     set_source_files_properties(file-win32.c PROPERTIES HEADER_FILE_ONLY ON)
     97    set_source_files_properties(file-win32.c watchdir-win32.c PROPERTIES HEADER_FILE_ONLY ON)
    8198endif()
    8299
     
    93110    utils.h
    94111    variant.h
     112    watchdir.h
    95113    web.h
    96114    ${PROJECT_BINARY_DIR}/version.h
     
    141159    verify.h
    142160    version.h
     161    watchdir-common.h
    143162    webseed.h
    144163)
     
    241260    set(crypto-test_ADD_SOURCES crypto-test-ref.h)
    242261
    243     foreach(T bitfield blocklist clients crypto error file history json magnet metainfo move peer-msgs quark rename rpc session tr-getopt utils variant)
     262    foreach(T bitfield blocklist clients crypto error file history json magnet metainfo move peer-msgs quark rename rpc session
     263              tr-getopt utils variant watchdir)
    244264        set(TP ${TR_NAME}-test-${T})
    245265        add_executable(${TP} ${T}-test.c ${${T}-test_ADD_SOURCES})
  • trunk/libtransmission/Makefile.am

    r14459 r14651  
    7373  variant-json.c \
    7474  verify.c \
     75  watchdir.c \
     76  watchdir-generic.c \
    7577  web.c \
    7678  webseed.c \
    7779  wildmat.c
    7880
     81if USE_INOTIFY
     82libtransmission_a_SOURCES += watchdir-inotify.c
     83endif
     84
     85if USE_KQUEUE
     86libtransmission_a_SOURCES += watchdir-kqueue.c
     87endif
     88
    7989if WIN32
    80 libtransmission_a_SOURCES += file-win32.c
     90libtransmission_a_SOURCES += file-win32.c watchdir-win32.c
    8191else
    8292libtransmission_a_SOURCES += file-posix.c
     
    151161  verify.h \
    152162  version.h \
     163  watchdir.h \
     164  watchdir-common.h \
    153165  web.h \
    154166  webseed.h
     
    174186  tr-getopt-test \
    175187  utils-test \
    176   variant-test
     188  variant-test \
     189  watchdir-test
    177190
    178191noinst_PROGRAMS = $(TESTS)
     
    271284variant_test_LDFLAGS = ${apps_ldflags}
    272285
     286watchdir_test_SOURCES = watchdir-test.c $(TEST_SOURCES)
     287watchdir_test_LDADD = ${apps_ldadd}
     288watchdir_test_LDFLAGS = ${apps_ldflags}
     289
    273290rename_test_SOURCES = rename-test.c $(TEST_SOURCES)
    274291rename_test_LDADD = ${apps_ldadd}
Note: See TracChangeset for help on using the changeset viewer.