mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
Add shared memory hit counter example to redbean
This commit is contained in:
parent
38e3ab57a6
commit
8aca94f951
6 changed files with 114 additions and 29 deletions
|
@ -29,7 +29,7 @@ assert(mem:read() == 'hello')
|
||||||
mem:write('hi')
|
mem:write('hi')
|
||||||
assert(mem:read() == 'hi')
|
assert(mem:read() == 'hi')
|
||||||
assert(mem:read(0, 5) == 'hi\0lo')
|
assert(mem:read(0, 5) == 'hi\0lo')
|
||||||
mem:write('H', 0, 1)
|
mem:write(0, 'H', 1)
|
||||||
assert(mem:read(0, 5) == 'Hi\0lo')
|
assert(mem:read(0, 5) == 'Hi\0lo')
|
||||||
assert(mem:read(1, 1) == 'i')
|
assert(mem:read(1, 1) == 'i')
|
||||||
|
|
||||||
|
|
20
third_party/lua/lunix.c
vendored
20
third_party/lua/lunix.c
vendored
|
@ -2696,19 +2696,29 @@ static int LuaUnixMemoryRead(lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.Memory:write(data:str[, offset:int[, bytes:int]])
|
// unix.Memory:write([offset:int,] data:str[, bytes:int])
|
||||||
static int LuaUnixMemoryWrite(lua_State *L) {
|
static int LuaUnixMemoryWrite(lua_State *L) {
|
||||||
|
int b;
|
||||||
const char *s;
|
const char *s;
|
||||||
size_t i, n, j;
|
size_t i, n, j;
|
||||||
struct Memory *m;
|
struct Memory *m;
|
||||||
m = luaL_checkudata(L, 1, "unix.Memory");
|
m = luaL_checkudata(L, 1, "unix.Memory");
|
||||||
|
if (!lua_isnumber(L, 2)) {
|
||||||
|
// unix.Memory:write(data:str[, bytes:int])
|
||||||
|
i = 0;
|
||||||
s = luaL_checklstring(L, 2, &n);
|
s = luaL_checklstring(L, 2, &n);
|
||||||
i = luaL_optinteger(L, 3, 0);
|
b = 3;
|
||||||
|
} else {
|
||||||
|
// unix.Memory:write(offset:int, data:str[, bytes:int])
|
||||||
|
i = luaL_checkinteger(L, 2);
|
||||||
|
s = luaL_checklstring(L, 3, &n);
|
||||||
|
b = 4;
|
||||||
|
}
|
||||||
if (i > m->size) {
|
if (i > m->size) {
|
||||||
luaL_error(L, "out of range");
|
luaL_error(L, "out of range");
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
if (lua_isnoneornil(L, 4)) {
|
if (lua_isnoneornil(L, b)) {
|
||||||
// unix.Memory:write(data:str[, offset:int])
|
// unix.Memory:write(data:str[, offset:int])
|
||||||
// writes binary data, plus a nul terminator
|
// writes binary data, plus a nul terminator
|
||||||
if (i < n < m->size) {
|
if (i < n < m->size) {
|
||||||
|
@ -2723,9 +2733,9 @@ static int LuaUnixMemoryWrite(lua_State *L) {
|
||||||
} else {
|
} else {
|
||||||
// unix.Memory:write(data:str, offset:int, bytes:int])
|
// unix.Memory:write(data:str, offset:int, bytes:int])
|
||||||
// writes binary data without including nul-terminator
|
// writes binary data without including nul-terminator
|
||||||
j = luaL_checkinteger(L, 4);
|
j = luaL_checkinteger(L, b);
|
||||||
if (j > n) {
|
if (j > n) {
|
||||||
luaL_argerror(L, 4, "bytes is more than what's in data");
|
luaL_argerror(L, b, "bytes is more than what's in data");
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
n = j;
|
n = j;
|
||||||
|
|
|
@ -20,6 +20,30 @@ db:exec[[
|
||||||
INSERT INTO test (content) VALUES ('Hello Sqlite3');
|
INSERT INTO test (content) VALUES ('Hello Sqlite3');
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
-- shared memory hit counter
|
||||||
|
SHM_LOCK = 0 -- index zero (first eight bytes) will hold mutex
|
||||||
|
SHM_JSON = 8 -- store json payload starting at the index eight
|
||||||
|
shm = unix.mapshared(65520)
|
||||||
|
function Lock()
|
||||||
|
local ok, old = shm:cmpxchg(SHM_LOCK, 0, 1)
|
||||||
|
if not ok then
|
||||||
|
if old == 1 then
|
||||||
|
old = shm:xchg(SHM_LOCK, 2)
|
||||||
|
end
|
||||||
|
while old > 0 do
|
||||||
|
shm:wait(SHM_LOCK, 2)
|
||||||
|
old = shm:xchg(SHM_LOCK, 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function Unlock()
|
||||||
|
old = shm:fetch_add(SHM_LOCK, -1)
|
||||||
|
if old == 2 then
|
||||||
|
shm:store(SHM_LOCK, 0)
|
||||||
|
shm:wake(SHM_LOCK, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function OnServerListen(fd, ip, port)
|
function OnServerListen(fd, ip, port)
|
||||||
unix.setsockopt(fd, unix.SOL_TCP, unix.TCP_SAVE_SYN, true)
|
unix.setsockopt(fd, unix.SOL_TCP, unix.TCP_SAVE_SYN, true)
|
||||||
return false
|
return false
|
||||||
|
@ -29,8 +53,22 @@ function OnClientConnection(ip, port, serverip, serverport)
|
||||||
syn, synerr = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_SAVED_SYN)
|
syn, synerr = unix.getsockopt(GetClientFd(), unix.SOL_TCP, unix.TCP_SAVED_SYN)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function UpdateHitCounter()
|
||||||
|
local s, t, k
|
||||||
|
Lock()
|
||||||
|
s = shm:read(SHM_JSON)
|
||||||
|
if s == '' then s = '{}' end
|
||||||
|
t = DecodeJson(s)
|
||||||
|
k = GetPath()
|
||||||
|
if not t[k] then t[k] = 0 end
|
||||||
|
t[k] = t[k] + 1
|
||||||
|
shm:write(SHM_JSON, EncodeJson(t))
|
||||||
|
Unlock()
|
||||||
|
end
|
||||||
|
|
||||||
-- this intercepts all requests if it's defined
|
-- this intercepts all requests if it's defined
|
||||||
function OnHttpRequest()
|
function OnHttpRequest()
|
||||||
|
UpdateHitCounter()
|
||||||
if GetHeader('User-Agent') then
|
if GetHeader('User-Agent') then
|
||||||
Log(kLogInfo, "client is running %s and reports %s" % {
|
Log(kLogInfo, "client is running %s and reports %s" % {
|
||||||
finger.GetSynFingerOs(finger.FingerSyn(syn)),
|
finger.GetSynFingerOs(finger.FingerSyn(syn)),
|
||||||
|
|
35
tool/net/demo/hitcounter.lua
Normal file
35
tool/net/demo/hitcounter.lua
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
Write([[<!doctype html>
|
||||||
|
<title>redbean mapshared demo</title>
|
||||||
|
<style>
|
||||||
|
body { padding: 1em; }
|
||||||
|
h1 a { color: inherit; text-decoration: none; }
|
||||||
|
h1 img { border: none; vertical-align: middle; }
|
||||||
|
input { margin: 1em; padding: .5em; }
|
||||||
|
pre { margin-left: 2em; }
|
||||||
|
p { word-break: break-word; max-width: 650px; }
|
||||||
|
dt { font-weight: bold; }
|
||||||
|
dd { margin-top: 1em; margin-bottom: 1em; }
|
||||||
|
.hdr { text-indent: -1em; padding-left: 1em; }
|
||||||
|
</style>
|
||||||
|
<h1>
|
||||||
|
<a href="/"><img src="/redbean.png"></a>
|
||||||
|
<a href="fetch.lua">redbean mapshared demo</a>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
This page displays a <code>unix.mapshared()</code> hit counter of
|
||||||
|
the <code>GetPath()</code>.
|
||||||
|
</p>
|
||||||
|
<dl>
|
||||||
|
]])
|
||||||
|
|
||||||
|
Lock()
|
||||||
|
s = shm:read(SHM_JSON)
|
||||||
|
if s == '' then s = '{}' end
|
||||||
|
t = DecodeJson(s)
|
||||||
|
Unlock()
|
||||||
|
|
||||||
|
for k,v in pairs(t) do
|
||||||
|
Write('<dt>%s<dd>%d\n' % {EscapeHtml(k), v})
|
||||||
|
end
|
||||||
|
|
||||||
|
Write('</dl>')
|
|
@ -4509,7 +4509,7 @@ UNIX MODULE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function Unlock()
|
function Unlock()
|
||||||
old = mem:add(LOCK, -1)
|
old = mem:fetch_add(LOCK, -1)
|
||||||
if old == 2 then
|
if old == 2 then
|
||||||
mem:store(LOCK, 0)
|
mem:store(LOCK, 0)
|
||||||
mem:wake(LOCK, 1)
|
mem:wake(LOCK, 1)
|
||||||
|
@ -4568,7 +4568,7 @@ UNIX MODULE
|
||||||
single lock which is used to synchronize reads and writes to
|
single lock which is used to synchronize reads and writes to
|
||||||
that specific map. To make it scale, create additional maps.
|
that specific map. To make it scale, create additional maps.
|
||||||
|
|
||||||
unix.Memory:write(data:str[, offset:int[, bytes:int]])
|
unix.Memory:write([offset:int,] data:str[, bytes:int]])
|
||||||
|
|
||||||
Writes bytes to memory region.
|
Writes bytes to memory region.
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ o/$(MODE)/tool/net/demo/store-asset.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/maxmind.lua.zip.o \
|
o/$(MODE)/tool/net/demo/maxmind.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/opensource.lua.zip.o \
|
o/$(MODE)/tool/net/demo/opensource.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/demo/hitcounter.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/binarytrees.lua.zip.o \
|
o/$(MODE)/tool/net/demo/binarytrees.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/crashreport.lua.zip.o \
|
o/$(MODE)/tool/net/demo/crashreport.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/closedsource.lua.zip.o \
|
o/$(MODE)/tool/net/demo/closedsource.lua.zip.o \
|
||||||
|
@ -205,6 +206,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
||||||
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/maxmind.lua.zip.o \
|
o/$(MODE)/tool/net/demo/maxmind.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/opensource.lua.zip.o \
|
o/$(MODE)/tool/net/demo/opensource.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/demo/hitcounter.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/binarytrees.lua.zip.o \
|
o/$(MODE)/tool/net/demo/binarytrees.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/crashreport.lua.zip.o \
|
o/$(MODE)/tool/net/demo/crashreport.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/closedsource.lua.zip.o \
|
o/$(MODE)/tool/net/demo/closedsource.lua.zip.o \
|
||||||
|
|
Loading…
Reference in a new issue