2013-08-24 39 views
13

Tôi đang xem thư mục cho các sự kiện hệ thống tệp. Mọi thứ dường như hoạt động tốt với một ngoại lệ. Khi tôi tạo một tập tin lần đầu tiên, nó phun ra rằng nó đã được tạo ra. Sau đó, tôi có thể xóa nó và nó nói rằng nó đã được gỡ bỏ. Khi tôi tạo lại cùng một tệp, tôi nhận được cả cờ được tạo và xóa cùng một lúc. Tôi rõ ràng là sự hiểu lầm làm thế nào các lá cờ đang được thiết lập khi gọi lại đang được gọi. Chuyện gì đang xảy ra ở đây?OSX FSEventStreamEventFlags không hoạt động chính xác

// 
// 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; 
} 
+0

tương tự vấn đề: https://github.com/haskell-fswatch/hfsnotify/issues/36 –

+1

Từ mã gọi lại của bạn, tôi không thấy bất kỳ cách nào bạn có thể xóa cả hai và tạo cùng một lúc. Chúng phải được in trong các cuộc gọi lại riêng biệt. (Bạn có nếu() else if().) –

+0

Bạn đã kiểm tra xem việc xóa cờ 'kFSEventStreamCreateFlagNoDefer' có thay đổi gì không? – JSuar

Trả lời

6

Theo như tôi có thể nói, bạn sẽ phải tìm kiếm một trong hai kFSEventStreamEventFlagItemRemoved hoặc kFSEventStreamEventFlagItemCreated, và sau đó sử dụng stat() hoặc tương tự để kiểm tra xem các tập tin được trong thực tế thêm hoặc xóa. Tài liệu FSEvents dường như gợi ý như vậy.

Có vẻ như API đang kết hợp các bit sự kiện với nhau ... vì vậy thực sự đó là một OR của tất cả các thay đổi được thực hiện kể từ khi FSEventsListener được tạo. Vì có vẻ như vậy, một tùy chọn khác có thể là tạo một FSEventListener mới mỗi lần (và sử dụng tùy chọn hẹn giờ kết hợp).

Tôi đã làm một số Googling, nhưng không tìm thấy các ví dụ khác về vấn đề này hoặc thậm chí mã mẫu táo, nhưng tôi đã không dành quá nhiều thời gian cho nó.

trước đây tôi đã sử dụng các API kqueue: https://gist.github.com/nielsbot/5155671 (ý chính Đây là một wrapper obj-c xung quanh kqueue)

tôi đã thay đổi mẫu mã của bạn để hiển thị tất cả những lá cờ thiết lập cho mỗi 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; 
} 
+0

Cảm ơn! Tôi thích ý tưởng sử dụng kqueue - không biết nó hoạt động trên Mac OS X. –

Các vấn đề liên quan