Add opendir/releasedir support. Relieve ws thread CPU usage.

This commit is contained in:
Omar Rizwan 2018-11-29 09:53:03 -08:00
parent ed5419ae41
commit 90181466bd
2 changed files with 178 additions and 65 deletions

View file

@ -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();
});

View file

@ -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);
} }