示例#1
0
FSEventStreamRef CreateEventStream( DirWatchMap path )
{
  if ( ( g_Stream == NULL ) && CanRunNotifications() )
  {
    CFStringRef* pathLists = (CFStringRef*)malloc( sizeof(CFStringRef*) * path.size() );
    int   index = 0;
    for ( DirWatchMap::iterator it = path.begin() ; it != path.end(); ++it)
    {
      pathLists[index] = CFStringCreateWithFileSystemRepresentation( NULL, OsString(it->path).c_str());
      index++;
    }
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)pathLists, index, NULL);

    FSEventStreamContext *callbackInfo = NULL;
 
    FSEventStreamRef stream = FSEventStreamCreate(NULL, &fsevent_callback, callbackInfo, pathsToWatch,
        kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents );

    CFRelease( pathsToWatch );
    free( pathLists );

    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    if (!FSEventStreamStart(stream)) 
      debug_warn(L"event_loop FSEventStreamStart failed!"); 
    else
      return stream;
  }
  return NULL;
}
示例#2
0
Status dir_watch_Poll(DirWatchNotifications& notifications)
{
	if(initialized == -1)
		return ERR::FAIL;	// NOWARN
	if(!initialized) // XXX Fix Atlas instead of suppressing the warning
		return ERR::FAIL; //WARN_RETURN(ERR::LOGIC);

	std::vector<NotificationEvent> polled_notifications;

	pthread_mutex_lock(&g_mutex);
	g_notifications.swap(polled_notifications);
	pthread_mutex_unlock(&g_mutex);

	for(size_t i = 0; i < polled_notifications.size(); ++i)
	{
		DirWatchNotification::EType type;
		// TODO: code is actually a bitmask, so this is slightly incorrect
		switch(polled_notifications[i].code)
		{
		case IN_CLOSE_WRITE:
			type = DirWatchNotification::Changed;
			break;
		case IN_CREATE:
			type = DirWatchNotification::Created;
			break;
		case IN_DELETE:
			type = DirWatchNotification::Deleted;
			break;
		default:
			continue;
		}

		DirWatchMap::iterator it = g_paths.find(polled_notifications[i].wd);
		if(it != g_paths.end())
		{
			OsPath filename = Path(OsString(it->second->path).append(polled_notifications[i].filename));
			notifications.push_back(DirWatchNotification(filename, type));
		}
		else
		{
			debug_printf("dir_watch_Poll: Notification with invalid watch descriptor wd=%d\n", polled_notifications[i].wd);
		}
	}

	// nothing new; try again later
	return INFO::OK;
}
示例#3
0
static void fsevent_callback(
    ConstFSEventStreamRef UNUSED(streamRef),
    void * UNUSED(clientCallBackInfo),
    size_t numEvents,
    void *eventPaths,
    const FSEventStreamEventFlags eventFlags[],
    const FSEventStreamEventId UNUSED(eventIds)[] )
{
    unsigned long i;
    char **paths = (char **)eventPaths;
 
    for (i=0; i<numEvents; i++)
    {
      bool    isWatched = false;
      OsPath eventPath  = OsPath(paths[i]);
      unsigned long eventType = eventFlags[i];

      if ( eventPath.Filename().string().c_str()[0] != '.' )
      {
        for ( DirWatchMap::iterator it = g_Paths.begin() ; it != g_Paths.end(); ++it)
          if ( path_is_subpath( it->path.string().c_str(), eventPath.string().c_str() ) )
            isWatched = true;
      }

      if ( ! isWatched )
        return;

      OsPath filename = Path( eventPath.string().c_str() );

      if ( eventType & kFSEventStreamEventFlagItemIsFile)
      {
        if ( eventType & kFSEventStreamEventFlagItemRemoved )
          g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted ));
        else if ( eventType & kFSEventStreamEventFlagItemRenamed )
          g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted ));
        else if ( eventType & kFSEventStreamEventFlagItemCreated )
          g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Created ));
        else if ( eventType & kFSEventStreamEventFlagItemModified )
          g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Changed ));
      }
    }

}
示例#4
0
Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)
{
  PDirWatch tmpDirWatch(new DirWatch);
  dirWatch.swap(tmpDirWatch);
  dirWatch->path = path;
  dirWatch->reqnum = 0;
  g_Paths.push_back( *dirWatch );

  bool  alreadyInsideRootPath = false;
  for ( DirWatchMap::iterator it = g_RootPaths.begin() ; it != g_RootPaths.end(); ++it)
  {
    if ( path_is_subpath( path.string().c_str(), it->path.string().c_str() ) )
      alreadyInsideRootPath = true;
  }

  if ( !alreadyInsideRootPath )
  {
    DeleteEventStream();
    g_RootPaths.push_back( *dirWatch );
  }

	return INFO::OK;
}
示例#5
0
Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)
{
	char resolved[PATH_MAX + 1];

	// init already failed; don't try again or complain	
	if(initialized == -1)
		return ERR::FAIL;	// NOWARN

	if(!initialized)
	{
		errno = 0;
		if((inotifyfd = inotify_init()) < 0) 
		{
			// Check for error ?
			int err = errno;
			initialized = -1;
			LOGERROR("Error initializing inotify file descriptor; hotloading will be disabled, errno=%d", err);
			errno = err;
			return StatusFromErrno();	// NOWARN
		}

		errno = 0;
		int ret = pthread_create(&g_event_loop_thread, NULL, &inotify_event_loop, NULL);
		if (ret != 0)
		{
			initialized = -1;
			LOGERROR("Error creating inotify event loop thread; hotloading will be disabled, err=%d", ret);
			errno = ret;
			return StatusFromErrno();	// NOWARN
		}

		initialized = 1;
		atexit(inotify_deinit);
	}

	PDirWatch tmpDirWatch(new DirWatch);
	errno = 0;
	int wd = inotify_add_watch(inotifyfd, realpath(OsString(path).c_str(), resolved), IN_CREATE | IN_DELETE | IN_CLOSE_WRITE);
	if (wd < 0)
		WARN_RETURN(StatusFromErrno());

	dirWatch.swap(tmpDirWatch);
	dirWatch->path = path;
	dirWatch->reqnum = wd;
	g_paths.insert(std::make_pair(wd, dirWatch));

	return INFO::OK;
}