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 = {
|
const unix = {
|
||||||
EPERM: 1,
|
EPERM: 1,
|
||||||
ENOENT: 2,
|
ENOENT: 2,
|
||||||
|
@ -93,6 +71,13 @@ function pathComponent(path, i) {
|
||||||
|
|
||||||
const router = {
|
const router = {
|
||||||
"tabs": {
|
"tabs": {
|
||||||
|
/* "last-focused": {
|
||||||
|
* // FIXME: symlink to tab by id.
|
||||||
|
* async readlink() {
|
||||||
|
* return "../windows/last-focused/selected-tab"
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
*/
|
||||||
"by-id": {
|
"by-id": {
|
||||||
async readdir() {
|
async readdir() {
|
||||||
const tabs = await queryTabs();
|
const tabs = await queryTabs();
|
||||||
|
@ -112,6 +97,21 @@ const router = {
|
||||||
return (tab.title + "\n").substr(offset, size);
|
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) {
|
async function open(path) {
|
||||||
let route = findRoute(path);
|
let route = findRoute(path);
|
||||||
if (route.open) return route.open(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) {
|
async function read(path, fh, size, offset) {
|
||||||
|
@ -170,7 +164,23 @@ async function release(path, fh) {
|
||||||
if (route.release) return route.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);
|
const req = JSON.parse(event.data);
|
||||||
|
|
||||||
let response = { op: req.op, error: unix.EIO };
|
let response = { op: req.op, error: unix.EIO };
|
||||||
|
@ -190,12 +200,6 @@ ws.onmessage = async function(event) {
|
||||||
fh: await open(req.path)
|
fh: await open(req.path)
|
||||||
};
|
};
|
||||||
|
|
||||||
} else if (req.op === 'readdir') {
|
|
||||||
response = {
|
|
||||||
op: 'readdir',
|
|
||||||
entries: [".", "..", ...(await readdir(req.path))]
|
|
||||||
};
|
|
||||||
|
|
||||||
} else if (req.op === 'read') {
|
} else if (req.op === 'read') {
|
||||||
const buf = await read(req.path, req.fh, req.size, req.offset)
|
const buf = await read(req.path, req.fh, req.size, req.offset)
|
||||||
response = {
|
response = {
|
||||||
|
@ -208,6 +212,22 @@ ws.onmessage = async function(event) {
|
||||||
response = {
|
response = {
|
||||||
op: 'release'
|
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) {
|
} catch (e) {
|
||||||
response = {
|
response = {
|
||||||
|
@ -220,3 +240,25 @@ ws.onmessage = async function(event) {
|
||||||
response.id = req.id;
|
response.id = req.id;
|
||||||
ws.send(JSON.stringify(response));
|
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();
|
||||||
|
});
|
||||||
|
|
119
fs/hello.c
119
fs/hello.c
|
@ -63,6 +63,7 @@ static request_id enqueue_request(cJSON *req) {
|
||||||
|
|
||||||
/* printf("%s\n", queue[id].request); */
|
/* printf("%s\n", queue[id].request); */
|
||||||
|
|
||||||
|
pthread_cond_signal(&queue_cv);
|
||||||
pthread_mutex_unlock(&queue_mutex);
|
pthread_mutex_unlock(&queue_mutex);
|
||||||
|
|
||||||
return id;
|
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
|
static int
|
||||||
hello_open(const char *path, struct fuse_file_info *fi)
|
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
|
static int
|
||||||
hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
off_t offset, struct fuse_file_info *fi)
|
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
|
static int
|
||||||
hello_read(const char *path, char *buf, size_t size, off_t offset,
|
hello_releasedir(const char *path, struct fuse_file_info *fi)
|
||||||
struct fuse_file_info *fi)
|
|
||||||
{
|
{
|
||||||
MAKE_REQ("read", {
|
MAKE_REQ("releasedir", {
|
||||||
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", {
|
|
||||||
cJSON_AddStringToObject(req, "path", path);
|
cJSON_AddStringToObject(req, "path", path);
|
||||||
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
cJSON_AddNumberToObject(req, "fh", fi->fh);
|
||||||
}, {
|
}, {
|
||||||
|
@ -229,10 +277,14 @@ static int hello_release(const char *path, struct fuse_file_info *fi) {
|
||||||
|
|
||||||
static struct fuse_operations hello_filesystem_operations = {
|
static struct fuse_operations hello_filesystem_operations = {
|
||||||
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
.getattr = hello_getattr, /* To provide size, permissions, etc. */
|
||||||
|
.readlink = hello_readlink,
|
||||||
.open = hello_open, /* To enforce read-only access. */
|
.open = hello_open, /* To enforce read-only access. */
|
||||||
.read = hello_read, /* To provide file content. */
|
.read = hello_read, /* To provide file content. */
|
||||||
.release = hello_release,
|
.release = hello_release,
|
||||||
|
|
||||||
|
.opendir = hello_opendir,
|
||||||
.readdir = hello_readdir, /* To provide directory listing. */
|
.readdir = hello_readdir, /* To provide directory listing. */
|
||||||
|
.releasedir = hello_releasedir
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -339,6 +391,24 @@ test_log(const char* text)
|
||||||
DEBUG("[debug] %s\n", 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 *websocket_main(void *threadid)
|
||||||
{
|
{
|
||||||
void *memory = NULL;
|
void *memory = NULL;
|
||||||
|
@ -365,6 +435,8 @@ void *websocket_main(void *threadid)
|
||||||
|
|
||||||
printf("Awaiting WebSocket connection from Chrome extension.\n");
|
printf("Awaiting WebSocket connection from Chrome extension.\n");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
await_io_demand();
|
||||||
|
|
||||||
send_any_enqueued_requests();
|
send_any_enqueued_requests();
|
||||||
|
|
||||||
wby_update(&server);
|
wby_update(&server);
|
||||||
|
@ -384,5 +456,4 @@ main(int argc, char **argv)
|
||||||
pthread_t websocket_thread;
|
pthread_t websocket_thread;
|
||||||
pthread_create(&websocket_thread, NULL, websocket_main, NULL);
|
pthread_create(&websocket_thread, NULL, websocket_main, NULL);
|
||||||
return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
|
return fuse_main(argc, argv, &hello_filesystem_operations, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue