Browse Source

separate files

Danilo Fragoso 10 tháng trước cách đây
mục cha
commit
31daf94cd6
5 tập tin đã thay đổi với 93 bổ sung47 xóa
  1. 3 0
      .gitignore
  2. 5 16
      command.zig
  3. 27 12
      main.zig
  4. 34 8
      socket.zig
  5. 24 11
      storage.zig

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+pizzakv
+main
+tools/

+ 5 - 16
command.zig

@@ -11,12 +11,7 @@ const Command = enum {
 fn parseKeyValue(buf: []const u8) ?[2][]const u8 {
     var kvIterator = std.mem.splitAny(u8, buf, "|");
     const key = kvIterator.first();
-    const value = kvIterator.next() orelse {
-        std.debug.print("No value found for key: {s}\n", .{key});
-        return null;
-    };
-
-    return [2][]const u8{ key, value };
+    return [2][]const u8{ key, kvIterator.rest() };
 }
 
 pub fn parse(msg: []const u8) ?[]const u8 {
@@ -32,10 +27,7 @@ pub fn parse(msg: []const u8) ?[]const u8 {
 
     switch (command) {
         .read => {
-            const key = messageIterator.next() orelse {
-                std.debug.print("No key provided for read command\n", .{});
-                return null;
-            };
+            const key = messageIterator.rest();
 
             const value = storage.read(key) orelse {
                 std.debug.print("Key not found in storage: {s}\n", .{key});
@@ -45,14 +37,11 @@ pub fn parse(msg: []const u8) ?[]const u8 {
             return value;
         },
         .write => {
-            const kvPair = messageIterator.next() orelse {
-                std.debug.print("No key-value pair provided for read command\n", .{});
-                return null;
-            };
+            const kvPair = messageIterator.rest();
 
             const kv = parseKeyValue(kvPair) orelse {
                 std.debug.print("Failed to parse key-value pair\n", .{});
-                return null;
+                return "false";
             };
 
             if (storage.write(kv[0], kv[1])) {
@@ -64,7 +53,7 @@ pub fn parse(msg: []const u8) ?[]const u8 {
         },
         .delete => {
             std.debug.print("Delete command received\n", .{});
-            return null;
+            return "false";
         },
         .status => {
             std.debug.print("Status command received\n", .{});

+ 27 - 12
main.zig

@@ -1,6 +1,8 @@
 const std = @import("std");
+
 const net = std.net;
 const posix = std.posix;
+const fmt = std.fmt;
 
 const socket = @import("socket.zig");
 const command = @import("command.zig");
@@ -9,7 +11,10 @@ const storage = @import("storage.zig");
 pub fn main() !void {
     const listener = try socket.init(8080);
     defer posix.close(listener);
-    std.debug.print("pizzakv!\n", .{});
+
+    std.debug.print("2025 pizzakv!\n<danilo.fragoso@dev>\n---------\n", .{});
+    std.debug.print("Commands:\n\nread key\nwrite key|value\ndelete key\nstatus\n", .{});
+    std.debug.print("---------\n", .{});
 
     while (true) {
         var client_address: net.Address = undefined;
@@ -19,20 +24,30 @@ pub fn main() !void {
             std.debug.print("error accept: {any}\n", .{err});
             continue;
         };
-        defer posix.close(conn);
+        //defer posix.close(conn);
 
         std.debug.print("Connection received\n", .{});
-        var buf: [128]u8 = undefined;
-        const n = try socket.read(conn, &buf);
+        var requestBuffer: [1024 * 1024]u8 = undefined;
+        var responseBuffer: [1024 * 1024]u8 = undefined;
+        while (true) {
+            const n = try socket.readUntilNewLine(conn, &requestBuffer);
+            if (n == 0) {
+                break;
+            }
 
-        const response = command.parse(buf[0..n]) orelse {
-            std.debug.print("Failed to parse message\n", .{});
-            continue;
-        };
+            const cmdResponse = command.parse(requestBuffer[0..n]) orelse {
+                std.debug.print("Failed to parse message\n", .{});
+                socket.write(conn, "false\n") catch |err| {
+                    std.debug.print("error writing: {any}\n", .{err});
+                };
+                continue;
+            };
 
-        socket.write(conn, response) catch |err| {
-            // This can easily happen, say if the client disconnects.
-            std.debug.print("error writing: {any}\n", .{err});
-        };
+            @memcpy(responseBuffer[0..cmdResponse.len], cmdResponse);
+            responseBuffer[cmdResponse.len] = '\n';
+            socket.write(conn, responseBuffer[0 .. cmdResponse.len + 1]) catch |err| {
+                std.debug.print("error writing: {any}\n", .{err});
+            };
+        }
     }
 }

+ 34 - 8
socket.zig

@@ -3,7 +3,7 @@ const net = std.net;
 const posix = std.posix;
 
 pub fn init(port: u16) !posix.socket_t {
-    const address = try std.net.Address.parseIp("127.0.0.1", port);
+    const address = try std.net.Address.parseIp("0.0.0.0", port);
 
     const tpe: u32 = posix.SOCK.STREAM;
     const protocol = posix.IPPROTO.TCP;
@@ -17,6 +17,36 @@ pub fn init(port: u16) !posix.socket_t {
     return listener;
 }
 
+pub fn readUntilCR(conn: posix.socket_t, buf: []u8) !usize {
+    var pos: usize = 0;
+    while (pos < buf.len) {
+        const n = try posix.read(conn, buf[pos .. pos + 1]);
+        if (n == 0) {
+            return pos;
+        }
+        if (buf[pos] == '\r') {
+            return pos + 1;
+        }
+        pos += n;
+    }
+    return pos;
+}
+
+pub fn readUntilNewLine(conn: posix.socket_t, buf: []u8) !usize {
+    var pos: usize = 0;
+    while (pos < buf.len) {
+        const n = try posix.read(conn, buf[pos .. pos + 1]);
+        if (n == 0) {
+            return pos;
+        }
+        if (buf[pos] == '\n') {
+            return pos + 1;
+        }
+        pos += n;
+    }
+    return pos;
+}
+
 pub fn read(conn: posix.socket_t, buf: []u8) !usize {
     var pos: usize = 0;
     while (pos < buf.len) {
@@ -30,12 +60,8 @@ pub fn read(conn: posix.socket_t, buf: []u8) !usize {
 }
 
 pub fn write(conn: posix.socket_t, msg: []const u8) !void {
-    var pos: usize = 0;
-    while (pos < msg.len) {
-        const written = try posix.write(conn, msg[pos..]);
-        if (written == 0) {
-            return error.Closed;
-        }
-        pos += written;
+    const written = try posix.write(conn, msg);
+    if (written != msg.len) {
+        return error.PartialWrite;
     }
 }

+ 24 - 11
storage.zig

@@ -1,35 +1,48 @@
 const std = @import("std");
 
-var buf: [1024 * 1024 * 100][]const u8 = undefined;
+const backend_size = 1024 * 1024 * 100;
+var buf: [backend_size][]const u8 = undefined;
+var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+const allocator = arena.allocator();
 
 pub fn hashKey(k: []const u8) u32 {
+    return djb2(k);
+    //return xoramasrosas(k);
+}
+
+pub fn djb2(key: []const u8) u32 {
+    var hash: u32 = 5381;
+
+    for (key) |c| {
+        hash = ((hash << 5) +% hash) +% c;
+    }
+
+    return hash;
+}
+
+pub fn xoramasrosas(k: []const u8) u32 {
     var hash: u32 = 17 * 22;
-    const xoramasrosas = "xoramasrosas";
+    const x = "xoramasrosas";
 
     for (k, 0..) |char, i| {
-        hash = hash +% (char ^ xoramasrosas[i % xoramasrosas.len]);
+        hash = hash +% (char ^ x[i % 12]) << 12;
     }
 
     return hash;
 }
 
 pub fn write(key: []const u8, value: []const u8) bool {
-    std.debug.print("Writing key: {s}, value: {s}\n", .{ key, value });
-    const hash = hashKey(key);
-
-    const valueCopy = std.heap.page_allocator.dupe(u8, value) catch {
+    const valueCopy = allocator.dupe(u8, value) catch {
         std.debug.print("Failed to duplicate value for key: {s}\n", .{key});
         return false;
     };
 
+    const hash = hashKey(key);
     buf[hash % buf.len] = valueCopy;
     return true;
 }
 
 pub fn read(key: []const u8) ?[]const u8 {
-    std.debug.print("Reading key: {s}\n", .{key});
     const hash = hashKey(key);
-    const value = buf[hash % buf.len];
-
-    return value;
+    return buf[hash % buf.len];
 }