OSX FSEventStreamEventFlags不能正常工作 [英] OSX FSEventStreamEventFlags not working correctly

查看:440
本文介绍了OSX FSEventStreamEventFlags不能正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在看文件系统事件的目录。似乎一切都正常工作有一个例外。当我创建一个文件中的第一次,它吐出来创建它。然后,我可以删除它,它说,它已被删除。当我再次去创建相同的文件,我得到都在同一时间创建和删除标记。我明显感到误解如何回调被调用时,标志被设置。这里发生了什么?

  //
// main.c中
// GoFSEvents
//
//创建者凯尔库克在13年8月22日。
//版权所有(C)2013凯尔库克。版权所有。
//#包括LT&; CoreServices / CoreServices.h>
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;无效eventCallback(FSEventStreamRef流,无效* callbackInfo,为size_t numEvents,无效*路径,常量FSEventStreamEventFlags eventFlags [],常量FSEventStreamEventId eventIds []){
    焦炭** pathsList =路径;    的for(int i = 0; I< numEvents;我++){
        UINT32标志= eventFlags [I]        UINT32创建= kFSEventStreamEventFlagItemCreated;
        UINT32删除= kFSEventStreamEventFlagItemRemoved;        如果(旗&安培;删除){
            的printf(项中移除:%S \\ n,pathsList [I]);
        }
        否则,如果(旗&安培;创建){
            的printf(项创建:%S \\ n,pathsList [I]);
        }
    }
}INT主(INT ARGC,为const char * argv的[])
{
    CFStringRef mypath中= CFSTR(/路径/到/目录);
    CFArrayRef路径= CFArrayCreate(NULL,(常量无效**)及mypath中,1,NULL);    CFRunLoo preF环= CFRunLoopGetMain();
    FSEventStreamRef流= FSEventStreamCreate(NULL,(FSEventStreamCallback)eventCallback,NULL,路径,kFSEventStreamEventIdSinceNow,1.0,kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
    FSEventStreamScheduleWithRunLoop(流循环,kCFRunLoopDefaultMode);
    FSEventStreamStart(流);    CFRunLoopRun();    FSEventStreamStop(流);
    FSEventStreamInvalidate(流);
    FSEventStreamRelease(流);    返回0;
}


解决方案

据我所知,你将不得不寻找任何 kFSEventStreamEventFlagItemRemoved kFSEventStreamEventFlagItemCreated ,然后用 STAT()或类似的检查,如果该文件实际上添加或删除。该FSEvents文档似乎暗示这样。

它看起来像API是OR符号事件位在一起......所以说实在的,因为在创建FSEventsListener所做的所有更改的OR。因为这似乎是的情况下,另一种选择可能是创建一个新的FSEventListener每次(并使用聚结计时器选项)。

我做了一些谷歌搜索,但没有发现这个问题,甚至苹果样品code的其他例子,但我并没有太长时间花钱就可以了。

我已经previously使用的kqueue API: https://gist.github.com/nielsbot/5155671(这个要点是围绕一个kqueue的OBJ-C包装)

我改变你的样品code要为每个FSEvent设置的所有标志:

 的#include< CoreServices / CoreServices.h>
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;静态INT __count = 0;
无效eventCallback(FSEventStreamRef流,无效* callbackInfo,为size_t numEvents,无效*路径,常量FSEventStreamEventFlags eventFlags [],常量FSEventStreamEventId eventIds []){
    焦炭** pathsList =路径;    的printf(回调#%U \\ N,++ __计数);
    为const char *标志[] = {
        MustScanSubDirs
        UserDropped
        KernelDropped
        EventIdsWrapped
        HistoryDone
        RootChanged
        安装,
        卸载,
        ItemCreated
        ItemRemoved
        ItemInodeMetaMod
        ItemRenamed
        ItemModified
        ItemFinderInfoMod
        ItemChangeOwner
        ItemXattrMod
        ItemIsFile
        ItemIsDir
        ItemIsSymlink
        OwnEvent
    };    的for(int i = 0; I< numEvents;我++)
    {
        的printf(%U \\ N,I);
        的printf(\\ tpath%S \\ n,pathsList [I]);
        的printf(\\ tflags:);
        长位= 1;
        对于(INT指数= 0,计数= sizeof的(标志)/ sizeof的(标志[0]);指数<计数++指数)
        {
            如果((eventFlags [1] - 放大器;!位)= 0)
            {
                的printf(%S标志[指数]);
            }
            比特下;&下; = 1;
        }
        的printf(\\ n);
    }    FSEventStreamFlushSync(流);}INT主(INT ARGC,为const char * argv的[])
{
    CFStringRef路径= CFStringCreateWithCString(kCFAllocatorDefault,ARGV [1],kCFStringEncodingUTF8);
    CFArrayRef路径= CFArrayCreate(NULL,(常量无效**)及路径,1,&安培; kCFTypeArrayCallBacks);
    如果(路径){CFRelease(路径); }    CFRunLoo preF环= CFRunLoopGetCurrent();
    FSEventStreamRef流= FSEventStreamCreate(NULL,(FSEventStreamCallback)eventCallback,NULL,路径,kFSEventStreamEventIdSinceNow,0,kFSEventStreamCreateFlagFileEvents);
    如果(路径){CFRelease(路径); }    FSEventStreamScheduleWithRunLoop(流循环,kCFRunLoopDefaultMode);
    FSEventStreamStart(流);    CFRunLoopRun();    FSEventStreamStop(流);
    FSEventStreamInvalidate(流);
    FSEventStreamRelease(流);    返回0;
}

I am watching a directory for file system events. Everything seems to work fine with one exception. When I create a file the first time, it spits out that it was created. Then I can remove it and it says it was removed. When I go to create the same file again, I get both a created and removed flag at the same time. I obviously am misunderstanding how the flags are being set when the callback is being called. What is happening here?

//
//  main.c
//  GoFSEvents
//
//  Created by Kyle Cook on 8/22/13.
//  Copyright (c) 2013 Kyle Cook. All rights reserved.
//

#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>

void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
    char **pathsList = paths;

    for(int i = 0; i<numEvents; i++) {
        uint32 flag = eventFlags[i];

        uint32 created = kFSEventStreamEventFlagItemCreated;
        uint32 removed = kFSEventStreamEventFlagItemRemoved;

        if(flag & removed) {
            printf("Item Removed: %s\n", pathsList[i]);
        }
        else if(flag & created) {
            printf("Item Created: %s\n", pathsList[i]);
        }
    }
}

int main(int argc, const char * argv[])
{
    CFStringRef mypath = CFSTR("/path/to/dir");
    CFArrayRef paths = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);

    CFRunLoopRef loop = CFRunLoopGetMain();
    FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
    FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);

    CFRunLoopRun();

    FSEventStreamStop(stream);
    FSEventStreamInvalidate(stream);
    FSEventStreamRelease(stream);

    return 0;
}

解决方案

As far as I can tell, you will have to look for either kFSEventStreamEventFlagItemRemoved or kFSEventStreamEventFlagItemCreated, and then use stat() or similar to check if the file was in fact added or deleted. The FSEvents documentation seems to hint as such.

It looks like the API is or'ing the events bits together... so really it's an OR of all the changes made since the FSEventsListener is created. Since that seems to be the case, another option might be to create a new FSEventListener each time (and use the coalesce timer option).

I did some Googling, but didn't find other examples of this problem or even apple sample code, but I didn't spend too long on it.

I have previously used the kqueue API: https://gist.github.com/nielsbot/5155671 (This gist is an obj-c wrapper around kqueue)

I changed your sample code to show all flags set for each FSEvent:

#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>

static int __count = 0 ;
void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
    char **pathsList = paths;

    printf("callback #%u\n", ++__count ) ;
    const char * flags[] = {
        "MustScanSubDirs",
        "UserDropped",
        "KernelDropped",
        "EventIdsWrapped",
        "HistoryDone",
        "RootChanged",
        "Mount",
        "Unmount",
        "ItemCreated",
        "ItemRemoved",
        "ItemInodeMetaMod",
        "ItemRenamed",
        "ItemModified",
        "ItemFinderInfoMod",
        "ItemChangeOwner",
        "ItemXattrMod",
        "ItemIsFile",
        "ItemIsDir",
        "ItemIsSymlink",
        "OwnEvent"
    } ;

    for(int i = 0; i<numEvents; i++)
    {
        printf("%u\n", i ) ;
        printf("\tpath %s\n", pathsList[i]) ;
        printf("\tflags: ") ;
        long bit = 1 ;
        for( int index=0, count = sizeof( flags ) / sizeof( flags[0]); index < count; ++index )
        {
            if ( ( eventFlags[i] & bit ) != 0 )
            {
                printf("%s ", flags[ index ] ) ;
            }
            bit <<= 1 ;
        }
        printf("\n") ;
    }

    FSEventStreamFlushSync( stream ) ;

}

int main(int argc, const char * argv[])
{
    CFStringRef path = CFStringCreateWithCString( kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8 ) ;
    CFArrayRef paths = CFArrayCreate(NULL, (const void **)&path, 1, &kCFTypeArrayCallBacks );
    if ( path ) { CFRelease( path ) ; }

    CFRunLoopRef loop = CFRunLoopGetCurrent() ;
    FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 0, kFSEventStreamCreateFlagFileEvents );
    if ( paths ) { CFRelease( paths ) ; }

    FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);

    CFRunLoopRun() ;

    FSEventStreamStop(stream);
    FSEventStreamInvalidate(stream);
    FSEventStreamRelease(stream);

    return 0;
}

这篇关于OSX FSEventStreamEventFlags不能正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆