Files

136 lines
4.6 KiB
Plaintext

//* This file is explicitly licensed under the MIT license. *//
//* Copyright (c) 2023 Citadel Station developers. *//
/**
* String KKV module
*
* this is the "generic store anything by key/value" system
* group specific string load is allowed but not required.
*
* use if none of the others can work
* or if you're somehow too lazy to optimize your persistence system by making a new persistence type
* but somehow not lazy enough to optimize it into a string??
*
* notice how we can't delete strings?
* that's intentional, and for optimization.
*
* string KKV does not currently allow for generations, because generations is a map concept, and this
* is more of a general system. if you require generations, it can be added later. i just do not really
* foresee a usage for it yet; even if we needed full-state map serialization, the map systems should
* handle that instead.
*/
/datum/controller/subsystem/persistence
//* Get / Set *//
/**
* gets a persistent string
*
* given this proc is for advanced users, it will not hold your hand on what group to use. figure it out.
* prefer SSpersistence for id lookups, not SSmapping, as it's outside of SSmapping's concerns to resolve that.
*
* @params
* - key - key of string
* - group - optional group-specific. null counts as its own group.
*/
/datum/controller/subsystem/persistence/proc/string_kkv_get(key, group)
return string_kkv_load(group, key)
/**
* sets a persistent string
*
* given this proc is for advanced users, it will not hold your hand on what group to use. figure it out.
* prefer SSpersistence for id lookups, not SSmapping, as it's outside of SSmapping's concerns to resolve that.
*
* @params
* - key - key of string
* - value - string to set it to
* - group - optional group-specific. null counts as its own group.
* - flush - immediately invoke SQL; otherwise subsystem decides when.
*/
/datum/controller/subsystem/persistence/proc/string_kkv_set(key, value, group, flush)
string_kkv_save(group, key, value)
//* Backend Save/Load *//
//! Why the usr fuckery? Because we intentionally wish to obfuscate admin proccalls, since we properly sanitize **everything** in these procs.
/datum/controller/subsystem/persistence/proc/string_kkv_load(group = PERSISTENCE_DEFAULT_NULL_GROUP, key)
if(!SSdbcore.Connect())
return
var/oldusr = usr
usr = null
var/datum/db_query/query = SSdbcore.NewQuery(
"SELECT `value` FROM [DB_PREFIX_TABLE_NAME("persistence_string_kkv")] WHERE `group` = :group AND `key` = :key",
list(
"group" = group,
"key" = key
)
)
query.Execute(FALSE)
usr = oldusr
if(!query.NextRow())
return
. = query.item[1]
qdel(query)
/datum/controller/subsystem/persistence/proc/string_kkv_save(group = PERSISTENCE_DEFAULT_NULL_GROUP, key, value)
if(!SSdbcore.Connect())
return
var/oldusr = usr
usr = null
var/datum/db_query/query = SSdbcore.NewQuery(
"INSERT INTO [DB_PREFIX_TABLE_NAME("persistence_string_kkv")] (`group`, `key`, `value`) VALUES (:group, :key, :value) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `modified` = Now(), `revision` = `revision` + 1",
list(
"group" = group,
"key" = key,
"value" = value
)
)
query.Execute(FALSE)
usr = oldusr
qdel(query)
//* Benchmarks *//
/datum/controller/subsystem/persistence/proc/benchmark_string_kkv()
var/oldusr = usr
usr = null
message_admins("SSpersist: benchmarking string storage")
var/amt = 10000
var/list/pointer = list(amt)
var/list/keys = list()
var/list/values = list()
for(var/i in 1 to amt)
keys += "[rand(1, 10000000)]"
values += "[rand(1, 100000000000000)]"
var/start = REALTIMEOFDAY
kkv_string_save_benchmark(pointer, keys, values, amt)
UNTIL(pointer[1] == 0)
var/end = REALTIMEOFDAY
message_admins("SSpersist: saving [amt] strings took [end - start] ds")
pointer = list(amt)
start = REALTIMEOFDAY
kkv_string_load_benchmark(pointer, keys, amt)
UNTIL(pointer[1] == 0)
end = REALTIMEOFDAY
message_admins("SSpersist: loading [amt] strings took [end - start] ds")
usr = oldusr
/datum/controller/subsystem/persistence/proc/kkv_string_save_benchmark(list/pointer, list/keys, list/values, amt)
set waitfor = FALSE
for(var/i in 1 to amt)
kkv__string_save_benchmark(pointer, keys[i], values[i])
/datum/controller/subsystem/persistence/proc/kkv_string_load_benchmark(list/pointer, list/keys, amt)
set waitfor = FALSE
for(var/i in 1 to amt)
kkv__string_load_benchmark(pointer, keys[i])
/datum/controller/subsystem/persistence/proc/kkv__string_save_benchmark(list/pointer, key, value)
string_kkv_save("benchmark", key, value)
pointer[1]--
/datum/controller/subsystem/persistence/proc/kkv__string_load_benchmark(list/pointer, key)
string_kkv_load("benchmark", key)
pointer[1]--