Browse Source

[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.)
master
Glenn Strauss 3 months ago
parent
commit
188248d238
  1. 248
      src/mod_magnet.c

248
src/mod_magnet.c

@ -343,79 +343,200 @@ static int magnet_print(lua_State *L) {
return 0;
}
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;
}
lua_createtable(L, 0, 16); /* returned on stack */
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");
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_pushinteger(L, sce->st.st_mtime);
lua_setfield(L, -2, "st_mtime");
lua_pushliteral(L, "stat[\"field\"] invalid: ");
lua_pushvalue(L, -2); /* field */
lua_concat(L, 2);
lua_error(L);
return 0;
}
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");
__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;
}
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");
__attribute_cold__
static int magnet_stat_pairs_noimpl(lua_State *L) {
lua_pushcclosure(L, magnet_stat_pairs_noimpl_iter, 0);
return 1;
}
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");
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) */
}
}
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");
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;
}
return 1;
/* 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;
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…
Cancel
Save