[mod_magnet] lighty.stat now returns userdata obj
lighty.stat now returns a userdata object instead of a populated table. The userdata object provides methods to access the (stat_cache_entry *) stored in the userdata object. (This approach is often much faster than populating the table of stat entries, as the fields get copied on demand (upon use) into lua types.)personal/stbuehler/tests-path
parent
bf05943258
commit
188248d238
264
src/mod_magnet.c
264
src/mod_magnet.c
|
@ -343,79 +343,200 @@ static int magnet_print(lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int magnet_stat_field(lua_State *L) {
|
||||
if (lua_gettop(L) != 2)
|
||||
return 0; /*(should not happen; __index method in protected metatable)*/
|
||||
|
||||
stat_cache_entry * const sce = *(stat_cache_entry **)lua_touserdata(L, -2);
|
||||
const_buffer k = magnet_checkconstbuffer(L, -1);
|
||||
switch (k.ptr[0]) {
|
||||
case 'c': { /* content-type */
|
||||
if (0 != strcmp(k.ptr, "content-type")) break;
|
||||
request_st * const r = magnet_get_request(L);
|
||||
const buffer *content_type = stat_cache_content_type_get(sce, r);
|
||||
if (content_type && !buffer_is_blank(content_type))
|
||||
lua_pushlstring(L, BUF_PTR_LEN(content_type));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
case 'e': { /* etag */
|
||||
if (0 != strcmp(k.ptr, "etag")) break;
|
||||
request_st * const r = magnet_get_request(L);
|
||||
const buffer *etag = stat_cache_etag_get(sce, r->conf.etag_flags);
|
||||
if (etag && !buffer_is_blank(etag))
|
||||
lua_pushlstring(L, BUF_PTR_LEN(etag));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
case 'i': /* is_* */
|
||||
if (k.len < 4) break;
|
||||
switch (k.ptr[3]) {
|
||||
case 'b': /* is_block */
|
||||
if (0 == strcmp(k.ptr, "is_block")) {
|
||||
lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'c': /* is_char */
|
||||
if (0 == strcmp(k.ptr, "is_char")) {
|
||||
lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'd': /* is_dir */
|
||||
if (0 == strcmp(k.ptr, "is_dir")) {
|
||||
lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'f': /* is_file is_fifo */
|
||||
if (0 == strcmp(k.ptr, "is_file")) {
|
||||
lua_pushboolean(L, S_ISREG(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
if (0 == strcmp(k.ptr, "is_fifo")) {
|
||||
lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'l': /* is_link */
|
||||
if (0 == strcmp(k.ptr, "is_link")) {
|
||||
lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 's': /* is_socket */
|
||||
if (0 == strcmp(k.ptr, "is_socket")) {
|
||||
lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 's': /* st_* */
|
||||
if (k.len < 4) break;
|
||||
switch (k.ptr[3]) {
|
||||
case 'a': /* st_atime */
|
||||
if (0 == strcmp(k.ptr, "st_atime")) {
|
||||
lua_pushinteger(L, TIME64_CAST(sce->st.st_atime));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'c': /* st_ctime */
|
||||
if (0 == strcmp(k.ptr, "st_ctime")) {
|
||||
lua_pushinteger(L, TIME64_CAST(sce->st.st_ctime));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'i': /* st_ino */
|
||||
if (0 == strcmp(k.ptr, "st_ino")) {
|
||||
lua_pushinteger(L, sce->st.st_ino);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'm': /* st_mtime st_mode */
|
||||
if (0 == strcmp(k.ptr, "st_mtime")) {
|
||||
lua_pushinteger(L, TIME64_CAST(sce->st.st_mtime));
|
||||
return 1;
|
||||
}
|
||||
if (0 == strcmp(k.ptr, "st_mode")) {
|
||||
lua_pushinteger(L, sce->st.st_mode);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'g': /* st_gid */
|
||||
if (0 == strcmp(k.ptr, "st_gid")) {
|
||||
lua_pushinteger(L, sce->st.st_gid);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 's': /* st_size */
|
||||
if (0 == strcmp(k.ptr, "st_size")) {
|
||||
lua_pushinteger(L, sce->st.st_size);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'u': /* st_uid */
|
||||
if (0 == strcmp(k.ptr, "st_uid")) {
|
||||
lua_pushinteger(L, sce->st.st_uid);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lua_pushliteral(L, "stat[\"field\"] invalid: ");
|
||||
lua_pushvalue(L, -2); /* field */
|
||||
lua_concat(L, 2);
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
__attribute_cold__
|
||||
static int magnet_stat_pairs_noimpl_iter(lua_State *L) {
|
||||
request_st * const r = magnet_get_request(L);
|
||||
log_error(r->conf.errh, __FILE__, __LINE__,
|
||||
"(lua) pairs() not implemented on lighty.stat object; "
|
||||
"returning empty iter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
__attribute_cold__
|
||||
static int magnet_stat_pairs_noimpl(lua_State *L) {
|
||||
lua_pushcclosure(L, magnet_stat_pairs_noimpl_iter, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void magnet_stat_metatable(lua_State *L) {
|
||||
if (luaL_newmetatable(L, "lighty.stat")) { /* (sp += 1) */
|
||||
lua_pushcfunction(L, magnet_stat_field); /* (sp += 1) */
|
||||
lua_setfield(L, -2, "__index"); /* (sp -= 1) */
|
||||
lua_pushcfunction(L, magnet_newindex_readonly); /* (sp += 1) */
|
||||
lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
|
||||
lua_pushcfunction(L, magnet_stat_pairs_noimpl); /* (sp += 1) */
|
||||
lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */
|
||||
lua_pushboolean(L, 0); /* (sp += 1) */
|
||||
lua_setfield(L, -2, "__metatable"); /* protect metatable (sp -= 1) */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int magnet_stat(lua_State *L) {
|
||||
buffer stor; /*(note: do not free magnet_checkbuffer() result)*/
|
||||
const buffer * const sb = magnet_checkbuffer(L, 1, &stor);
|
||||
stat_cache_entry * const sce = (!buffer_is_blank(sb))
|
||||
? stat_cache_get_entry(sb)
|
||||
: NULL;
|
||||
if (NULL == sce) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
buffer stor; /*(note: do not free magnet_checkbuffer() result)*/
|
||||
const buffer * const sb = magnet_checkbuffer(L, 1, &stor);
|
||||
stat_cache_entry * const sce = (!buffer_is_blank(sb))
|
||||
? stat_cache_get_entry(sb)
|
||||
: NULL;
|
||||
if (NULL == sce) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, 16); /* returned on stack */
|
||||
/* note: caching sce valid only for procedural script which does not yield;
|
||||
* (sce might not be valid if script yields and is later resumed)
|
||||
* (script must not cache sce in persistent global state for later use)
|
||||
* (If we did want sce to be persistent, then could increment sce refcnt,
|
||||
* and set up __gc metatable method to decrement sce refcnt) */
|
||||
stat_cache_entry ** const udata = /* (sp += 1) */
|
||||
(struct stat_cache_entry **)lua_newuserdata(L, sizeof(stat_cache_entry *));
|
||||
*udata = sce;
|
||||
|
||||
lua_pushboolean(L, S_ISREG(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_file");
|
||||
|
||||
lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_dir");
|
||||
|
||||
lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_char");
|
||||
|
||||
lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_block");
|
||||
|
||||
lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_socket");
|
||||
|
||||
lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_link");
|
||||
|
||||
lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
|
||||
lua_setfield(L, -2, "is_fifo");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_mtime);
|
||||
lua_setfield(L, -2, "st_mtime");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_ctime);
|
||||
lua_setfield(L, -2, "st_ctime");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_atime);
|
||||
lua_setfield(L, -2, "st_atime");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_uid);
|
||||
lua_setfield(L, -2, "st_uid");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_gid);
|
||||
lua_setfield(L, -2, "st_gid");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_size);
|
||||
lua_setfield(L, -2, "st_size");
|
||||
|
||||
lua_pushinteger(L, sce->st.st_ino);
|
||||
lua_setfield(L, -2, "st_ino");
|
||||
|
||||
request_st * const r = magnet_get_request(L);
|
||||
const buffer *etag = stat_cache_etag_get(sce, r->conf.etag_flags);
|
||||
if (etag && !buffer_is_blank(etag)) {
|
||||
lua_pushlstring(L, BUF_PTR_LEN(etag));
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
lua_setfield(L, -2, "etag");
|
||||
|
||||
const buffer *content_type = stat_cache_content_type_get(sce, r);
|
||||
if (content_type && !buffer_is_blank(content_type)) {
|
||||
lua_pushlstring(L, BUF_PTR_LEN(content_type));
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
lua_setfield(L, -2, "content-type");
|
||||
|
||||
return 1;
|
||||
magnet_stat_metatable(L); /* (sp += 1) */
|
||||
lua_setmetatable(L, -2); /* (sp -= 1) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1142,7 +1263,8 @@ static void magnet_init_lighty_table(lua_State * const L) {
|
|||
lua_pop(L, 1); /* pop global table */ /* (sp -= 1) */
|
||||
|
||||
magnet_mainenv_metatable(L); /* init table for mem locality (sp += 1) */
|
||||
lua_pop(L, 1); /* pop mainenv metatable (sp -= 1) */
|
||||
magnet_stat_metatable(L); /* init table for mem locality (sp += 1) */
|
||||
lua_pop(L, 2); /* pop mainenv,stat metatables (sp -= 2) */
|
||||
|
||||
/* lighty table
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue