Index: api/lp/outbox.t ================================================================== --- api/lp/outbox.t +++ api/lp/outbox.t @@ -26,11 +26,10 @@ time = lib.osclock.time(nil) else var tp, ok = lib.math.decparse(at) if ok then time = tp end end - lib.io.fmt('from-time: %llu\n', time) var posts = co.srv:post_enum_author_uid(uid, lib.store.range { mode = 1; -- time -> idx from_time = time; to_idx = 65; }) @@ -40,10 +39,11 @@ if posts.sz > 0 then defer posts:free() for i=0, lib.math.smallest(posts.sz,64) do if i~=0 then json:lpush',' end json:ppush(lib.api.lp.tweet(co,posts(i).ptr,true)) oldest = lib.math.smallest(posts(i)().posted, oldest) + posts(i):free() end end json:lpush'],"totalItems":':ipush(posts.sz) if oldest ~= time and oldest > 0 and posts.sz > 64 then json:lpush',"next":"https://':ppush(co.srv.cfg.domain):ppush(path) Index: backend/pgsql.t ================================================================== --- backend/pgsql.t +++ backend/pgsql.t @@ -956,11 +956,12 @@ local tempviews = sqlsquash(lib.util.ingest 'backend/schema/pgsql-views.sql') local prep = { quote var res = lib.pq.PQexec([con], tempviews) if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then - lib.dbg('uploading pgsql session views') + lib.dbg('uploaded pgsql session views') + lib.pq.PQclear(res) else lib.bail('backend pgsql - failed to upload session views: \n', lib.pq.PQresultErrorMessage(res)) end end } @@ -1028,17 +1029,22 @@ lib.bail(['grievous error occurred executing '..k..' against database']) elseif lib.pq.PQresultStatus(res) ~= okconst then lib.bail(['PGSQL database procedure '..k..' failed\n'], lib.pq.PQresultErrorMessage(res)) end - - var ct = lib.pq.PQntuples(res) - if ct == 0 then - lib.pq.PQclear(res) - return pqr {0, nil} - else - return pqr {ct, res} + escape + if q.cmd then + emit quote lib.pq.PQclear(res) end + else emit quote + var ct = lib.pq.PQntuples(res) + if ct == 0 then + lib.pq.PQclear(res) + return pqr {0, nil} + else + return pqr {ct, res} + end + end end end end q.exec.name = 'pgsql.' .. k .. '.exec' end @@ -1244,10 +1250,11 @@ uid: uint64 ): lib.store.powerset var powers = lib.store.rights_default().powers var map = array([privmap]) var r = queries.actor_powers_fetch.exec(src, uid) + defer r:free() for i=0, r.sz do for j=0, [map.type.N] do var pn = r:_string(i,0) if map[j].name:cmp(pn) then @@ -1263,28 +1270,34 @@ end local txdo = terra(src: &lib.store.source) var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'begin') + var r: bool if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.dbg('beginning pgsql transaction') - return true + r = true else lib.warn('backend pgsql - failed to begin transaction: \n', lib.pq.PQresultErrorMessage(res)) - return false + r = false end + lib.pq.PQclear(res) + return r end local txdone = terra(src: &lib.store.source) var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), 'end') + var r: bool if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.dbg('completing pgsql transaction') - return true + r = true else lib.warn('backend pgsql - failed to complete transaction: \n', lib.pq.PQresultErrorMessage(res)) - return false + r = false end + lib.pq.PQclear(res) + return r end local b = `lib.store.backend { id = "pgsql"; open = [terra(src: &lib.store.source): &opaque @@ -1350,41 +1363,45 @@ queries.server_setup_self.exec(src,domain,key,lib.osclock.time(nil)) end]; dbsetup = [terra(src: &lib.store.source): bool var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), schema) + var r = true if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.report('successfully instantiated schema in database') - return true else lib.warn('backend pgsql - failed to initialize database: \n', lib.pq.PQresultErrorMessage(res)) - return false + r = false end + lib.pq.PQclear(res) + return r end]; obliterate_everything = [terra(src: &lib.store.source): bool var res = lib.pq.PQexec([&lib.pq.PGconn](src.handle), obliterator) + var r = true if lib.pq.PQresultStatus(res) == lib.pq.PGRES_COMMAND_OK then lib.report('successfully wiped out everything parsav-related in database') - return true else lib.warn('backend pgsql - failed to obliterate database: \n', lib.pq.PQresultErrorMessage(res)) return false end + lib.pq.PQclear(res) + return r end]; - conf_get = [terra(src: &lib.store.source, key: pstring) + conf_get = [terra(src: &lib.store.source, pool: &lib.mem.pool, key: pstring) var r = queries.conf_get.exec(src, key) if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else defer r:free() - return r:String(0,0) + return r:_string(0,0):pdup(pool) end end]; conf_set = [terra(src: &lib.store.source, key: pstring, val: pstring) - queries.conf_set.exec(src, key, val):free() end]; + queries.conf_set.exec(src, key, val) end]; conf_reset = [terra(src: &lib.store.source, key: rawstring) - queries.conf_reset.exec(src, key):free() end]; + queries.conf_reset.exec(src, key) end]; actor_fetch_uid = [terra(src: &lib.store.source, uid: uint64) var r = queries.actor_fetch_uid.exec(src, uid) if r.sz == 0 then return [lib.mem.ptr(lib.store.actor)] { ct = 0, ptr = nil } @@ -1513,10 +1530,11 @@ actor_stats = [terra(src: &lib.store.source, uid: uint64) var r = queries.actor_stats.exec(src, uid) if r.sz == 0 then lib.bail('error fetching actor stats!') end + defer r:free() var s: lib.store.actor_stats s.posts = r:int(uint64, 0, 0) s.follows = r:int(uint64, 0, 1) s.followers = r:int(uint64, 0, 2) s.mutuals = r:int(uint64, 0, 3) @@ -1589,10 +1607,11 @@ src: &lib.store.source, post: uint64 ): lib.mem.ptr(lib.store.post) var r = queries.post_fetch.exec(src, post) if r.sz == 0 then return [lib.mem.ptr(lib.store.post)].null() end + defer r:free() var p = row_to_post(&r, 0) p.ptr.source = src return p end]; @@ -1648,10 +1667,11 @@ var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz) for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL ret.ptr[i].ptr.source = src end + r:free() return ret end]; timeline_circle_fetch = [terra( @@ -1666,10 +1686,11 @@ var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz) for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL ret.ptr[i].ptr.source = src end + r:free() return ret end]; timeline_actor_fetch_uid = [terra( @@ -1684,10 +1705,11 @@ var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz) for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL ret.ptr[i].ptr.source = src end + r:free() return ret end]; post_enum_author_uid = [terra( @@ -1702,10 +1724,11 @@ var ret: lib.mem.ptr(lib.mem.ptr(lib.store.post)) ret:init(r.sz) for i=0,r.sz do ret.ptr[i] = row_to_post(&r, i) -- MUST FREE ALL ret.ptr[i].ptr.source = src end + r:free() return ret end]; actor_powers_fetch = getpow; @@ -1734,10 +1757,11 @@ -- check against default rights, insert records for wherever powers differ lib.dbg('created new actor, establishing powers') privupdate(src,ac) lib.dbg('powers established') + r:free() return ac.id end]; actor_rel_create = [terra( src: &lib.store.source, @@ -1820,10 +1844,11 @@ src: &lib.store.source, aid: uint64 ): lib.mem.ptr(lib.store.auth) var r = queries.auth_fetch_aid.exec(src,aid) if r.sz == 0 then return [lib.mem.ptr(lib.store.auth)].null() end + defer r:free() var kind = r:_string(0, 2) var comment = r:_string(0, 3) var a = [ lib.str.encapsulate(lib.store.auth, { kind = {`kind.ptr, `kind.ct+1}; comment = {`comment.ptr, `comment.ct+1}; @@ -1842,10 +1867,11 @@ src: &lib.store.source, uid: uint64 ): lib.mem.lstptr(lib.store.auth) var r = queries.auth_enum_uid.exec(src,uid) if r.sz == 0 then return [lib.mem.lstptr(lib.store.auth)].null() end + defer r:free() var ret = lib.mem.heapa([lib.mem.ptr(lib.store.auth)], r.sz) for i=0, r.sz do var kind = r:_string(i, 1) var comment = r:_string(i, 2) var a = [ lib.str.encapsulate(lib.store.auth, { @@ -2006,11 +2032,11 @@ src: &lib.store.source, uid: uint64, folder: pstring ) var res = queries.artifact_enum_uid.exec(src,uid,folder) - if res.sz > 0 then + if res.sz > 0 then defer res:free() var m = lib.mem.heapa([lib.mem.ptr(lib.store.artifact)], res.sz) for i=0,res.sz do m.ptr[i] = row_to_artifact(&res, i) m(i).ptr.owner = uid end @@ -2162,19 +2188,19 @@ src: &lib.store.source, pool: &lib.mem.pool, uid: uint64, key: pstring ): pstring - var r = queries.actor_conf_str_get.exec(src, uid, key) - if r.sz > 0 then - return r:_string(0,0):pdup(pool) - else return pstring.null() end - end]; + var r = queries.actor_conf_str_get.exec(src, uid, key) + if r.sz > 0 then defer r:free() + return r:_string(0,0):pdup(pool) + else return pstring.null() end + end]; actor_conf_str_set = [terra(src: &lib.store.source, uid: uint64, key: pstring, value: pstring): {} - queries.actor_conf_str_set.exec(src,uid,key,value) end]; + queries.actor_conf_str_set.exec(src,uid,key,value) end]; actor_conf_str_reset = [terra(src: &lib.store.source, uid: uint64, key: pstring): {} - queries.actor_conf_str_reset.exec(src,uid,key) end]; + queries.actor_conf_str_reset.exec(src,uid,key) end]; actor_conf_int_enum = nil; actor_conf_int_get = [terra(src: &lib.store.source, uid: uint64, key: pstring) var r = queries.actor_conf_int_get.exec(src, uid, key) if r.sz > 0 then Index: convo.t ================================================================== --- convo.t +++ convo.t @@ -16,11 +16,11 @@ uploads: lib.mem.vec(lib.http.upload) body: pstring -- cache ui_hue: uint16 navbar: pstring - actorcache: lib.mem.cache(lib.mem.ptr(lib.store.actor),32) -- naive cache to avoid unnecessary queries + actorcache: lib.mem.cache(lib.mem.ptr(lib.store.actor),32,true) -- naive cache to avoid unnecessary queries -- private varbuf: pstring vbofs: &int8 } Index: mem.t ================================================================== --- mem.t +++ mem.t @@ -17,11 +17,11 @@ ptr = [&ty:astype()](m.heapa_raw(sizeof(ty) * sz)); ct = sz; } end) -function m.cache(ty,sz) +function m.cache(ty,sz,autofree) sz = sz or 32 local struct c { store: ty[sz] top: intptr cur: intptr @@ -35,11 +35,11 @@ self.top = lib.math.biggest(self.top, self.cur + 1) self.cur = (self.cur + 1) % sz return v end c.metamethods.__apply = terra(self: &c, idx: intptr) return &self.store[idx] end - if ty.ptr_basetype then + if autofree then terra c:free() for i=0,self.top do self.store[i]:free() end end end return c Index: mgtool.t ================================================================== --- mgtool.t +++ mgtool.t @@ -56,10 +56,12 @@ src: &lib.store.source srv: &lib.srv.overlord sid: uint64 iname: rawstring + + cfgpool: lib.mem.pool } idelegate.metamethods.__methodmissing = macro(function(meth, self, ...) local expr = {...} local rt @@ -76,10 +78,14 @@ elseif self.src ~= nil then r=self.src:[meth]([expr]) else lib.bail('no data source specified') end in r end end) + +terra idelegate:conf(key: lib.str.t) + return self:conf_get(&self.cfgpool, key) +end terra idelegate:ipc_send(cmd: lib.ipc.cmd.t, operand: uint64) var emp = self.emperor var acks: lib.mem.ptr(lib.ipc.ack) if self.sid == 0 and self.iname == nil then @@ -157,10 +163,11 @@ var srv: lib.srv.overlord var dlg = idelegate { emperor = &emp, srv = &srv; src = nil, sid = 0, iname = nil, all = false; } + dlg.cfgpool:init(128) var mode: ctloptions mode:parse(argc,argv) defer mode:free() if mode.version then version() return 0 end if mode.help then @@ -380,11 +387,11 @@ if cfmode.help then [ lib.emit(false, 1, 'usage: ', `argv[0], ' mkroot ', cfmode.type.helptxt.flags, ' ', cfmode.type.helptxt.opts) ] return 1 end if cfmode.arglist.ct == 1 then - var am = dlg:conf_get('credential-store') + var am = dlg:conf('credential-store') var mg: bool if (not am) or am:cmp('managed') then mg = true elseif am:cmp('unmanaged') then lib.warn('credential store is unmanaged; you will need to create credentials for the new root user manually!') Index: mime.t ================================================================== --- mime.t +++ mime.t @@ -58,11 +58,10 @@ idcache[mime] = ty end local op = lib.http.mime[typecode] if op == nil then op = lib.http.mime.none end - print(typecode,op) ty.offset = #typestore typestore[#typestore + 1] = `mime { key = typecode; canonical = [ty.id[1]]; @@ -98,12 +97,11 @@ tbl = idcache; typedex = typedex; lookup = terra(m: pstr): &mime for i=0, [#typemap_l] do if m:cmp(typemap[i].string) then - lib.io.fmt('returning type %s %u\n', typemap[i].type.key, typemap[i].type.output) return typemap[i].type end end return nil end; } Index: parsav.t ================================================================== --- parsav.t +++ parsav.t @@ -642,11 +642,11 @@ lib.str.ncpy(&a.iname[0], srv.id, [(`a.iname).tree.type.N]) else a.iname[0] = 0 end elseif d.cmd == lib.ipc.cmd.chnoise then lib.noise.level = d.operand elseif d.cmd == lib.ipc.cmd.cfgrefresh then - srv.cfg:free() + srv.cfg:purge() srv.cfg:load() end d:ack(&lib.ipc.global_emperor, &a) end end Index: route.t ================================================================== --- route.t +++ route.t @@ -519,11 +519,10 @@ [check] in [me] end end)()] if privs:sz() > 0 then lib.dbg('installing credential restrictions') - lib.io.fmt('on priv %llu\n',aid) co.srv:auth_privs_set(aid, privs) end lib.dbg('setting netmask restrictions') var nm = co:pgetv('netmask') @@ -907,22 +906,22 @@ terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8)) -- TODO retrieve user avatars var usr = co.srv:actor_fetch_xid(handle) - if not usr then - goto default end - if usr(0).origin == 0 then - if usr(0).avatarid == 0 then goto default end - var avi, mime = co.srv:artifact_load(usr(0).avatarid) - if not avi then goto default end - defer avi:free() defer mime:free() - co:bytestream(mime,avi) - else - co:reroute(usr(0).avatar) - end - do return end + if not usr then goto default end + do defer usr:free() + if usr(0).origin == 0 then + if usr(0).avatarid == 0 then goto default end + var avi, mime = co.srv:artifact_load(usr(0).avatarid) + if not avi then goto default end + defer avi:free() defer mime:free() + co:bytestream(mime,avi) + else + co:reroute(usr(0).avatar) + end + return end ::default:: co:reroute('/s/default-avatar.webp') end terra http.file_serve_raw(co: &lib.srv.convo, id: lib.mem.ptr(int8)) var id, idok = lib.math.shorthand.parse(id.ptr, id.ct) Index: session.t ================================================================== --- session.t +++ session.t @@ -24,15 +24,16 @@ &hash[0]) ptr = ptr + lib.math.shorthand.gen(lib.math.truncate64(hash, [hash.type.N]), ptr) return ptr - out end -terra m.cookie_interpret(secret: lib.mem.ptr(int8), c: lib.mem.ptr(int8), now: uint64) -- returns either 0,0 or a valid {authid, timepoint} - var authid_sz = lib.str.cspan(c.ptr, lib.str.lit '.', c.ct) +terra m.cookie_interpret(secret: lib.mem.ptr(int8), c: lib.mem.ptr(int8), now: uint64) + -- returns either 0,0 or a valid {authid, timepoint} + var authid_sz = lib.str.cspan(c.ptr, '.', c.ct) if authid_sz == 0 then return 0,0 end if authid_sz + 1 > c.ct then return 0,0 end - var time_sz = lib.str.cspan(c.ptr+authid_sz+1, lib.str.lit '.', c.ct - (authid_sz+1)) + var time_sz = lib.str.cspan(c.ptr+authid_sz+1, '.', c.ct - (authid_sz+1)) if time_sz == 0 then return 0,0 end if (authid_sz + time_sz + 2) > c.ct then return 0,0 end var hash_sz = c.ct - (authid_sz + time_sz + 2) var knownhash: uint8[lib.crypt.algsz.sha256] Index: srv.t ================================================================== --- srv.t +++ srv.t @@ -3,10 +3,11 @@ local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' } local pstring = lib.mem.ptr(int8) local struct srv local struct cfgcache { + _pool: lib.mem.pool secret: pstring pol_sec: secmode.t pol_reg: bool pol_autoherald: bool credmgd: bool @@ -32,18 +33,16 @@ cfg: cfgcache id: rawstring pool: lib.mem.pool } -terra cfgcache:free() -- :/ TODO replace with pool - self.secret:free() - self.instance:free() - self.domain:free() - self.ui_cue_staff:free() - self.ui_cue_founder:free() - self.usrdef_pol_follow:free() - self.usrdef_pol_follow_req:free() +terra cfgcache:purge() + self._pool:clear() +end + +terra cfgcache:free() + self._pool:free() end terra srv:post_enum_author_uid(uid: uint64, r: lib.store.range): lib.mem.vec(lib.mem.ptr(lib.store.post)) var all: lib.mem.vec(lib.mem.ptr(lib.store.post)) all:init(64) for i=0,self.sources.ct do var src = self.sources.ptr + i @@ -377,11 +376,11 @@ end var boundary = pstring {ptr=p+9,ct=ctt.ct - ((p - ctt.ptr) + 9)} co.method = lib.http.method.post_file co.uploads:init(8) - var bsr = (lib.str.acc{}):compose('\r\n--',boundary,'\r\n'):finalize() + var bsr = co:qstr('\r\n--',boundary,'\r\n') var upmap = lib.str.splitmap(co.body,bsr,8) -- first entry may not be preceded by header-break if lib.str.find(upmap(0), pstring { ptr = bsr.ptr + 2, ct = bsr.ct - 2 @@ -453,18 +452,15 @@ end end end end end - bsr:free() upmap:free() end end end - var mtt = lib.http.mime._str(co.reqtype) - lib.dbg('routing with negotiated type of ', {mtt.ptr,mtt.ct}) route.dispatch_http(&co, uri) ::fail:: if co.uploads.run > 0 then for i=0,co.uploads.sz do @@ -656,10 +652,11 @@ --end terra cfgcache.methods.load :: {&cfgcache} -> {} terra cfgcache:init(o: &srv) self.overlord = o + self._pool:init(256) self:load() end terra srv:setup(befile: rawstring) cfg(self, befile) @@ -677,11 +674,11 @@ terra srv:start(iname: rawstring) self:conprep(lib.store.prepmode.full) self.cfg:init(self) self.pool:init(self.cfg.poolinitsz) - var dbbind = self:conf_get('bind') + var dbbind = self:conf_get(&self.pool, 'bind') if iname == nil then iname = lib.proc.getenv('parsav_instance') end if iname == nil then self.id = self.cfg.instance.ptr; -- let this leak -- it'll be needed for the lifetime of the process anyway else self.id = iname end @@ -700,11 +697,11 @@ lib.report('binding to ', bind) lib.net.mg_mgr_init(&self.webmgr) self.webcon = lib.net.mg_http_listen(&self.webmgr, bind, handle.http, self) - if dbbind.ptr ~= nil then dbbind:free() end + --if dbbind.ptr ~= nil then dbbind:free() end end terra srv:poll() lib.net.mg_mgr_poll(&self.webmgr,300) end @@ -717,74 +714,84 @@ end self.sources:free() self.pool:free() end -terra cfgcache:cfint(name: rawstring, default: intptr) - var str = self.overlord:conf_get(name) +terra cfgcache:cfstr(name: pstring) + return self.overlord:conf_get(&self._pool, name) +end + +terra cfgcache:cfint(name: pstring, default: intptr) + var f = self._pool:frame() + var str = self:cfstr(name) + defer self._pool:reset(f) if str.ptr ~= nil then var i,ok = lib.math.decparse(str) if ok then default = i else - lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected integer; using default value instead') + lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected integer; using default value instead') end - str:free() end return default end -terra cfgcache:cffsz(name: rawstring, default: intptr) - var str = self.overlord:conf_get(name) +terra cfgcache:cffsz(name: pstring, default: intptr) + var f = self._pool:frame() + var str = self:cfstr(name) + defer self._pool:reset(f) if str:ref() then var sz, ok = lib.math.fsz_parse(str) if ok then default = sz else - lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected byte length; using default value instead') + lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected byte length; using default value instead') end - str:free() end return default end -terra cfgcache:cfbool(name: rawstring, default: bool) - var str = self.overlord:conf_get(name) +terra cfgcache:cfbool(name: pstring, default: bool) + var f = self._pool:frame() + var str = self:cfstr(name) + defer self._pool:reset(f) if str.ptr ~= nil then if str:cmp('true') or str:cmp('on') or str:cmp('yes') or str:cmp('1') then default = true elseif str:cmp('false') or str:cmp('off') or str:cmp('no') or str:cmp('0') then default = false else - lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected boolean; using default value instead') + lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected boolean; using default value instead') end - str:free() end return default end terra cfgcache:load() - self.instance = self.overlord:conf_get('instance-name') - self.domain = self.overlord:conf_get('domain') - self.secret = self.overlord:conf_get('server-secret') + + self.instance = self:cfstr('instance-name') + self.domain = self:cfstr('domain') + self.secret = self:cfstr('server-secret') self.pol_reg = self:cfbool('policy-self-register', false) self.pol_autoherald = self:cfbool('policy-self-herald', true) do self.credmgd = false - var sreg = self.overlord:conf_get('credential-store') + var fr = self._pool:frame() + var sreg = self:cfstr('credential-store') if sreg:ref() then if lib.str.cmp(sreg.ptr, 'managed') == 0 then self.credmgd = true else self.credmgd = false end - sreg:free() + self._pool:reset(fr) end end self.maxupsz = self:cffsz('maximum-artifact-size', [1024 * 100]) -- 100 kilobyte default self.poolinitsz = self:cffsz('server-pool-size-initial', [1024 * 10]) -- 10 kilobyte default self.pol_sec = secmode.lockdown - var smode = self.overlord:conf_get('policy-security') + do var fr = self._pool:frame() + var smode = self:cfstr('policy-security') if smode.ptr ~= nil then if lib.str.cmp(smode.ptr, 'public') == 0 then self.pol_sec = secmode.public elseif lib.str.cmp(smode.ptr, 'private') == 0 then self.pol_sec = secmode.private @@ -791,36 +798,38 @@ elseif lib.str.cmp(smode.ptr, 'lockdown') == 0 then self.pol_sec = secmode.lockdown elseif lib.str.cmp(smode.ptr, 'isolate') == 0 then self.pol_sec = secmode.isolate end - smode:free() - end + self._pool:reset(fr) + end end self.ui_hue = self:cfint('ui-accent',config.default_ui_accent) self.nranks = self:cfint('user-ranks',10) self.maxinvites = self:cfint('max-invites',64) - var webmaster = self.overlord:conf_get('master') - if webmaster:ref() then defer webmaster:free() + do var fr = self._pool:frame() + var webmaster = self:cfstr('master') + defer self._pool:reset(fr) + if webmaster:ref() then var wma = self.overlord:actor_fetch_xid(webmaster) if not wma then lib.warn('the webmaster specified in the configuration store does not seem to exist or is not known to this instance; preceding as if no master defined. if the master is a remote user, you can rectify this with the `actor "',{webmaster.ptr,webmaster.ct},'" instantiate` and `conf refresh` commands') else self.master = wma(0).id wma:free() end - end + end end - self.ui_cue_staff = self.overlord:conf_get('ui-profile-cue-staff') - self.ui_cue_founder = self.overlord:conf_get('ui-profile-cue-master') + self.ui_cue_staff = self:cfstr('ui-profile-cue-staff') + self.ui_cue_founder = self:cfstr('ui-profile-cue-master') - self.usrdef_pol_follow = self.overlord:conf_get('user-default-acl-follow') - self.usrdef_pol_follow_req = self.overlord:conf_get('user-default-acl-follow-req') + self.usrdef_pol_follow = self:cfstr('user-default-acl-follow') + self.usrdef_pol_follow_req = self:cfstr('user-default-acl-follow-req') end return { overlord = srv; convo = convo; route = route; secmode = secmode; } Index: store.t ================================================================== --- store.t +++ store.t @@ -374,11 +374,11 @@ -- backends by the server; that is pathological behavior that will -- not have the desired effect server_setup_self: {&m.source, rawstring, lib.mem.ptr(uint8)} -> {} - conf_get: {&m.source, lib.str.t} -> lib.mem.ptr(int8) + conf_get: {&m.source, &lib.mem.pool, lib.str.t} -> lib.mem.ptr(int8) conf_set: {&m.source, lib.str.t, lib.str.t} -> {} conf_reset: {&m.source, rawstring} -> {} actor_create: {&m.source, &m.actor} -> uint64 actor_save: {&m.source, &m.actor} -> {}