On Mon, Jan 19, 2015 at 12:06 AM, LÉVAI Dániel <l...@ecentrum.hu> wrote:

>> It might be better to look at the kqueue patch that FreeBSD are using.
>
> Now this seems to work for me on i386, at least. It applied almost
> clean, but I've taken the liberty and removed the whitespace-only
> changes from FreeBSD's diff(s). I'll be honest, it got a bit slower, but
> this could very well be because of my rusty hard drives.
>
> Here is my diff:

I do not use MiniDLNA, but your diff below looks good and, if it
works, then it's ok with me if Stuart wants to commit it.

ciao,
David

>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/multimedia/minidlna/Makefile,v
> retrieving revision 1.10
> diff -p -u -r1.10 Makefile
> --- Makefile    3 Sep 2014 21:15:43 -0000       1.10
> +++ Makefile    18 Jan 2015 22:45:10 -0000
> @@ -3,6 +3,7 @@
>  COMMENT=       lightweight DLNA/UPnP-AV media server
>
>  V=             1.1.4
> +REVISION=      0
>  DISTNAME=      minidlna-$V
>  PKGNAME=       minidlna-$V
>
> @@ -34,9 +35,15 @@ LIB_DEPENDS= audio/flac \
>                 graphics/jpeg \
>                 graphics/libexif
>
> +AUTOCONF_VERSION= 2.69
> +AUTOMAKE_VERSION= 1.14
> +
>  NO_TEST=       Yes
>  E=             ${PREFIX}/share/examples/minidlna
>
> +post-patch:
> +       @cd ${WRKSRC} && env AUTOCONF_VERSION=${AUTOCONF_VERSION} \
> +           AUTOMAKE_VERSION=${AUTOMAKE_VERSION} ./autogen.sh
>  post-install:
>         ${INSTALL_DATA_DIR} $E
>         ${INSTALL_DATA} ${WRKSRC}/minidlna.conf $E
> Index: patches/patch-configure_ac
> ===================================================================
> RCS file: patches/patch-configure_ac
> diff -N patches/patch-configure_ac
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-configure_ac  18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,12 @@
> +$OpenBSD$
> +--- configure.ac.orig  Tue Aug 26 23:09:22 2014
> ++++ configure.ac       Sun Jan 18 22:45:07 2015
> +@@ -481,7 +481,7 @@ AC_CHECK_LIB(vorbisfile, vorbis_comment_query,
> + 
> ################################################################################################################
> + ### Header checks
> +
> +-AC_CHECK_HEADERS([arpa/inet.h asm/unistd.h endian.h machine/endian.h 
> fcntl.h libintl.h locale.h netdb.h netinet/in.h stddef.h stdlib.h string.h 
> sys/file.h sys/inotify.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h 
> unistd.h])
> ++AC_CHECK_HEADERS([arpa/inet.h asm/unistd.h endian.h machine/endian.h 
> fcntl.h libintl.h locale.h netdb.h netinet/in.h stddef.h stdlib.h string.h 
> sys/file.h sys/inotify.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h 
> unistd.h sys/event.h])
> +
> + AC_CHECK_FUNCS(inotify_init, AC_DEFINE(HAVE_INOTIFY,1,[Whether kernel has 
> inotify support]), [
> +     AC_MSG_CHECKING([for __NR_inotify_init syscall])
> Index: patches/patch-inotify_c
> ===================================================================
> RCS file: patches/patch-inotify_c
> diff -N patches/patch-inotify_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-inotify_c     18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,569 @@
> +$OpenBSD$
> +--- inotify.c.orig     Sun Jan 18 22:45:24 2015
> ++++ inotify.c  Sun Jan 18 22:45:27 2015
> +@@ -15,9 +15,9 @@
> +  * You should have received a copy of the GNU General Public License
> +  * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
> +  */
> + #include "config.h"
> +
> +-#ifdef HAVE_INOTIFY
> ++#if defined(HAVE_INOTIFY) || defined(HAVE_SYS_EVENT_H)
> + #include <stdio.h>
> + #include <string.h>
> + #include <stdlib.h>
> +@@ -31,11 +31,16 @@
> + #include <sys/time.h>
> + #include <sys/resource.h>
> + #include <poll.h>
> ++#ifdef HAVE_INOTIFY
> + #ifdef HAVE_SYS_INOTIFY_H
> + #include <sys/inotify.h>
> +-#else
> ++#else /*HAVE_SYS_INOTIFY_H*/
> + #include "linux/inotify.h"
> + #include "linux/inotify-syscalls.h"
> ++#endif /*HAVE_SYS_INOTIFY_H*/
> ++#else
> ++#include <sys/event.h>
> ++#include <fcntl.h>
> + #endif
> + #include "libav.h"
> +
> +@@ -49,11 +54,13 @@
> + #include "playlist.h"
> + #include "log.h"
> +
> ++#ifdef HAVE_INOTIFY
> + #define EVENT_SIZE  ( sizeof (struct inotify_event) )
> + #define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
> + #define DESIRED_WATCH_LIMIT 65536
> +
> + #define PATH_BUF_SIZE PATH_MAX
> ++#endif
> +
> + struct watch
> + {
> +@@ -86,13 +93,35 @@ add_watch(int fd, const char * path)
> +       struct watch *nw;
> +       int wd;
> +
> ++#ifdef HAVE_INOTIFY
> +       wd = inotify_add_watch(fd, path, 
> IN_CREATE|IN_CLOSE_WRITE|IN_DELETE|IN_MOVE);
> +       if( wd < 0 )
> +       {
> +               DPRINTF(E_ERROR, L_INOTIFY, "inotify_add_watch(%s) [%s]\n", 
> path, strerror(errno));
> +               return -1;
> +       }
> ++#else /*HAVE_INOTIFY*/
> ++      wd = open(path, O_RDONLY);
> ++      if (wd == -1)
> ++      {
> ++              DPRINTF(E_ERROR, L_INOTIFY, 
> "inotify_add_watch[kqueue,open](%s) [%s]\n", path, strerror(errno));
> ++              return -1;
> ++      }
> +
> ++      struct kevent ke;
> ++      EV_SET(&ke, wd,
> ++              EVFILT_VNODE,
> ++              EV_ADD | EV_ENABLE | EV_CLEAR,
> ++              NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND /*| NOTE_ATTRB*/,
> ++              0, NULL);
> ++
> ++      if( kevent(fd, &ke, 1, NULL, 0, NULL) == -1 )
> ++      {
> ++              DPRINTF(E_ERROR, L_INOTIFY, "inotify_add_watch[kqueue](%s) 
> [%s]\n", path, strerror(errno));
> ++              return -1;
> ++      }
> ++#endif
> ++
> +       nw = malloc(sizeof(struct watch));
> +       if( nw == NULL )
> +       {
> +@@ -125,7 +154,12 @@ remove_watch(int fd, const char * path)
> +       for( w = watches; w; w = w->next )
> +       {
> +               if( strcmp(path, w->path) == 0 )
> ++#ifdef HAVE_INOTIFY
> +                       return(inotify_rm_watch(fd, w->wd));
> ++#else
> ++                      close(w->wd); /* kqueue cleans up events when handle 
> dies*/
> ++                      return(0);
> ++#endif
> +       }
> +
> +       return 1;
> +@@ -145,15 +179,14 @@ next_highest(unsigned int num)
> + int
> + inotify_create_watches(int fd)
> + {
> +-      FILE * max_watches;
> +-      unsigned int num_watches = 0, watch_limit;
> ++      unsigned int num_watches = 0;
> +       char **result;
> +       int i, rows = 0;
> +       struct media_dir_s * media_path;
> +
> +       for( media_path = media_dirs; media_path != NULL; media_path = 
> media_path->next )
> +       {
> +-              DPRINTF(E_DEBUG, L_INOTIFY, "Add watch to %s\n", 
> media_path->path);
> ++              DPRINTF(E_DEBUG, L_INOTIFY, "Setting up monitoring on %s\n", 
> media_path->path);
> +               add_watch(fd, media_path->path);
> +               num_watches++;
> +       }
> +@@ -165,7 +198,11 @@ inotify_create_watches(int fd)
> +               num_watches++;
> +       }
> +       sqlite3_free_table(result);
> +
> ++#ifdef HAVE_INOTIFY
> ++      FILE * max_watches;
> ++      unsigned int watch_limit;
> ++
> +       max_watches = fopen("/proc/sys/fs/inotify/max_user_watches", "r");
> +       if( max_watches )
> +       {
> +@@ -194,16 +231,17 @@ inotify_create_watches(int fd)
> +                       else
> +                       {
> +                               DPRINTF(E_WARN, L_INOTIFY, "WARNING: Inotify 
> max_user_watches [%u] is low or close to the number of used watches [%u] "
> +                                                       "and I do not have 
> permission to increase this limit.  Please do so manually by "
> +                                                       "writing a higher 
> value into /proc/sys/fs/inotify/max_user_watches.\n", watch_limit, 
> num_watches);
> +                       }
> +               }
> +       }
> +       else
> +       {
> +               DPRINTF(E_WARN, L_INOTIFY, "WARNING: Could not read inotify 
> max_user_watches!  "
> +                                       "Hopefully it is enough to cover %u 
> current directories plus any new ones added.\n", num_watches);
> +       }
> ++#endif
> +
> +       return rows;
> + }
> +@@ -218,7 +256,11 @@ inotify_remove_watches(int fd)
> +       while( w )
> +       {
> +               last_w = w;
> ++#ifdef HAVE_INOTIFY
> +               inotify_rm_watch(fd, w->wd);
> ++#else
> ++              close(w->wd); /*kqueue cleans up after fhandle dies*/
> ++#endif
> +               free(w->path);
> +               rm_watches++;
> +               w = w->next;
> +@@ -261,10 +303,10 @@ int add_dir_watch(int fd, char * path, char * filename
> +               while( (e = readdir(ds)) )
> +               {
> +                       if( strcmp(e->d_name, ".") == 0 ||
> +                           strcmp(e->d_name, "..") == 0 )
> +                               continue;
> +                       if( (e->d_type == DT_DIR) ||
> +                           (e->d_type == DT_UNKNOWN && 
> resolve_unknown_type(dir, NO_MEDIA) == TYPE_DIR) )
> +                               i += add_dir_watch(fd, dir, e->d_name);
> +               }
> +       }
> +@@ -293,7 +335,10 @@ inotify_insert_file(char * name, const char * path)
> +       media_types types = ALL_MEDIA;
> +       struct media_dir_s * media_path = media_dirs;
> +       struct stat st;
> ++      struct timeval now;
> +
> ++      DPRINTF(E_DEBUG, L_INOTIFY, "inotify_insert_file: %s @ %s\n", name, 
> path);
> ++
> +       /* Is it cover art for another file? */
> +       if( is_image(path) )
> +               update_if_album_art(path);
> +@@ -357,6 +402,16 @@ inotify_insert_file(char * name, const char * path)
> +       if( stat(path, &st) != 0 )
> +               return -1;
> +
> ++      (void)gettimeofday(&now, NULL);
> ++      while (now.tv_sec < st.st_mtime + 3)
> ++      {
> ++              DPRINTF(E_DEBUG, L_INOTIFY, "Sleeping until %s is stable for 
> a few seconds ...\n", path);
> ++              sleep(1);
> ++              (void)gettimeofday(&now, NULL);
> ++              if (stat(path, &st) != 0)
> ++                      return -1;
> ++      }
> ++
> +       ts = sql_get_int_field(db, "SELECT TIMESTAMP from DETAILS where PATH 
> = '%q'", path);
> +       if( !ts && is_playlist(path) && (sql_get_int_field(db, "SELECT ID 
> from PLAYLISTS where PATH = '%q'", path) > 0) )
> +       {
> +@@ -386,9 +441,9 @@ inotify_insert_file(char * name, const char * path)
> +
> +               do
> +               {
> +-                      //DEBUG DPRINTF(E_DEBUG, L_INOTIFY, "Checking %s\n", 
> parent_buf);
> ++                      /*DEBUG DPRINTF(E_DEBUG, L_INOTIFY, "Checking %s\n", 
> parent_buf);*/
> +                       id = sql_get_text_field(db, "SELECT OBJECT_ID from 
> OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
> +                                                   " where d.PATH = '%q' and 
> REF_ID is NULL", parent_buf);
> +                       if( id )
> +                       {
> +                               if( !depth )
> +@@ -446,6 +501,8 @@ inotify_insert_directory(int fd, char *name, const cha
> +       struct media_dir_s* media_path;
> +       struct stat st;
> +
> ++      DPRINTF(E_DEBUG, L_INOTIFY, "inotify_insert_directory: %s @ %s\n", 
> name, path);
> ++
> +       if( access(path, R_OK|X_OK) != 0 )
> +       {
> +               DPRINTF(E_WARN, L_INOTIFY, "Could not access %s [%s]\n", 
> path, strerror(errno));
> +@@ -459,7 +516,7 @@ inotify_insert_directory(int fd, char *name, const cha
> +
> +       parent_buf = strdup(path);
> +       id = sql_get_text_field(db, "SELECT OBJECT_ID from OBJECTS o left 
> join DETAILS d on (d.ID = o.DETAIL_ID)"
> +                                   " where d.PATH = '%q' and REF_ID is 
> NULL", dirname(parent_buf));
> +       if( !id )
> +               id = sqlite3_mprintf("%s", BROWSEDIR_ID);
> +       insert_directory(name, path, BROWSEDIR_ID, id+2, 
> get_next_available_id("OBJECTS", id));
> +@@ -554,27 +611,25 @@ inotify_remove_file(const char * path)
> +       {
> +               sql_exec(db, "DELETE from PLAYLISTS where ID = %lld", 
> detailID);
> +               sql_exec(db, "DELETE from DETAILS where ID ="
> +                            " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID 
> = '%s$%llX')",
> +                        MUSIC_PLIST_ID, detailID);
> +               sql_exec(db, "DELETE from OBJECTS where OBJECT_ID = '%s$%llX' 
> or PARENT_ID = '%s$%llX'",
> +                        MUSIC_PLIST_ID, detailID, MUSIC_PLIST_ID, detailID);
> +       }
> +       else
> +       {
> +               /* Delete the parent containers if we are about to empty 
> them. */
> +-              snprintf(sql, sizeof(sql), "SELECT PARENT_ID from OBJECTS 
> where DETAIL_ID = %lld"
> +-                                         " and PARENT_ID not like '64$%%'",
> +-                                         (long long int)detailID);
> ++              snprintf(sql, sizeof(sql), "SELECT PARENT_ID from OBJECTS 
> where DETAIL_ID = %lld", (long long int)detailID);
> +               if( (sql_get_table(db, sql, &result, &rows, NULL) == 
> SQLITE_OK) )
> +               {
> +                       int i, children;
> +                       for( i = 1; i <= rows; i++ )
> +                       {
> +                               /* If it's a playlist item, adjust the item 
> count of the playlist */
> +                               if( strncmp(result[i], MUSIC_PLIST_ID, 
> strlen(MUSIC_PLIST_ID)) == 0 )
> +                               {
> +                                       sql_exec(db, "UPDATE PLAYLISTS set 
> FOUND = (FOUND-1) where ID = %d",
> +                                                atoi(strrchr(result[i], '$') 
> + 1));
> +                               }
> +
> +                               children = sql_get_int_field(db, "SELECT 
> count(*) from OBJECTS where PARENT_ID = '%s'", result[i]);
> +@@ -582,6 +637,8 @@ inotify_remove_file(const char * path)
> +                                       continue;
> +                               if( children < 2 )
> +                               {
> ++                                      sql_exec(db, "DELETE from DETAILS 
> where ID ="
> ++                                                                            
>            " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", 
> result[i]);
> +                                       sql_exec(db, "DELETE from OBJECTS 
> where OBJECT_ID = '%s'", result[i]);
> +
> +                                       ptr = strrchr(result[i], '$');
> +@@ -589,6 +646,8 @@ inotify_remove_file(const char * path)
> +                                               *ptr = '\0';
> +                                       if( sql_get_int_field(db, "SELECT 
> count(*) from OBJECTS where PARENT_ID = '%s'", result[i]) == 0 )
> +                                       {
> ++                                              sql_exec(db, "DELETE from 
> DETAILS where ID ="
> ++                                                                            
>                    " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", 
> result[i]);
> +                                               sql_exec(db, "DELETE from 
> OBJECTS where OBJECT_ID = '%s'", result[i]);
> +                                       }
> +                               }
> +@@ -613,11 +672,13 @@ inotify_remove_directory(int fd, const char * path)
> +       int64_t detailID = 0;
> +       int rows, i, ret = 1;
> +
> ++      DPRINTF(E_DEBUG, L_INOTIFY, "inotify_remove_directory: %s\n", path);
> ++
> +       /* Invalidate the scanner cache so we don't insert files into 
> non-existent containers */
> +       valid_cache = 0;
> +       remove_watch(fd, path);
> +       sql = sqlite3_mprintf("SELECT ID from DETAILS where (PATH > '%q/' and 
> PATH <= '%q/%c')"
> +                             " or PATH = '%q'", path, path, 0xFF, path);
> +       if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) )
> +       {
> +               if( rows )
> +@@ -639,6 +700,7 @@ inotify_remove_directory(int fd, const char * path)
> +       return ret;
> + }
> +
> ++#ifdef HAVE_INOTIFY
> + void *
> + start_inotify()
> + {
> +@@ -649,7 +711,7 @@ start_inotify()
> +       int length, i = 0;
> +       char * esc_name = NULL;
> +       struct stat st;
> +
> +       pollfds[0].fd = inotify_init();
> +       pollfds[0].events = POLLIN;
> +
> +@@ -664,13 +726,13 @@ start_inotify()
> +       }
> +       inotify_create_watches(pollfds[0].fd);
> +       if (setpriority(PRIO_PROCESS, 0, 19) == -1)
> +               DPRINTF(E_WARN, L_INOTIFY,  "Failed to reduce inotify thread 
> priority\n");
> +       sqlite3_release_memory(1<<31);
> +       av_register_all();
> +
> +       while( !quitting )
> +       {
> +                 length = poll(pollfds, 1, timeout);
> +               if( !length )
> +               {
> +                       if( next_pl_fill && (time(NULL) >= next_pl_fill) )
> +@@ -708,12 +770,12 @@ start_inotify()
> +                               snprintf(path_buf, sizeof(path_buf), "%s/%s", 
> get_path_from_wd(event->wd), event->name);
> +                               if ( event->mask & IN_ISDIR && (event->mask & 
> (IN_CREATE|IN_MOVED_TO)) )
> +                               {
> +                                       DPRINTF(E_DEBUG, L_INOTIFY,  "The 
> directory %s was %s.\n",
> +                                               path_buf, (event->mask & 
> IN_MOVED_TO ? "moved here" : "created"));
> +                                       
> inotify_insert_directory(pollfds[0].fd, esc_name, path_buf);
> +                               }
> +                               else if ( (event->mask & 
> (IN_CLOSE_WRITE|IN_MOVED_TO|IN_CREATE)) &&
> +                                         (lstat(path_buf, &st) == 0) )
> +                               {
> +                                       if( S_ISLNK(st.st_mode) )
> +                                       {
> +@@ -727,7 +789,7 @@ start_inotify()
> +                                       else if( event->mask & 
> (IN_CLOSE_WRITE|IN_MOVED_TO) && st.st_size > 0 )
> +                                       {
> +                                               if( (event->mask & 
> IN_MOVED_TO) ||
> +                                                   (sql_get_int_field(db, 
> "SELECT TIMESTAMP from DETAILS where PATH = '%q'", path_buf) != st.st_mtime) )
> +                                               {
> +                                                       DPRINTF(E_DEBUG, 
> L_INOTIFY, "The file %s was %s.\n",
> +                                                               path_buf, 
> (event->mask & IN_MOVED_TO ? "moved here" : "changed"));
> +@@ -756,4 +818,234 @@ quitting:
> +
> +       return 0;
> + }
> ++#else
> ++void *
> ++start_kqueue()
> ++{
> ++      int global_kqueue_handle = -1;
> ++
> ++      global_kqueue_handle = kqueue();
> ++      if ( global_kqueue_handle < 0 )
> ++      {
> ++              DPRINTF(E_ERROR, L_INOTIFY, "kqueue() failed: %s\n", 
> strerror(errno));
> ++              return 0;
> ++      }
> ++
> ++      while( scanning )
> ++      {
> ++              if( quitting )
> ++                      goto quitting;
> ++
> ++              DPRINTF(E_DEBUG, L_INOTIFY, "..waiting for scanning to 
> complete...\n");
> ++              sleep(1);
> ++      }
> ++
> ++      DPRINTF(E_DEBUG, L_INOTIFY, "GOING WILD!\n");
> ++
> ++      inotify_create_watches(global_kqueue_handle);
> ++      if (setpriority(PRIO_PROCESS, 0, 19) == -1)
> ++              DPRINTF(E_WARN, L_INOTIFY,      "Failed to reduce kqueue 
> thread priority\n");
> ++      sqlite3_release_memory(1<<31);
> ++      av_register_all();
> ++
> ++      while( !quitting )
> ++      {
> ++              struct kevent ke;
> ++              if ( kevent(global_kqueue_handle, NULL, 0, &ke, 1, NULL) == 
> -1 )
> ++              {
> ++                      DPRINTF(E_WARN, L_INOTIFY,      "kevent polling 
> failure: %s\n", strerror(errno));
> ++                      continue;
> ++              }
> ++
> ++              /*DPRINTF(E_DEBUG, L_INOTIFY,   "GOT KEVENT:\n"
> ++                      "ident=0x%X, filter=0x%X, flags=0x%X, fflags=0x%X, 
> data=0x%X, udata=0x%X\n",
> ++                      ke.ident, ke.filter, ke.flags, ke.fflags, ke.data, 
> ke.udata);*/
> ++
> ++              char* dir_path = get_path_from_wd(ke.ident);
> ++              if (dir_path == NULL)
> ++              {
> ++                      DPRINTF(E_ERROR, L_INOTIFY, "Path with FD=0x%X can't 
> be resolved.\n", ke.ident);
> ++                      continue;
> ++              }
> ++
> ++              if (ke.fflags & NOTE_DELETE)
> ++              {
> ++                      DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] deleted.\n", 
> dir_path);
> ++                      inotify_remove_directory(ke.ident, dir_path);
> ++              }
> ++              else if ((ke.fflags & (NOTE_WRITE | NOTE_LINK)) == 
> (NOTE_WRITE | NOTE_LINK))
> ++              {
> ++                      DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] content 
> updated (directory).\n", dir_path);
> ++
> ++                      char * sql;
> ++                      char **result;
> ++                      int i, rows;
> ++                      sql = sqlite3_mprintf("SELECT PATH from DETAILS where 
> (PATH > '%q/' and PATH <= '%q/%c')"
> ++                              " and SIZE = ''", dir_path, dir_path, 0xFF);
> ++                      if( (sql_get_table(db, sql, &result, &rows, NULL) != 
> SQLITE_OK) )
> ++                      {
> ++                              DPRINTF(E_WARN, L_INOTIFY, "Read state [%s]: 
> Query failed, not updating\n", dir_path);
> ++                              sqlite3_free(sql);
> ++                              continue;
> ++                      }
> ++
> ++                      for( i=1; i <= rows; i++ )
> ++                      {
> ++                              DPRINTF(E_DEBUG, L_INOTIFY, "Indexed content: 
> %s\n", result[i]);
> ++                              if (access(result[i], R_OK) == -1)
> ++                              {
> ++                                      /* actually, global_kqueue_handle is 
> not used here */
> ++                                      
> inotify_remove_directory(global_kqueue_handle, result[i]);
> ++                              }
> ++                      }
> ++
> ++                      DIR* d;
> ++                      struct dirent * entry;
> ++                      d = opendir(dir_path);
> ++                      if (!d)
> ++                      {
> ++                              DPRINTF(E_ERROR, L_INOTIFY, "Can't list [%s] 
> (%s)\n", dir_path, strerror(errno));
> ++                              continue;
> ++                      }
> ++
> ++                      for ( entry = readdir(d); entry != NULL; entry = 
> readdir(d) )
> ++                      {
> ++                              if ( (entry->d_type == DT_DIR) &&
> ++                                      (strcmp(entry->d_name, "..") != 0) &&
> ++                                      (strcmp(entry->d_name, ".") != 0) )
> ++                              {
> ++                                      char tmp_path[PATH_MAX];
> ++                                      int result_path_len;
> ++
> ++                                      result_path_len = snprintf(tmp_path, 
> PATH_MAX,
> ++                                              "%s/%s", dir_path, 
> entry->d_name);
> ++                                      if (result_path_len >= PATH_MAX)
> ++                                      {
> ++                                              DPRINTF(E_ERROR, L_INOTIFY, 
> "File path too long for %s!", entry->d_name);
> ++                                              continue;
> ++                                      }
> ++
> ++                                      DPRINTF(E_DEBUG, L_INOTIFY, "Walking 
> %s\n", tmp_path);
> ++                                      char found_flag = 0;
> ++                                      for( i=1; i <= rows; i++ )
> ++                                      {
> ++                                              if (strcmp(result[i], 
> tmp_path) == 0)
> ++                                              {
> ++                                                      found_flag = 1;
> ++                                                      break;
> ++                                              }
> ++                                      }
> ++
> ++                                      if ( !found_flag )
> ++                                      {
> ++                                              char * esc_name = NULL;
> ++                                              esc_name = 
> modifyString(strdup(entry->d_name), "&", "&amp;amp;", 0);
> ++                                              
> inotify_insert_directory(global_kqueue_handle, esc_name, tmp_path);
> ++                                              free(esc_name);
> ++                                      }
> ++                              }
> ++                      }
> ++
> ++                      closedir(d);
> ++
> ++                      sqlite3_free_table(result);
> ++                      sqlite3_free(sql);
> ++              }
> ++              else if (ke.fflags & NOTE_WRITE)
> ++              {
> ++                      DPRINTF(E_DEBUG, L_INOTIFY, "Path [%s] content 
> updated (file).\n", dir_path);
> ++
> ++                      char * sql;
> ++                      char **result;
> ++                      int i, rows;
> ++                      sql = sqlite3_mprintf("SELECT PATH from DETAILS where 
> (PATH > '%q/' and PATH <= '%q/%c')"
> ++                              " and SIZE <> ''", dir_path, dir_path, 0xFF);
> ++                      if( (sql_get_table(db, sql, &result, &rows, NULL) != 
> SQLITE_OK) )
> ++                      {
> ++                              DPRINTF(E_WARN, L_INOTIFY, "Read state [%s]: 
> Query failed, not updating\n", dir_path);
> ++                              sqlite3_free(sql);
> ++                              continue;
> ++                      }
> ++
> ++                      for( i=1; i <= rows; i++ )
> ++                      {
> ++                              DPRINTF(E_DEBUG, L_INOTIFY, "Indexed content: 
> %s\n", result[i]);
> ++                              if (access(result[i], R_OK) == -1) /*oops, 
> our file is gone*/
> ++                              {
> ++                                      inotify_remove_file(result[i]);
> ++                              }
> ++                      }
> ++
> ++                      DIR* d;
> ++                      struct dirent * entry;
> ++                      d = opendir(dir_path);
> ++                      if (!d)
> ++                      {
> ++                              DPRINTF(E_ERROR, L_INOTIFY, "Can't list [%s] 
> (%s)\n", dir_path, strerror(errno));
> ++                              continue;
> ++                      }
> ++
> ++                      for ( entry = readdir(d); entry != NULL; entry = 
> readdir(d) )
> ++                      {
> ++                              if ( (entry->d_type == DT_REG) ||
> ++                                   (entry->d_type == DT_LNK) )
> ++                              {
> ++                                      char tmp_path[PATH_MAX];
> ++                                      int result_path_len;
> ++
> ++                                      result_path_len = snprintf(tmp_path, 
> PATH_MAX,
> ++                                              "%s/%s", dir_path, 
> entry->d_name);
> ++                                      if (result_path_len >= PATH_MAX)
> ++                                      {
> ++                                              DPRINTF(E_ERROR, L_INOTIFY, 
> "File path too long for %s!", entry->d_name);
> ++                                              continue;
> ++                                      }
> ++
> ++                                      DPRINTF(E_DEBUG, L_INOTIFY, "Walking 
> %s\n", tmp_path);
> ++
> ++                                      char found_flag = 0;
> ++                                      for( i=1; i <= rows; i++ )
> ++                                      {
> ++                                              if (strcmp(result[i], 
> tmp_path) == 0)
> ++                                              {
> ++                                                      found_flag = 1;
> ++                                                      break;
> ++                                              }
> ++                                      }
> ++
> ++                                      if ( !found_flag )
> ++                                      {
> ++                                              char * esc_name = NULL;
> ++                                              struct stat st;
> ++
> ++                                              if( stat(tmp_path, &st) != 0 )
> ++                                              {
> ++                                                      DPRINTF(E_ERROR, 
> L_INOTIFY, "'%s' disappeared!", tmp_path);
> ++                                                      continue;
> ++                                              }
> ++
> ++                                              esc_name = 
> modifyString(strdup(entry->d_name), "&", "&amp;amp;", 0);
> ++                                              if ( S_ISDIR(st.st_mode) )
> ++                                                      
> inotify_insert_directory(global_kqueue_handle, esc_name, tmp_path);
> ++                                              else
> ++                                                      
> inotify_insert_file(esc_name, tmp_path);
> ++                                              free(esc_name);
> ++                                      }
> ++                              }
> ++                      }
> ++
> ++                      closedir(d);
> ++
> ++                      sqlite3_free_table(result);
> ++                      sqlite3_free(sql);
> ++              }
> ++      }
> ++      inotify_remove_watches(global_kqueue_handle);
> ++quitting:
> ++
> ++      return 0;
> ++}
> + #endif
> ++
> ++#endif // defined(HAVE_INOTIFY) || defined(HAVE_SYS_EVENT_H)
> ++
> Index: patches/patch-inotify_h
> ===================================================================
> RCS file: patches/patch-inotify_h
> diff -N patches/patch-inotify_h
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-inotify_h     18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,14 @@
> +$OpenBSD$
> +--- inotify.h.orig     Tue Aug 26 23:09:22 2014
> ++++ inotify.h  Sun Jan 18 22:45:07 2015
> +@@ -4,4 +4,10 @@ inotify_remove_file(const char * path);
> +
> + void *
> + start_inotify();
> ++#elif defined(HAVE_SYS_EVENT_H)
> ++int
> ++inotify_remove_file(const char* path);
> ++
> ++void *
> ++start_kqueue();
> + #endif
> Index: patches/patch-metadata_c
> ===================================================================
> RCS file: patches/patch-metadata_c
> diff -N patches/patch-metadata_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-metadata_c    18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,12 @@
> +$OpenBSD$
> +--- metadata.c.orig    Tue Aug 26 23:09:22 2014
> ++++ metadata.c Sun Jan 18 22:45:07 2015
> +@@ -149,7 +149,7 @@ check_for_captions(const char *path, int64_t detailID)
> +
> +       if (ret == 0)
> +       {
> +-              sql_exec(db, "INSERT into CAPTIONS"
> ++              sql_exec(db, "INSERT OR REPLACE into CAPTIONS"
> +                            " (ID, PATH) "
> +                            "VALUES"
> +                            " (%lld, %Q)", detailID, file);
> Index: patches/patch-minidlna_c
> ===================================================================
> RCS file: patches/patch-minidlna_c
> diff -N patches/patch-minidlna_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-minidlna_c    18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,43 @@
> +$OpenBSD$
> +--- minidlna.c.orig    Tue Aug 26 23:09:22 2014
> ++++ minidlna.c Sun Jan 18 22:45:07 2015
> +@@ -46,6 +46,7 @@
> +  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
> THE
> +  * POSSIBILITY OF SUCH DAMAGE.
> +  */
> ++#define FD_SETSIZE 8192
> + #include <stdlib.h>
> + #include <unistd.h>
> + #include <string.h>
> +@@ -376,6 +377,7 @@ rescan:
> +               open_db(&db);
> +               if (*scanner_pid == 0) /* child (scanner) process */
> +               {
> ++                      DPRINTF(E_DEBUG, L_GENERAL, "Starting scanner in 
> forked child\n");
> +                       start_scanner();
> +                       sqlite3_close(db);
> +                       log_close();
> +@@ -384,6 +386,7 @@ rescan:
> +               }
> +               else if (*scanner_pid < 0)
> +               {
> ++                      DPRINTF(E_DEBUG, L_GENERAL, "Starting scanner in 
> parent\n");
> +                       start_scanner();
> +               }
> + #else
> +@@ -1047,6 +1050,15 @@ main(int argc, char **argv)
> +                                                   "Inotify will be 
> disabled.\n");
> +               else if (pthread_create(&inotify_thread, NULL, start_inotify, 
> NULL) != 0)
> +                       DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() 
> failed for start_inotify. EXITING\n");
> ++      }
> ++#elif defined(HAVE_SYS_EVENT_H)
> ++      if( GETFLAG(INOTIFY_MASK) )
> ++      {
> ++              if (!sqlite3_threadsafe() || sqlite3_libversion_number() < 
> 3005001)
> ++                      DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not 
> threadsafe!  "
> ++                      "Kqueue will be disabled.\n");
> ++              else if (pthread_create(&inotify_thread, NULL, start_kqueue, 
> NULL) != 0)
> ++                      DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() 
> failed for start_kqueue. EXITING\n");
> +       }
> + #endif
> +       smonitor = OpenAndConfMonitorSocket();
> Index: patches/patch-minidlna_conf
> ===================================================================
> RCS file: /cvs/ports/multimedia/minidlna/patches/patch-minidlna_conf,v
> retrieving revision 1.4
> diff -p -u -r1.4 patch-minidlna_conf
> --- patches/patch-minidlna_conf 11 Jun 2014 00:26:59 -0000      1.4
> +++ patches/patch-minidlna_conf 18 Jan 2015 22:45:10 -0000
> @@ -28,7 +28,7 @@ default directories, plus we don't use i
>
>   # set this to merge all media_dir base contents into the root container
>   # note: the default is no
> -@@ -25,22 +26,18 @@ media_dir=/opt
> +@@ -25,22 +26,22 @@ media_dir=/opt
>   #friendly_name=My DLNA Server
>
>   # set this if you would like to specify the directory where you want 
> MiniDLNA to store its database and album art cache
> @@ -47,10 +47,10 @@ default directories, plus we don't use i
>   # this should be a list of file names to check for when searching for album 
> art
>   # note: names should be delimited with a forward slash ("/")
>   
> album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
> --
> --# set this to no to disable inotify monitoring to automatically discover 
> new files
> --# note: the default is yes
> --inotify=yes
> +
> + # set this to no to disable inotify monitoring to automatically discover 
> new files
> + # note: the default is yes
> + inotify=yes
>
>   # set this to yes to enable support for streaming .jpg and .mp3 files to a 
> TiVo supporting HMO
>   enable_tivo=no
> Index: patches/patch-upnpevents_c
> ===================================================================
> RCS file: patches/patch-upnpevents_c
> diff -N patches/patch-upnpevents_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-upnpevents_c  18 Jan 2015 22:45:10 -0000
> @@ -0,0 +1,14 @@
> +$OpenBSD$
> +--- upnpevents.c.orig  Tue Aug 26 23:09:22 2014
> ++++ upnpevents.c       Sun Jan 18 22:45:07 2015
> +@@ -417,6 +417,10 @@ void upnpevents_selectfds(fd_set *readset, fd_set *wri
> + {
> +       struct upnp_event_notify * obj;
> +       for(obj = notifylist.lh_first; obj != NULL; obj = 
> obj->entries.le_next) {
> ++              if (obj->s > FD_SETSIZE)
> ++                      DPRINTF(E_FATAL, L_HTTP,
> ++                          "upnpevents_selectfds: file descriptor %d too big 
> for select, limit is %d\n",
> ++                          obj->s, FD_SETSIZE);
> +               DPRINTF(E_DEBUG, L_HTTP, "upnpevents_selectfds: %p %d %d\n",
> +                      obj, obj->state, obj->s);
> +               if(obj->s >= 0) {
>
>
> Comments, tests?
>
>
> Daniel
>
> --
> LÉVAI Dániel
> PGP key ID = 0x83B63A8F
> Key fingerprint = DBEC C66B A47A DFA2 792D  650C C69B BE4C 83B6 3A8F
>



-- 
"If you try a few times and give up, you'll never get there. But if
you keep at it... There's a lot of problems in the world which can
really be solved by applying two or three times the persistence that
other people will."
                -- Stewart Nelson

Reply via email to