On 01/19/15 17:13, David Coppa wrote:
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.

How will this patch affect libraries with more then 512 directories, since kqueue is restricted by the limit of open file descriptors?
martijn@donar:/home/multimedia/Video's$ ulimit -n
512
martijn@donar:/home/multimedia/Video's$ find . -type d | wc -l
    2345
martijn@donar:/home/multimedia/Video's$ find . -type f | wc -l
   57640


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





Reply via email to