nimtracker.nim 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2016 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Memory tracking support for Nim.
  10. when not defined(memTracker) and not isMainModule:
  11. {.error: "Memory tracking support is turned off!".}
  12. {.push memtracker: off.}
  13. # we import the low level wrapper and are careful not to use Nim's
  14. # memory manager for anything here.
  15. import sqlite3
  16. var
  17. dbHandle: PSqlite3
  18. insertStmt {.threadvar.}: Pstmt
  19. const insertQuery = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
  20. template sbind(x: int; value) =
  21. when value is cstring:
  22. let ret = insertStmt.bindText(x, value, value.len.int32, SQLITE_TRANSIENT)
  23. if ret != SQLITE_OK:
  24. quit "could not bind value"
  25. else:
  26. let ret = insertStmt.bindInt64(x, value)
  27. if ret != SQLITE_OK:
  28. quit "could not bind value"
  29. when defined(memTracker):
  30. proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [], gcsafe.} =
  31. if insertStmt.isNil:
  32. if prepare_v2(dbHandle, insertQuery,
  33. insertQuery.len, insertStmt, nil) != SQLITE_OK:
  34. quit "could not bind query to insertStmt " & $sqlite3.errmsg(dbHandle)
  35. for i in 0..log.count-1:
  36. var success = false
  37. let e = log.data[i]
  38. discard sqlite3.reset(insertStmt)
  39. discard clearBindings(insertStmt)
  40. sbind 1, e.op
  41. sbind(2, cast[int](e.address))
  42. sbind 3, e.size
  43. sbind 4, e.file
  44. sbind 5, e.line
  45. if step(insertStmt) == SQLITE_DONE:
  46. success = true
  47. if not success:
  48. quit "could not write to database! " & $sqlite3.errmsg(dbHandle)
  49. proc execQuery(q: string) =
  50. var s: Pstmt
  51. if prepare_v2(dbHandle, q, q.len.int32, s, nil) == SQLITE_OK:
  52. discard step(s)
  53. if finalize(s) != SQLITE_OK:
  54. quit "could not finalize " & $sqlite3.errmsg(dbHandle)
  55. else:
  56. quit "could not prepare statement " & $sqlite3.errmsg(dbHandle)
  57. proc setupDb() =
  58. execQuery """create table if not exists tracking(
  59. id integer primary key,
  60. op varchar not null,
  61. address integer not null,
  62. size integer not null,
  63. file varchar not null,
  64. line integer not null
  65. )"""
  66. execQuery "delete from tracking"
  67. if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
  68. setupDb()
  69. const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
  70. if prepare_v2(dbHandle, insertQuery,
  71. insertQuery.len, insertStmt, nil) == SQLITE_OK:
  72. when defined(memTracker):
  73. setTrackLogger logEntries
  74. else:
  75. quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
  76. else:
  77. quit "could not setup sqlite " & $sqlite3.errmsg(dbHandle)
  78. {.pop.}