Skip to content

Commit

Permalink
Added basic features for Rubinius::FSEvent.
Browse files Browse the repository at this point in the history
  • Loading branch information
brixen committed Aug 31, 2014
1 parent 86366a0 commit 51e816c
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 15 deletions.
33 changes: 33 additions & 0 deletions kernel/delta/fsevent.rb
@@ -0,0 +1,33 @@
module Rubinius
class FSEvent
attr_accessor :fileno
attr_accessor :path

def self.allocate
Rubinius.primitive :fsevent_allocate
raise PrimitiveFailure, "Rubinius::FSEvent.allocate failed"
end

def watch_file(fd, path)
Rubinius.primitive :fsevent_watch_file
raise PrimitiveFailure, "Rubinius::FSEvent#watch_file failed"
end

def wait_for_event
Rubinius.primitive :fsevent_wait_for_event
raise PrimitiveFailure, "Rubinius::FSEvent#wait_for_event failed"
end

def inspect
str = "#<#{self.class}:0x#{self.__id__.to_s(16)}"

str << " fileno=#{fileno}" if fileno
str << " path=#{path}" if path
str << ">"

Rubinius::Type.infect str, self

str
end
end
end
1 change: 1 addition & 0 deletions kernel/delta/load_order.txt
Expand Up @@ -15,6 +15,7 @@ signal.rbc
struct.rbc
thread.rbc
code_loader.rbc
fsevent.rbc
console.rbc
ffi.rbc
ruby_constants.rbc
Expand Down
1 change: 1 addition & 0 deletions rakelib/vm.rake
Expand Up @@ -82,6 +82,7 @@ field_extract_headers = %w[
vm/builtin/dir.hpp
vm/builtin/exception.hpp
vm/builtin/float.hpp
vm/builtin/fsevent.hpp
vm/builtin/immediates.hpp
vm/builtin/iseq.hpp
vm/builtin/list.hpp
Expand Down
52 changes: 52 additions & 0 deletions vm/builtin/fsevent.cpp
@@ -0,0 +1,52 @@
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/fsevent.hpp"
#include "builtin/string.hpp"

#include "ontology.hpp"

namespace rubinius {
void FSEvent::init(STATE) {
GO(fsevent).set(ontology::new_class_under(state, "FSEvent", G(rubinius)));
G(fsevent)->set_object_type(state, FSEventType);
}

#ifdef HAVE_KQUEUE
FSEvent* FSEvent::create(STATE) {
FSEvent* fsevent = state->new_object<FSEvent>(G(fsevent));
fsevent->kq_ = kqueue();
return fsevent;
}

FSEvent* FSEvent::allocate(STATE, Object* self) {
FSEvent* fsevent = create(state);
fsevent->klass(state, as<Class>(self));
return fsevent;
}

Object* FSEvent::watch_file(STATE, Fixnum* fd, String* path) {
this->fileno(state, fd);
this->path(state, path);

EV_SET(&filter_, fd->to_native(), EVFILT_VNODE,
EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);

return cNil;
}

Object* FSEvent::watch_file(STATE, int fd, const char* path) {
return watch_file(state, Fixnum::from(fd), String::create(state, path));
}

Object* FSEvent::wait_for_event() {
int status = kevent(kq_, &filter_, 1, &event_, 1, NULL);

if(status < 0 || !(event_.fflags & NOTE_WRITE)) {
return cNil;
}

return cTrue;
}
#elif HAVE_INOTIFY
#endif
}
64 changes: 64 additions & 0 deletions vm/builtin/fsevent.hpp
@@ -0,0 +1,64 @@
#ifndef RBX_FSEVENT_HPP
#define RBX_FSEVENT_HPP

#include "builtin/object.hpp"

#ifdef HAVE_KQUEUE
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#elif HAVE_INOTIFY
#else
#error "No file system event utility is available. Please submit an issue."
#endif

namespace rubinius {
class Fixnum;
class String;

class FSEvent : public Object {
public:
const static object_type type = FSEventType;

private:
Fixnum* fileno_; // slot
String* path_; // slot

public:
/* accessors */

attr_accessor(fileno, Fixnum);
attr_accessor(path, String);

#ifdef HAVE_KQUEUE
private:
int kq_;
struct kevent filter_;
struct kevent event_;

#elif HAVE_INOTIFY
#endif

public:
static void init(STATE);

static FSEvent* create(STATE);

// Rubinius.primitive+ :fsevent_allocate
static FSEvent* allocate(STATE, Object* self);

// Rubinius.primitive :fsevent_watch_file
Object* watch_file(STATE, Fixnum* fd, String* path);
Object* watch_file(STATE, int fd, const char* path);

// Rubinius.primitive :fsevent_wait_for_event
Object* wait_for_event();

class Info : public TypeInfo {
public:
BASIC_TYPEINFO(TypeInfo)
};
};
}

#endif
34 changes: 19 additions & 15 deletions vm/console.cpp
Expand Up @@ -5,6 +5,7 @@

#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/fsevent.hpp"
#include "builtin/string.hpp"
#include "builtin/thread.hpp"

Expand Down Expand Up @@ -50,6 +51,7 @@ namespace rubinius {
, request_(state)
, response_(state)
, console_(state)
, fsevent_(state)
, request_fd_(-1)
, response_fd_(-1)
, request_exit_(false)
Expand Down Expand Up @@ -247,30 +249,32 @@ namespace rubinius {
request_fd_ = ::open("/tmp/rbx-console-request", O_CREAT | O_TRUNC | O_RDWR, 0666);
if(request_fd_ < 0) { puts("failed to open console request\n"); return; }

int kq = kqueue();
if(kq < 0) { puts("failed to get kqueue\n"); return; }
FSEvent* fsevent = FSEvent::create(state);
fsevent->watch_file(state, request_fd_, "/tmp/rbx-console-request");
fsevent_.set(fsevent);

struct kevent filter, event;
EV_SET(&filter, request_fd_, EVFILT_VNODE,
EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);
// int kq = kqueue();
// if(kq < 0) { puts("failed to get kqueue\n"); return; }

// struct kevent filter, event;
// EV_SET(&filter, request_fd_, EVFILT_VNODE,
// EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);

// const struct timespec timeout = { 0, 10000000 };

while(!request_exit_) {
int status = kevent(kq, &filter, 1, &event, 1, NULL);
Object* status = fsevent_.get()->wait_for_event();
// int status = kevent(kq, &filter, 1, &event, 1, NULL);

if(request_exit_) break;
if(status == 0) continue;
if(status < 0) perror("kevent");
if(status->nil_p()) continue;

if(event.fflags & NOTE_WRITE) {
char* request = read_request(state);
char* request = read_request(state);

if(request) {
utilities::thread::Mutex::LockGuard lg(list_lock_);
request_list_->push_back(request);
response_cond_.signal();
}
if(request) {
utilities::thread::Mutex::LockGuard lg(list_lock_);
request_list_->push_back(request);
response_cond_.signal();
}
}

Expand Down
2 changes: 2 additions & 0 deletions vm/console.hpp
Expand Up @@ -12,6 +12,7 @@
namespace rubinius {
class VM;
class State;
class FSEvent;
class Object;
class String;
class Thread;
Expand All @@ -27,6 +28,7 @@ namespace rubinius {
TypedRoot<Thread*> request_;
TypedRoot<Thread*> response_;
TypedRoot<Object*> console_;
TypedRoot<FSEvent*> fsevent_;

int request_fd_;
int response_fd_;
Expand Down
2 changes: 2 additions & 0 deletions vm/globals.hpp
Expand Up @@ -125,6 +125,7 @@ namespace rubinius {
TypedRoot<Class*> vm_class;
TypedRoot<Class*> atomic_ref;
TypedRoot<Class*> mirror;
TypedRoot<Class*> fsevent;

TypedRoot<Encoding*> usascii_encoding, utf8_encoding, ascii8bit_encoding;

Expand Down Expand Up @@ -253,6 +254,7 @@ namespace rubinius {
vm_class(&roots),
atomic_ref(&roots),
mirror(&roots),
fsevent(&roots),
usascii_encoding(&roots),
utf8_encoding(&roots),
ascii8bit_encoding(&roots)
Expand Down
2 changes: 2 additions & 0 deletions vm/ontology.cpp
Expand Up @@ -23,6 +23,7 @@
#include "builtin/executable.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/fsevent.hpp"
#include "builtin/io.hpp"
#include "builtin/iseq.hpp"
#include "builtin/list.hpp"
Expand Down Expand Up @@ -361,6 +362,7 @@ namespace rubinius {
Alias::init(state);
Randomizer::init(state);
Encoding::init(state);
FSEvent::init(state);
}

// @todo document all the sections of bootstrap_ontology
Expand Down

0 comments on commit 51e816c

Please sign in to comment.