mirror of
https://github.com/osnr/TabFS.git
synced 2024-06-15 20:25:18 +02:00
Add opendir/releasedir support. Relieve ws thread CPU usage.
This commit is contained in:
parent
ed5419ae41
commit
90181466bd
|
@ -1,25 +1,3 @@
|
|||
let ws;
|
||||
function tryConnect() {
|
||||
ws = new WebSocket("ws://localhost:8888");
|
||||
updateToolbarIcon();
|
||||
ws.onopen = ws.onclose = updateToolbarIcon;
|
||||
}
|
||||
|
||||
function updateToolbarIcon() {
|
||||
if (ws && ws.readyState == 1) { // OPEN
|
||||
chrome.browserAction.setBadgeBackgroundColor({color: 'blue'});
|
||||
chrome.browserAction.setBadgeText({text: 'f'});
|
||||
} else {
|
||||
chrome.browserAction.setBadgeBackgroundColor({color: 'red'});
|
||||
chrome.browserAction.setBadgeText({text: '!'});
|
||||
}
|
||||
}
|
||||
|
||||
tryConnect();
|
||||
chrome.browserAction.onClicked.addListener(function() {
|
||||
tryConnect();
|
||||
});
|
||||
|
||||
const unix = {
|
||||
EPERM: 1,
|
||||
ENOENT: 2,
|
||||
|
@ -93,6 +71,13 @@ function pathComponent(path, i) {
|
|||
|
||||
const router = {
|
||||
"tabs": {
|
||||
/* "last-focused": {
|
||||
* // FIXME: symlink to tab by id.
|
||||
* async readlink() {
|
||||
* return "../windows/last-focused/selected-tab"
|
||||
* }
|
||||
* },
|
||||
*/
|
||||
"by-id": {
|
||||
async readdir() {
|
||||
const tabs = await queryTabs();
|
||||
|
@ -112,6 +97,21 @@ const router = {
|
|||
return (tab.title + "\n").substr(offset, size);
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
async open(path) {
|
||||
const debuggee = {tabId: parseInt(pathComponent(path, -2))};
|
||||
await new Promise(resolve => chrome.debugger.attach(debuggee, "1.2", resolve));
|
||||
chrome.debugger.sendCommand(debuggee, "Page.getResourceTree", {}, function(result) {
|
||||
console.log(result);
|
||||
});
|
||||
},
|
||||
async read(path) {
|
||||
|
||||
},
|
||||
async close(path) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,16 +148,10 @@ async function getattr(path) {
|
|||
}
|
||||
}
|
||||
|
||||
async function readdir(path) {
|
||||
let route = findRoute(path);
|
||||
if (route.readdir) return route.readdir(path);
|
||||
return Object.keys(route);
|
||||
}
|
||||
|
||||
async function open(path) {
|
||||
let route = findRoute(path);
|
||||
if (route.open) return route.open(path);
|
||||
else return 0; // empty fd
|
||||
else return 0; // empty fh
|
||||
}
|
||||
|
||||
async function read(path, fh, size, offset) {
|
||||
|
@ -170,7 +164,23 @@ async function release(path, fh) {
|
|||
if (route.release) return route.release(path, fh);
|
||||
}
|
||||
|
||||
ws.onmessage = async function(event) {
|
||||
async function opendir(path) {
|
||||
let route = findRoute(path);
|
||||
if (route.opendir) return route.opendir(path);
|
||||
else return 0; // empty fh
|
||||
}
|
||||
async function readdir(path) {
|
||||
let route = findRoute(path);
|
||||
if (route.readdir) return route.readdir(path);
|
||||
return Object.keys(route);
|
||||
}
|
||||
async function releasedir(path) {
|
||||
let route = findRoute(path);
|
||||
if (route.releasedir) return route.releasedir(path);
|
||||
}
|
||||
|
||||
let ws;
|
||||
async function onmessage(event) {
|
||||
const req = JSON.parse(event.data);
|
||||
|
||||
let response = { op: req.op, error: unix.EIO };
|
||||
|
@ -190,12 +200,6 @@ ws.onmessage = async function(event) {
|
|||
fh: await open(req.path)
|
||||
};
|
||||
|
||||
} else if (req.op === 'readdir') {
|
||||
response = {
|
||||
op: 'readdir',
|
||||
entries: [".", "..", ...(await readdir(req.path))]
|
||||
};
|
||||
|
||||
} else if (req.op === 'read') {
|
||||
const buf = await read(req.path, req.fh, req.size, req.offset)
|
||||
response = {
|
||||
|
@ -208,6 +212,22 @@ ws.onmessage = async function(event) {
|
|||
response = {
|
||||
op: 'release'
|
||||
};
|
||||
|
||||
} else if (req.op === 'opendir') {
|
||||
response = {
|
||||
op: 'opendir',
|
||||
fh: await opendir(req.path)
|
||||
};
|
||||
|
||||
} else if (req.op === 'readdir') {
|
||||
response = {
|
||||
op: 'readdir',
|
||||
entries: [".", "..", ...(await readdir(req.path))]
|
||||
};
|
||||
|
||||
} else if (req.op === 'releasedir') {
|
||||
await releasedir(req.path, req.fh);
|
||||
response = { op: 'releasedir' };
|
||||
}
|
||||
} catch (e) {
|
||||
response = {
|
||||
|
@ -220,3 +240,25 @@ ws.onmessage = async function(event) {
|
|||
response.id = req.id;
|
||||
ws.send(JSON.stringify(response));
|
||||
};
|
||||
|
||||
function tryConnect() {
|
||||
ws = new WebSocket("ws://localhost:8888");
|
||||
updateToolbarIcon();
|
||||
ws.onopen = ws.onclose = updateToolbarIcon;
|
||||
ws.onmessage = onmessage;
|
||||
}
|
||||
|
||||
function updateToolbarIcon() {
|
||||
if (ws && ws.readyState == 1) { // OPEN
|
||||
chrome.browserAction.setBadgeBackgroundColor({color: 'blue'});
|
||||
chrome.browserAction.setBadgeText({text: 'f'});
|
||||
} else {
|
||||
chrome.browserAction.setBadgeBackgroundColor({color: 'red'});
|
||||
chrome.browserAction.setBadgeText({text: '!'});
|
||||
}
|
||||
}
|
||||
|
||||
tryConnect();
|
||||
chrome.browserAction.onClicked.addListener(function() {
|
||||
tryConnect();
|
||||
});
|
||||
|
|
129
fs/hello.c
129
fs/hello.c
|
@ -63,6 +63,7 @@ static request_id enqueue_request(cJSON *req) {
|
|||
|
||||
/* printf("%s\n", queue[id].request); */
|
||||
|
||||
pthread_cond_signal(&queue_cv);
|
||||
pthread_mutex_unlock(&queue_mutex);
|
||||
|
||||
return id;
|
||||
|
@ -163,6 +164,24 @@ hello_getattr(const char *path, struct stat *stbuf)
|
|||
});
|
||||
}
|
||||
|
||||
static int
|
||||
hello_readlink(const char *path, char *buf, size_t size)
|
||||
{
|
||||
MAKE_REQ("readlink", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
}, {
|
||||
cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
|
||||
// FIXME: fix
|
||||
char *resp_buf = cJSON_GetStringValue(resp_buf_item);
|
||||
size_t resp_buf_len = strlen(resp_buf);
|
||||
size = resp_buf_len < size ? resp_buf_len : size;
|
||||
|
||||
memcpy(buf, resp_buf, size);
|
||||
|
||||
ret = size;
|
||||
});
|
||||
}
|
||||
|
||||
static int
|
||||
hello_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
|
@ -177,6 +196,56 @@ hello_open(const char *path, struct fuse_file_info *fi)
|
|||
});
|
||||
}
|
||||
|
||||
static int
|
||||
hello_read(const char *path, char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
MAKE_REQ("read", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
cJSON_AddNumberToObject(req, "size", size);
|
||||
cJSON_AddNumberToObject(req, "offset", offset);
|
||||
|
||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
||||
}, {
|
||||
cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
|
||||
if (!resp_buf_item) return -EIO;
|
||||
|
||||
char *resp_buf = cJSON_GetStringValue(resp_buf_item);
|
||||
if (!resp_buf) return -EIO;
|
||||
|
||||
size_t resp_buf_len = strlen(resp_buf);
|
||||
size = resp_buf_len < size ? resp_buf_len : size;
|
||||
|
||||
memcpy(buf, resp_buf, size);
|
||||
|
||||
ret = size;
|
||||
});
|
||||
}
|
||||
|
||||
static int hello_release(const char *path, struct fuse_file_info *fi) {
|
||||
MAKE_REQ("release", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||
}, {
|
||||
ret = 0;
|
||||
});
|
||||
}
|
||||
|
||||
static int
|
||||
hello_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
MAKE_REQ("opendir", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
||||
}, {
|
||||
cJSON *fh_item = cJSON_GetObjectItemCaseSensitive(resp, "fh");
|
||||
if (fh_item) fi->fh = fh_item->valueint;
|
||||
|
||||
ret = 0;
|
||||
});
|
||||
}
|
||||
|
||||
static int
|
||||
hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||
off_t offset, struct fuse_file_info *fi)
|
||||
|
@ -196,30 +265,9 @@ hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
}
|
||||
|
||||
static int
|
||||
hello_read(const char *path, char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
hello_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
MAKE_REQ("read", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
cJSON_AddNumberToObject(req, "size", size);
|
||||
cJSON_AddNumberToObject(req, "offset", offset);
|
||||
|
||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||
cJSON_AddNumberToObject(req, "flags", fi->flags);
|
||||
}, {
|
||||
cJSON *resp_buf_item = cJSON_GetObjectItemCaseSensitive(resp, "buf");
|
||||
char *resp_buf = cJSON_GetStringValue(resp_buf_item);
|
||||
size_t resp_buf_len = strlen(resp_buf);
|
||||
size = resp_buf_len < size ? resp_buf_len : size;
|
||||
|
||||
memcpy(buf, resp_buf, size);
|
||||
|
||||
ret = size;
|
||||
});
|
||||
}
|
||||
|
||||
static int hello_release(const char *path, struct fuse_file_info *fi) {
|
||||
MAKE_REQ("release", {
|
||||
MAKE_REQ("releasedir", {
|
||||
cJSON_AddStringToObject(req, "path", path);
|
||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||
}, {
|
||||
|
@ -228,11 +276,15 @@ static int hello_release(const char *path, struct fuse_file_info *fi) {
|
|||
}
|
||||
|
||||
static struct fuse_operations hello_filesystem_operations = {
|
||||
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
||||
.open = hello_open, /* To enforce read-only access. */
|
||||
.read = hello_read, /* To provide file content. */
|
||||
.release = hello_release,
|
||||
.readdir = hello_readdir, /* To provide directory listing. */
|
||||
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
||||
.readlink = hello_readlink,
|
||||
.open = hello_open, /* To enforce read-only access. */
|
||||
.read = hello_read, /* To provide file content. */
|
||||
.release = hello_release,
|
||||
|
||||
.opendir = hello_opendir,
|
||||
.readdir = hello_readdir, /* To provide directory listing. */
|
||||
.releasedir = hello_releasedir
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -339,6 +391,24 @@ test_log(const char* text)
|
|||
DEBUG("[debug] %s\n", text);
|
||||
}
|
||||
|
||||
int check_io_demand() {
|
||||
if (con == NULL) return 1;
|
||||
|
||||
for (request_id id = 0; id < REQUEST_RESPONSE_QUEUE_SIZE; id++) {
|
||||
if (queue[id].state == SEND_REQUEST || queue[id].state == RECEIVE_RESPONSE) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void await_io_demand() {
|
||||
pthread_mutex_lock(&queue_mutex);
|
||||
while (!check_io_demand()) {
|
||||
pthread_cond_wait(&queue_cv, &queue_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&queue_mutex);
|
||||
}
|
||||
|
||||
void *websocket_main(void *threadid)
|
||||
{
|
||||
void *memory = NULL;
|
||||
|
@ -365,6 +435,8 @@ void *websocket_main(void *threadid)
|
|||
|
||||
printf("Awaiting WebSocket connection from Chrome extension.\n");
|
||||
for (;;) {
|
||||
await_io_demand();
|
||||
|
||||
send_any_enqueued_requests();
|
||||
|
||||
wby_update(&server);
|
||||
|
@ -384,5 +456,4 @@ main(int argc, char **argv)
|
|||
pthread_t websocket_thread;
|
||||
pthread_create(&websocket_thread, NULL, websocket_main, NULL);
|
||||
return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue