Add api to get db size to content db (#987)

* Add size proc to content_db

* Add way to reclaim used space
This commit is contained in:
KonradStaniec 2022-03-08 14:49:41 +01:00 committed by GitHub
parent d74e9cbf49
commit a330f0a4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 1 deletions

View File

@ -32,6 +32,8 @@ export kvstore_sqlite3
type
ContentDB* = ref object
kv: KvStoreRef
sizeStmt: SqliteStmt[NoParams, int64]
vacStmt: SqliteStmt[NoParams, void]
template expectDb(x: auto): untyped =
# There's no meaningful error handling implemented for a corrupt database or
@ -46,7 +48,36 @@ proc new*(T: type ContentDB, path: string, inMemory = false): ContentDB =
else:
SqStoreRef.init(path, "fluffy").expectDb()
ContentDB(kv: kvStore db.openKvStore().expectDb())
let getSizeStmt = db.prepareStmt(
"SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size();",
NoParams, int64).get()
let vacStmt = db.prepareStmt(
"VACUUM;",
NoParams, void).get()
ContentDB(kv: kvStore db.openKvStore().expectDb(), sizeStmt: getSizeStmt, vacStmt: vacStmt)
proc reclaimSpace*(db: ContentDB): void =
## Runs sqlie VACUMM commands which rebuilds db, repacking it into a minimal amount of disk space
## Ideal mode of operation, is to run it after several deletes.
## Another options would be to run 'PRAGMA auto_vacuum = FULL;' statement at the start of
## db to leave it in sqlite power to clean up
db.vacStmt.exec().expectDb()
proc size*(db: ContentDB): int64 =
## Retrun current size of DB as product of sqlite page_count and page_size
## https://www.sqlite.org/pragma.html#pragma_page_count
## https://www.sqlite.org/pragma.html#pragma_page_size
## It returns total size of db i.e both data and metadata used to store content
## also it is worth noting that when deleting content, size may lags behind due
## to the way how deleting works in sqlite.
## Good description can be found in: https://www.sqlite.org/lang_vacuum.html
var size: int64 = 0
discard (db.sizeStmt.exec do(res: int64):
size = res).expectDb()
return size
proc get*(db: ContentDB, key: openArray[byte]): Option[seq[byte]] =
var res: Option[seq[byte]]

View File

@ -12,6 +12,14 @@ import
../network/state/state_content,
../content_db
proc genByteSeq(length: int): seq[byte] =
var i = 0
var resultSeq = newSeq[byte](length)
while i < length:
resultSeq[i] = byte(i)
inc i
return resultSeq
suite "Content Database":
# Note: We are currently not really testing something new here just basic
# underlying kvstore.
@ -43,3 +51,37 @@ suite "Content Database":
check:
val.isNone()
db.contains(key) == false
test "ContentDB size":
let
db = ContentDB.new("", inMemory = true)
let numBytes = 10000
let size1 = db.size()
db.put(@[1'u8], genByteSeq(numBytes))
let size2 = db.size()
db.put(@[2'u8], genByteSeq(numBytes))
let size3 = db.size()
db.put(@[2'u8], genByteSeq(numBytes))
let size4 = db.size()
check:
size2 > size1
size3 > size2
size3 == size4
db.del(@[2'u8])
db.del(@[1'u8])
let size5 = db.size()
check:
size4 == size5
db.reclaimSpace()
let size6 = db.size()
check:
# After space reclamation size of db should be equal to initial size
size6 == size1