storage.zig 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. const std = @import("std");
  2. const index = @import("index.zig");
  3. const hashing = @import("hashing.zig");
  4. const persistence = @import("persistence.zig");
  5. const MAX_RECORDS = 10_000_000;
  6. const Entry = struct {
  7. key: []const u8,
  8. value: []const u8,
  9. next: ?*Entry,
  10. };
  11. var buf: [MAX_RECORDS]?*Entry = undefined;
  12. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  13. const allocator = arena.allocator();
  14. const EMPTY = "";
  15. var mutex: std.Thread.Mutex = .{};
  16. pub fn writeVolatile(key: []const u8, value: []const u8) ?*Entry {
  17. const hash = hashing.hashKey(key);
  18. const bufIdx = hash % buf.len;
  19. var current = buf[bufIdx];
  20. while (current) |entry| {
  21. if (std.mem.eql(u8, entry.key, key)) {
  22. allocator.free(entry.value);
  23. entry.value = allocator.dupe(u8, value) catch return null;
  24. return entry;
  25. }
  26. current = entry.next;
  27. }
  28. const newEntry = allocator.create(Entry) catch return null;
  29. errdefer allocator.destroy(newEntry);
  30. newEntry.* = Entry{
  31. .key = allocator.dupe(u8, key) catch return null,
  32. .value = allocator.dupe(u8, value) catch return null,
  33. .next = buf[bufIdx],
  34. };
  35. buf[bufIdx] = newEntry;
  36. index.insert(key);
  37. return newEntry;
  38. }
  39. pub fn write(key: []const u8, value: []const u8) bool {
  40. mutex.lock();
  41. defer mutex.unlock();
  42. const entry = writeVolatile(key, value);
  43. if (entry == null) {
  44. return false;
  45. }
  46. persistence.persist('W', entry.?.key, entry.?.value);
  47. return true;
  48. }
  49. pub fn read(key: []const u8) ?[]const u8 {
  50. mutex.lock();
  51. defer mutex.unlock();
  52. const hash = hashing.hashKey(key);
  53. var current = buf[hash % buf.len];
  54. while (current) |entry| {
  55. if (std.mem.eql(u8, entry.key, key)) {
  56. return entry.value;
  57. }
  58. current = entry.next;
  59. }
  60. return null;
  61. }
  62. pub fn deleteVolatile(key: []const u8) bool {
  63. const hash = hashing.hashKey(key);
  64. const bufIdx = hash % buf.len;
  65. var current = buf[bufIdx];
  66. var prev: ?*Entry = null;
  67. while (current) |entry| {
  68. if (std.mem.eql(u8, entry.key, key)) {
  69. if (prev) |p| {
  70. p.next = entry.next;
  71. } else {
  72. buf[bufIdx] = entry.next;
  73. }
  74. index.delete(key);
  75. allocator.free(entry.key);
  76. allocator.free(entry.value);
  77. allocator.destroy(entry);
  78. return true;
  79. }
  80. prev = entry;
  81. current = entry.next;
  82. }
  83. return false;
  84. }
  85. pub fn delete(key: []const u8) bool {
  86. mutex.lock();
  87. defer mutex.unlock();
  88. const deleted = deleteVolatile(key);
  89. if (deleted) {
  90. persistence.persist('D', key, "");
  91. }
  92. return deleted;
  93. }