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

View file

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