Skip to content

Commit

Permalink
Brute force tree walking implementation for linux
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett committed Mar 14, 2019
1 parent 346c4ad commit 59abd82
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 2 deletions.
14 changes: 13 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,22 @@
],
"conditions": [
['OS=="mac"', {
"sources": ["src/macos/FSEvents.cc"],
"variables": {
"use_nftw%": "false"
},
"conditions": [
['use_nftw=="true"', {
"sources": ["src/unix/nftw.cc"]
}, {
"sources": ["src/macos/FSEvents.cc"],
}]
],
"link_settings": {
"libraries": ["CoreServices.framework"]
}
}],
['OS=="linux"', {
"sources": ["src/unix/nftw.cc"]
}]
]
}
Expand Down
90 changes: 90 additions & 0 deletions src/DirTree.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#ifndef DIR_TREE_H
#define DIR_TREE_H

#include <string>
#include <unordered_set>
#include <ostream>
#include <istream>
#include "Event.hh"

struct DirEntry {
std::string path;
time_t mtime;

DirEntry(const char *p, const struct stat *info) {
path.assign(p);
mtime = info->st_mtime;
}

DirEntry(std::istream &stream) {
size_t size;

if (stream >> size) {
path.resize(size);
if (stream.read(&path[0], size)) {
stream >> mtime;
}
}
}

bool operator==(const DirEntry &other) const {
return path == other.path;
}

void write(std::ostream &stream) const {
stream << path.size() << path << mtime << "\n";
}
};

namespace std {
template <>
struct hash<DirEntry> {
std::size_t operator()(const DirEntry& k) const {
return hash<string>()(k.path);
}
};
}

struct DirTree {
std::unordered_set<DirEntry> entries;
DirTree() {}

DirTree(std::istream &stream) {
size_t size;
if (stream >> size) {
for (size_t i = 0; i < size; i++) {
entries.insert(DirEntry(stream));
}
}
}

void write(std::ostream &stream) {
stream << entries.size() << "\n";
for (auto it = entries.begin(); it != entries.end(); it++) {
it->write(stream);
}
}

EventList *getChanges(DirTree *snapshot) {
EventList *events = new EventList();
for (auto it = entries.begin(); it != entries.end(); it++) {
auto found = snapshot->entries.find(*it);
if (found == snapshot->entries.end()) {
events->push(it->path, "create");
} else if (found->mtime != it->mtime) {
events->push(it->path, "update");
}
}

for (auto it = snapshot->entries.begin(); it != snapshot->entries.end(); it++) {
size_t count = entries.count(*it);
if (count == 0) {
events->push(it->path, "delete");
}
}

return events;
}
};

#endif
2 changes: 1 addition & 1 deletion src/Event.hh
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public:
arr->Set(i, mEvents[i]->toJS());
}

return scope.Escape(arr);
return scope.Escape(arr);
}
};

Expand Down
36 changes: 36 additions & 0 deletions src/unix/nftw.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <string>
#include <sstream>
#include <ftw.h>
#include "../DirTree.hh"
#include "../Event.hh"

static DirTree *tree;
int addEntry(const char *path, const struct stat *info, const int flags, struct FTW *ftw) {
tree->entries.insert(DirEntry(path, info));
return 0;
}

DirTree *getDirTree(std::string *dir) {
tree = new DirTree();
int result = nftw(dir->c_str(), &addEntry, 15, FTW_PHYS);
if (result < 0) {
printf("error\n");
}

return tree;
}

std::string getCurrentTokenImpl(std::string *dir) {
auto tree = getDirTree(dir);
std::ostringstream os;
tree->write(os);
return os.str();
}

EventList *getEventsSinceImpl(std::string *dir, std::string *token) {
std::istringstream is(*token);
auto snapshot = new DirTree(is);
auto now = getDirTree(dir);

return now->getChanges(snapshot);
}

0 comments on commit 59abd82

Please sign in to comment.