From 2f9d912819779b2e06fabacc97453cf8aaa7d99d Mon Sep 17 00:00:00 2001 From: Eric Yen Date: Sat, 22 Aug 2015 12:00:38 -0400 Subject: [PATCH] add multi forget for fuse --- .travis.yml | 4 +++ Gruntfile.js | 2 +- binding.gyp | 6 ++-- fuse.js | 17 ++++++++- src/filesystem.cc | 88 +++++++++++++++++++++++++++++++++++++++++++--- src/filesystem.h | 85 +++++++++++++++++++++++++------------------- src/forget_data.cc | 51 +++++++++++++++++++++++++++ src/forget_data.h | 36 +++++++++++++++++++ src/node_fuse.cc | 7 ++++ 9 files changed, 252 insertions(+), 44 deletions(-) create mode 100644 src/forget_data.cc create mode 100644 src/forget_data.h diff --git a/.travis.yml b/.travis.yml index b09afa5..c9fa970 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,10 @@ before_install: - npm/.bin/npm install -g node-gyp-install - npm/.bin/npm install -g mocha - node-gyp-install + - wget http://downloads.sourceforge.net/project/fuse/fuse-2.X/2.9.4/fuse-2.9.4.tar.gz + - tar xf fuse-2.9.4.tar.gz + - mkdir include + - cp fuse-2.9.4/include/*.h include install: - npm/.bin/npm install diff --git a/Gruntfile.js b/Gruntfile.js index 1bed396..11316cb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,7 @@ module.exports = function (grunt){ }, scripts:{ files:['src/*.cc', 'src/*.h', 'binding.gyp'], - tasks:['gyp', 'mochaTest'] + tasks:['gyp','mochaTest'] }, example_test:{ files:['test/test_example.js', 'examples/example.js'], diff --git a/binding.gyp b/binding.gyp index d2b6c09..0c69246 100644 --- a/binding.gyp +++ b/binding.gyp @@ -6,15 +6,17 @@ "src/file_info.cc", "src/filesystem.cc", "src/node_fuse.cc", - "src/reply.cc", + "src/reply.cc", + 'src/forget_data.cc' ], "include_dirs": [ + './include', ' ring_buffer(__RING_SIZE__); @@ -195,6 +196,14 @@ namespace NodeFuse { break; case _FUSE_OPS_SETLK_: break; + case _FUSE_OPS_MULTI_FORGET_: + #if FUSE_USE_VERSION > 28 + #ifndef __APPLE__ + RemoteMultiForget(value->req, value->size, static_cast(value->userdata) ); + #endif + #endif + break; + case _FUSE_OPS_BMAP_: break; } @@ -243,6 +252,9 @@ namespace NodeFuse { fuse_ops.releasedir = FileSystem::ReleaseDir; fuse_ops.fsyncdir = FileSystem::FSyncDir; fuse_ops.statfs = FileSystem::StatFs; + #if FUSE_USE_VERSION > 28 + fuse_ops.forget_multi = FileSystem::MultiForget; + #endif // fuse_ops.setxattr = FileSystem::SetXAttr; // fuse_ops.getxattr = FileSystem::GetXAttr; // fuse_ops.listxattr = FileSystem::ListXAttr; @@ -430,6 +442,68 @@ namespace NodeFuse { //scope.Close(Undefined()); } + + #if FUSE_USE_VERSION > 28 + void FileSystem::MultiForget(fuse_req_t req, + size_t count, + struct fuse_forget_data *forget){ + struct fuse_cmd *value; + + if( ring_buffer.producer_claim_next(&value) != 0){ + printf("ring buffer was full while trying to enqueue multi forget\n"); + return; + } + + value->op = _FUSE_OPS_MULTI_FORGET_; + value->req = req; + value->size = count; + value->userdata = (void *) forget; + + ring_buffer.producer_publish();//(producers[ 0/*_FUSE_OPS_FORGET_*/]); + // uv_async_send(&uv_async_handle); + + } + void FileSystem::RemoteMultiForget(fuse_req_t req, + size_t count, + struct fuse_forget_data *forget_all) { + Nan::HandleScope scope;; + Fuse* fuse = static_cast(fuse_req_userdata(req)); + Local fsobj = Nan::New(fuse->fsobj); + Local vforget = fsobj->Get(Nan::New("multiforget").ToLocalChecked()); + Local forget = Local::Cast(vforget); + + Local context = RequestContextToObject(fuse_req_ctx(req))->ToObject(); + Local data = Nan::New(count); + + for( uint i = 0; i < count; i++){ + ForgetData *forget_data = new ForgetData(); + // forget_data->fd = &( forget_all[i] ); + Local infoObj = Nan::NewInstance(Nan::New(forget_data->constructor)).ToLocalChecked();//->GetFunction()->NewInstance(); + data->Set(i, infoObj); + } + + Reply* reply = new Reply(); + reply->request = req; + Local replyObj = Nan::NewInstance( Nan::New(reply->constructor)).ToLocalChecked();//->GetFunction()->NewInstance(); + reply->Wrap(replyObj); + + Local argv[3] = {context, data, replyObj}; + + Nan::TryCatch try_catch; + + forget->Call(fsobj, 3, argv); + + if (try_catch.HasCaught()) { + Nan::FatalException(try_catch); + } + + fuse_reply_none(req); + //scope.Close(Undefined()); + + } + #endif //FUSE_USE_VERSION + + void FileSystem::Forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) { @@ -453,7 +527,7 @@ namespace NodeFuse { void FileSystem::RemoteForget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup) { - Nan::HandleScope scope;; + // Nan::HandleScope scope;; Fuse* fuse = static_cast(fuse_req_userdata(req)); Local fsobj = Nan::New(fuse->fsobj); Local vforget = fsobj->Get(Nan::New("forget").ToLocalChecked()); @@ -463,7 +537,13 @@ namespace NodeFuse { Local inode = Nan::New(ino); Local nlookup_ = Nan::New( (int) nlookup); - Local argv[3] = {context, inode, nlookup_}; + Reply* reply = new Reply(); + reply->request = req; + Local replyObj = Nan::NewInstance( Nan::New(reply->constructor)).ToLocalChecked();//->GetFunction()->NewInstance(); + reply->Wrap(replyObj); + + + Local argv[4] = {context, inode, nlookup_, replyObj}; Nan::TryCatch try_catch; @@ -473,7 +553,7 @@ namespace NodeFuse { Nan::FatalException(try_catch); } - fuse_reply_none(req); + // fuse_reply_none(req); //scope.Close(Undefined()); } diff --git a/src/filesystem.h b/src/filesystem.h index 5b8b284..08a4e81 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -7,43 +7,45 @@ #include "node_fuse.h" #include #include -#define _FUSE_OPS_LOOKUP_ 0 -#define _FUSE_OPS_GETATTR_ 1 -#define _FUSE_OPS_OPEN_ 2 -#define _FUSE_OPS_READ_ 3 -#define _FUSE_OPS_READDIR_ 4 -#define _FUSE_OPS_INIT_ 5 -#define _FUSE_OPS_DESTROY_ 6 -#define _FUSE_OPS_FORGET_ 7 -#define _FUSE_OPS_SETATTR_ 8 -#define _FUSE_OPS_READLINK_ 9 -#define _FUSE_OPS_MKNOD_ 10 -#define _FUSE_OPS_MKDIR_ 11 -#define _FUSE_OPS_UNLINK_ 12 -#define _FUSE_OPS_RMDIR_ 13 -#define _FUSE_OPS_SYMLINK_ 14 -#define _FUSE_OPS_RENAME_ 15 -#define _FUSE_OPS_LINK_ 16 -#define _FUSE_OPS_WRITE_ 17 -#define _FUSE_OPS_FLUSH_ 18 -#define _FUSE_OPS_RELEASE_ 19 -#define _FUSE_OPS_FSYNC_ 20 -#define _FUSE_OPS_OPENDIR_ 21 -#define _FUSE_OPS_RELEASEDIR_ 22 -#define _FUSE_OPS_FSYNCDIR_ 23 -#define _FUSE_OPS_STATFS_ 24 -#define _FUSE_OPS_SETXATTR_ 25 -#define _FUSE_OPS_GETXATTR_ 26 -#define _FUSE_OPS_LISTXATTR_ 27 -#define _FUSE_OPS_REMOVEXATTR_ 28 -#define _FUSE_OPS_ACCESS_ 29 -#define _FUSE_OPS_CREATE_ 30 -#define _FUSE_OPS_GETLK_ 31 -#define _FUSE_OPS_SETLK_ 32 -#define _FUSE_OPS_BMAP_ 33 -#define _NUMBER_OF_FUSE_OPERATIONS_ 33 +#define _FUSE_OPS_LOOKUP_ 0 +#define _FUSE_OPS_GETATTR_ 1 +#define _FUSE_OPS_OPEN_ 2 +#define _FUSE_OPS_READ_ 3 +#define _FUSE_OPS_READDIR_ 4 +#define _FUSE_OPS_INIT_ 5 +#define _FUSE_OPS_DESTROY_ 6 +#define _FUSE_OPS_FORGET_ 7 +#define _FUSE_OPS_SETATTR_ 8 +#define _FUSE_OPS_READLINK_ 9 +#define _FUSE_OPS_MKNOD_ 10 +#define _FUSE_OPS_MKDIR_ 11 +#define _FUSE_OPS_UNLINK_ 12 +#define _FUSE_OPS_RMDIR_ 13 +#define _FUSE_OPS_SYMLINK_ 14 +#define _FUSE_OPS_RENAME_ 15 +#define _FUSE_OPS_LINK_ 16 +#define _FUSE_OPS_WRITE_ 17 +#define _FUSE_OPS_FLUSH_ 18 +#define _FUSE_OPS_RELEASE_ 19 +#define _FUSE_OPS_FSYNC_ 20 +#define _FUSE_OPS_OPENDIR_ 21 +#define _FUSE_OPS_RELEASEDIR_ 22 +#define _FUSE_OPS_FSYNCDIR_ 23 +#define _FUSE_OPS_STATFS_ 24 +#define _FUSE_OPS_SETXATTR_ 25 +#define _FUSE_OPS_GETXATTR_ 26 +#define _FUSE_OPS_LISTXATTR_ 27 +#define _FUSE_OPS_REMOVEXATTR_ 28 +#define _FUSE_OPS_ACCESS_ 29 +#define _FUSE_OPS_CREATE_ 30 +#define _FUSE_OPS_GETLK_ 31 +#define _FUSE_OPS_SETLK_ 32 +#define _FUSE_OPS_BMAP_ 33 +#define _FUSE_OPS_BMAP_ 33 +#define _FUSE_OPS_MULTI_FORGET_ 34 + +#define _NUMBER_OF_FUSE_OPERATIONS_ 34 -#define _FUSE_UNMOUNT_ 34 #define __RING_SIZE__ 256 extern uv_async_t uv_async_handle; @@ -94,6 +96,11 @@ namespace NodeFuse { static void Forget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + #if FUSE_USE_VERSION > 28 + static void MultiForget(fuse_req_t req, + size_t count, + struct fuse_forget_data *forget_all); + #endif static void GetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi); @@ -243,6 +250,12 @@ namespace NodeFuse { static void RemoteForget(fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + #if FUSE_USE_VERSION > 28 + static void RemoteMultiForget(fuse_req_t req, + size_t count, + struct fuse_forget_data *forget_all); + #endif + static void RemoteGetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info fi); diff --git a/src/forget_data.cc b/src/forget_data.cc new file mode 100644 index 0000000..a2d6a1d --- /dev/null +++ b/src/forget_data.cc @@ -0,0 +1,51 @@ +#include "forget_data.h" +#if FUSE_USE_VERSION > 28 + +namespace NodeFuse { + + Nan::Persistent ForgetData::constructor; + + NAN_METHOD(ForgetData::New){ + if (info.IsConstructCall()) { + ForgetData *fi = new ForgetData(); + Local obj = info.This(); + fi->Wrap(obj); + info.GetReturnValue().Set( obj ); + } else { + Local cons = Nan::New(constructor); + info.GetReturnValue().Set(cons->NewInstance()); + } + + } + void ForgetData::Initialize(Handle target){ + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("ForgetData").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Local object_tmpl = tpl->InstanceTemplate(); + + object_tmpl->SetInternalFieldCount(1); + + Nan::SetAccessor(object_tmpl, Nan::New("inode").ToLocalChecked(), ForgetData::GetIno); + Nan::SetAccessor(object_tmpl, Nan::New("nlookup").ToLocalChecked(), ForgetData::GetNLookup); + constructor.Reset(tpl->GetFunction()); + + } + ForgetData::ForgetData() : ObjectWrap() {} + ForgetData::~ForgetData() {} + void ForgetData::GetIno(v8::Local property, + const Nan::PropertyCallbackInfo& info) + { + ForgetData *forget_data = ObjectWrap::Unwrap(info.This()); + info.GetReturnValue().Set( Nan::New(static_cast(forget_data->fd->ino))); + } + + void ForgetData::GetNLookup(v8::Local property, + const Nan::PropertyCallbackInfo& info) + { + ForgetData *forget_data = ObjectWrap::Unwrap(info.This()); + info.GetReturnValue().Set( Nan::New( static_cast(forget_data->fd->nlookup)) ); + } + +} +#endif diff --git a/src/forget_data.h b/src/forget_data.h new file mode 100644 index 0000000..d1fa50d --- /dev/null +++ b/src/forget_data.h @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef SRC_FORGET_DATA_H_ +#define SRC_FORGET_DATA_H_ + +#if FUSE_USE_VERSION > 28 +#include "node_fuse.h" + +namespace NodeFuse { + class ForgetData : public ObjectWrap { + friend class FileSystem; + public: + static void Initialize(Handle target); + + ForgetData(); + virtual ~ForgetData(); + struct fuse_forget_data *fd; + static Nan::Persistent constructor; + static Nan::Persistent constructor_template; + static NAN_METHOD(New); + protected: + static void GetIno(v8::Local property, + const Nan::PropertyCallbackInfo& info) ; + static void GetNLookup(v8::Local property, + const Nan::PropertyCallbackInfo& info) ; + + + }; +} //namespace NodeFuse + + +#endif // if FUSE_USE_VERSION + +#endif // ifdef SRC_FILE_INFO_H diff --git a/src/node_fuse.cc b/src/node_fuse.cc index c5b330d..21a0da1 100644 --- a/src/node_fuse.cc +++ b/src/node_fuse.cc @@ -6,6 +6,7 @@ #include "reply.h" #include "file_info.h" #include "filesystem.h" +#include "forget_data.h" namespace NodeFuse { //stat struct symbols @@ -17,6 +18,12 @@ namespace NodeFuse { Reply::Initialize(target); FileInfo::Initialize(target); + #if FUSE_USE_VERSION > 28 + #ifndef __APPLE__ + ForgetData::Initialize(target); + #endif + #endif + Nan::Set(target , Nan::New("version").ToLocalChecked(), Nan::New(NODE_FUSE_VERSION).ToLocalChecked());