Skip to content

Commit

Permalink
import src from [navalgazer](https://github.com/shama/navelgazer)
Browse files Browse the repository at this point in the history
  • Loading branch information
heavyk committed Jun 12, 2015
1 parent dcdf10d commit c4a003c
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 88 deletions.
53 changes: 39 additions & 14 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "common.h"

static uv_async_t g_async;
static int g_watch_count;
static uv_sem_t g_semaphore;
static uv_thread_t g_thread;

Expand All @@ -35,55 +36,70 @@ static void CommonThread(void* handle) {
PlatformThread();
}

#if NODE_VERSION_AT_LEAST(0, 11, 13)
static void MakeCallbackInMainThread(uv_async_t* handle) {
#else
static void MakeCallbackInMainThread(uv_async_t* handle, int status) {
#endif
NanScope();

if (!g_callback.IsEmpty()) {
Handle<String> type;
switch (g_type) {
case EVENT_CHANGE:
type = String::New("change");
type = NanNew("change");
break;
case EVENT_DELETE:
type = String::New("delete");
type = NanNew("delete");
break;
case EVENT_RENAME:
type = String::New("rename");
type = NanNew("rename");
break;
case EVENT_CHILD_CREATE:
type = String::New("child-create");
type = NanNew("child-create");
break;
case EVENT_CHILD_CHANGE:
type = String::New("child-change");
type = NanNew("child-change");
break;
case EVENT_CHILD_DELETE:
type = String::New("child-delete");
type = NanNew("child-delete");
break;
case EVENT_CHILD_RENAME:
type = String::New("child-rename");
type = NanNew("child-rename");
break;
default:
type = String::New("unknown");
fprintf(stderr, "Got unknown event: %d\n", g_type);
type = NanNew("unknown");
return;
}

Handle<Value> argv[] = {
type,
WatcherHandleToV8Value(g_handle),
String::New(g_new_path.data(), g_new_path.size()),
String::New(g_old_path.data(), g_old_path.size()),
NanNew(std::string(g_new_path.begin(), g_new_path.end())),
NanNew(std::string(g_old_path.begin(), g_old_path.end())),
};
NanPersistentToLocal(g_callback)->Call(
Context::GetCurrent()->Global(), 4, argv);
NanNew(g_callback)->Call(NanGetCurrentContext()->Global(), 4, argv);
}

WakeupNewThread();
}

static void SetRef(bool value) {
uv_handle_t* h = reinterpret_cast<uv_handle_t*>(&g_async);
if (value) {
uv_ref(h);
} else {
uv_unref(h);
}
}

void CommonInit() {
uv_sem_init(&g_semaphore, 0);
uv_async_init(uv_default_loop(), &g_async, MakeCallbackInMainThread);
// As long as any uv_ref'd uv_async_t handle remains active, the node
// process will never exit, so we must call uv_unref here (#47).
SetRef(false);
g_watch_count = 0;
uv_thread_create(&g_thread, &CommonThread, NULL);
}

Expand Down Expand Up @@ -115,7 +131,7 @@ NAN_METHOD(SetCallback) {
if (!args[0]->IsFunction())
return NanThrowTypeError("Function required");

NanAssignPersistent(Function, g_callback, Handle<Function>::Cast(args[0]));
NanAssignPersistent(g_callback, Local<Function>::Cast(args[0]));
NanReturnUndefined();
}

Expand All @@ -132,6 +148,10 @@ NAN_METHOD(Watch) {
if (!PlatformIsHandleValid(handle))
return NanThrowTypeError("Unable to watch path");

if (g_watch_count++ == 0) {
SetRef(true);
}

NanReturnValue(WatcherHandleToV8Value(handle));
}

Expand All @@ -142,5 +162,10 @@ NAN_METHOD(Unwatch) {
return NanThrowTypeError("Handle type required");

PlatformUnwatch(V8ValueToWatcherHandle(args[0]));

if (--g_watch_count == 0) {
SetRef(false);
}

NanReturnUndefined();
}
3 changes: 2 additions & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ bool IsV8ValueWatcherHandle(Handle<Value> value);
#else
// Correspoding definetions on OS X and Linux.
typedef int32_t WatcherHandle;
#define WatcherHandleToV8Value(h) Integer::New(h)
#define WatcherHandleToV8Value(h) NanNew<Integer>(h)
#define V8ValueToWatcherHandle(v) v->Int32Value()
#define IsV8ValueWatcherHandle(v) v->IsInt32()
#endif
Expand Down Expand Up @@ -74,3 +74,4 @@ NAN_METHOD(Watch);
NAN_METHOD(Unwatch);

#endif // SRC_COMMON_H_

20 changes: 10 additions & 10 deletions src/handle_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ bool HandleMap::Erase(WatcherHandle key) {
if (iter == map_.end())
return false;

NanDispose(iter->second); // Deprecated, use NanDisposePersistent when v0.12 lands
NanDisposeUnsafePersistent(iter->second);
map_.erase(iter);
return true;
}

void HandleMap::Clear() {
for (Map::iterator iter = map_.begin(); iter != map_.end(); ++iter)
NanDispose(iter->second); // Deprecated, use NanDisposePersistent when v0.12 lands
NanDisposeUnsafePersistent(iter->second);
map_.clear();
}

Expand All @@ -69,7 +69,7 @@ NAN_METHOD(HandleMap::Add) {
if (obj->Has(key))
return NanThrowError("Duplicate key");

NanAssignUnsafePersistent(Value, obj->map_[key], args[1]);
NanAssignUnsafePersistent(obj->map_[key], args[1]);
NanReturnUndefined();
}

Expand All @@ -85,7 +85,7 @@ NAN_METHOD(HandleMap::Get) {
if (!obj->Has(key))
return NanThrowError("Invalid key");

NanReturnValue(NanPersistentToLocal(obj->map_[key]));
NanReturnValue(NanUnsafePersistentToLocal(obj->map_[key]));
}

// static
Expand All @@ -96,7 +96,7 @@ NAN_METHOD(HandleMap::Has) {
return NanThrowTypeError("Bad argument");

HandleMap* obj = ObjectWrap::Unwrap<HandleMap>(args.This());
NanReturnValue(Boolean::New(obj->Has(V8ValueToWatcherHandle(args[0]))));
NanReturnValue(NanNew<Boolean>(obj->Has(V8ValueToWatcherHandle(args[0]))));
}

// static
Expand All @@ -106,11 +106,11 @@ NAN_METHOD(HandleMap::Values) {
HandleMap* obj = ObjectWrap::Unwrap<HandleMap>(args.This());

int i = 0;
Handle<Array> keys = Array::New(obj->map_.size());
Handle<Array> keys = NanNew<Array>(obj->map_.size());
for (Map::const_iterator iter = obj->map_.begin();
iter != obj->map_.end();
++iter, ++i)
keys->Set(i, NanPersistentToLocal(iter->second));
keys->Set(i, NanUnsafePersistentToLocal(iter->second));

NanReturnValue(keys);
}
Expand Down Expand Up @@ -143,9 +143,9 @@ NAN_METHOD(HandleMap::Clear) {
void HandleMap::Initialize(Handle<Object> target) {
NanScope();

Local<FunctionTemplate> t = FunctionTemplate::New(HandleMap::New);
Local<FunctionTemplate> t = NanNew<FunctionTemplate>(HandleMap::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(NanSymbol("HandleMap"));
t->SetClassName(NanNew<String>("HandleMap"));

NODE_SET_PROTOTYPE_METHOD(t, "add", Add);
NODE_SET_PROTOTYPE_METHOD(t, "get", Get);
Expand All @@ -154,5 +154,5 @@ void HandleMap::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "remove", Remove);
NODE_SET_PROTOTYPE_METHOD(t, "clear", Clear);

target->Set(NanSymbol("HandleMap"), t->GetFunction());
target->Set(NanNew<String>("HandleMap"), t->GetFunction());
}
4 changes: 4 additions & 0 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "common.h"
#include "handle_map.h"

namespace {

void Init(Handle<Object> exports) {
CommonInit();
PlatformInit();
Expand All @@ -32,4 +34,6 @@ void Init(Handle<Object> exports) {
HandleMap::Initialize(exports);
}

} // namespace

NODE_MODULE(pathwatcher, Init)
12 changes: 3 additions & 9 deletions src/pathwatcher_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ static int g_inotify;
void PlatformInit() {
g_inotify = inotify_init();
if (g_inotify == -1) {
perror("inotify_init");
return;
}

Expand All @@ -53,10 +52,8 @@ void PlatformThread() {
} while (size == -1 && errno == EINTR);

if (size == -1) {
perror("read");
break;
} else if (size == 0) {
fprintf(stderr, "read returns 0, buffer size is too small\n");
break;
}

Expand All @@ -70,10 +67,10 @@ void PlatformThread() {

// Note that inotify won't tell us where the file or directory has been
// moved to, so we just treat IN_MOVE_SELF as file being deleted.
if (e->mask & (IN_ATTRIB | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE)) {
type = EVENT_CHANGE;
} else if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) {
if (e->mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF)) {
type = EVENT_DELETE;
} else if (e->mask & (IN_ATTRIB | IN_CREATE | IN_MODIFY | IN_MOVE)) {
type = EVENT_CHANGE;
} else {
continue;
}
Expand All @@ -86,9 +83,6 @@ void PlatformThread() {
WatcherHandle PlatformWatch(const char* path) {
int fd = inotify_add_watch(g_inotify, path, IN_ATTRIB | IN_CREATE |
IN_DELETE | IN_MODIFY | IN_MOVE | IN_MOVE_SELF | IN_DELETE_SELF);
if (fd == -1)
perror("inotify_add_watch");

return fd;
}

Expand Down
7 changes: 3 additions & 4 deletions src/pathwatcher_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void PlatformThread() {
int fd = static_cast<int>(event.ident);
std::vector<char> path;

if (event.fflags & NOTE_WRITE) {
if (event.fflags & (NOTE_WRITE | NOTE_ATTRIB)) {
type = EVENT_CHANGE;
} else if (event.fflags & NOTE_DELETE) {
type = EVENT_DELETE;
Expand All @@ -74,15 +74,14 @@ void PlatformThread() {
WatcherHandle PlatformWatch(const char* path) {
int fd = open(path, O_EVTONLY, 0);
if (fd < 0) {
// TODO: Maybe this could be handled better?
return -(errno);
return fd;
}

struct timespec timeout = { 0, 0 };
struct kevent event;
int filter = EVFILT_VNODE;
int flags = EV_ADD | EV_ENABLE | EV_CLEAR;
int fflags = NOTE_WRITE | NOTE_DELETE | NOTE_RENAME;
int fflags = NOTE_WRITE | NOTE_DELETE | NOTE_RENAME | NOTE_ATTRIB;
EV_SET(&event, fd, filter, flags, fflags, 0, (void*)path);
kevent(g_kqueue, &event, 1, NULL, 0, &timeout);

Expand Down
9 changes: 3 additions & 6 deletions src/pathwatcher_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static bool QueueReaddirchanges(HandleWrapper* handle) {
}

Handle<Value> WatcherHandleToV8Value(WatcherHandle handle) {
Handle<Value> value = NanPersistentToLocal(g_object_template)->NewInstance();
Handle<Value> value = NanNew(g_object_template)->NewInstance();
NanSetInternalFieldPointer(value->ToObject(), 0, handle);
return value;
}
Expand All @@ -137,8 +137,8 @@ void PlatformInit() {
g_wake_up_event = CreateEvent(NULL, FALSE, FALSE, NULL);
g_events.push_back(g_wake_up_event);

NanAssignPersistent(ObjectTemplate, g_object_template, ObjectTemplate::New());
NanPersistentToLocal(g_object_template)->SetInternalFieldCount(1);
NanAssignPersistent(g_object_template, ObjectTemplate::New());
NanNew(g_object_template)->SetInternalFieldCount(1);

WakeupNewThread();
}
Expand Down Expand Up @@ -273,7 +273,6 @@ WatcherHandle PlatformWatch(const char* path) {
// Requires a directory, file watching is emulated in js.
DWORD attr = GetFileAttributesW(wpath);
if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
fprintf(stderr, "%s is not a directory\n", path);
return INVALID_HANDLE_VALUE;
}

Expand All @@ -287,7 +286,6 @@ WatcherHandle PlatformWatch(const char* path) {
FILE_FLAG_OVERLAPPED,
NULL);
if (!PlatformIsHandleValid(dir_handle)) {
fprintf(stderr, "Unable to call CreateFileW for %s\n", path);
return INVALID_HANDLE_VALUE;
}

Expand All @@ -298,7 +296,6 @@ WatcherHandle PlatformWatch(const char* path) {
}

if (!QueueReaddirchanges(handle.get())) {
fprintf(stderr, "ReadDirectoryChangesW failed\n");
return INVALID_HANDLE_VALUE;
}

Expand Down
Loading

0 comments on commit c4a003c

Please sign in to comment.