diff --git a/src/fileEngine.zig b/src/fileEngine.zig index a859bde..6744624 100644 --- a/src/fileEngine.zig +++ b/src/fileEngine.zig @@ -100,61 +100,6 @@ pub const FileEngine = struct { } }; - // --------------------Logs-------------------- - // Make a lib out of it I think, like ZipponData, a ZipponLog - - const Level = enum { - Debug, - Info, - Warning, - Error, - Critical, - }; - - pub fn resetLog(self: FileEngine, file_name: []const u8) void { - const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return; - defer self.allocator.free(path); - - std.fs.cwd().deleteFile(path) catch {}; - _ = std.fs.cwd().createFile(path, .{}) catch return; - } - - pub fn createLog(self: FileEngine, file_name: []const u8) void { - const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return; - defer self.allocator.free(path); - - _ = std.fs.cwd().createFile(path, .{}) catch return; - } - - pub fn log(self: FileEngine, file_name: []const u8, level: Level, comptime format: []const u8, args: anytype) void { - const path = std.fmt.allocPrint(self.allocator, "{s}/LOG/{s}.log", .{ self.path_to_ZipponDB_dir, file_name }) catch return; - defer self.allocator.free(path); - - const file = std.fs.cwd().openFile(path, .{ .mode = .write_only }) catch return; - defer file.close(); - - file.seekFromEnd(0) catch return; - - const writer = file.writer(); - const now = DateTime.now(); - - // TODO: Use a format to add the 0 to be 00:00 and not 0:0 - var date_format_buffer = std.ArrayList(u8).init(self.allocator); - defer date_format_buffer.deinit(); - - now.format("YYYY/MM/DD-HH:mm:ss.SSSS", date_format_buffer.writer()) catch return; - writer.print("Time: {s} - ", .{date_format_buffer.items}) catch return; - switch (level) { - .Debug => writer.print("Debug - ", .{}) catch return, - .Info => writer.print("Info - ", .{}) catch return, - .Warning => writer.print("Warning - ", .{}) catch return, - .Error => writer.print("Error - ", .{}) catch return, - .Critical => writer.print("Critical - ", .{}) catch return, - } - writer.print(format, args) catch return; - writer.writeByte('\n') catch return; - } - // --------------------Other-------------------- pub fn readSchemaFile(allocator: Allocator, sub_path: []const u8, buffer: []u8) FileEngineError!usize { @@ -234,9 +179,14 @@ pub const FileEngine = struct { path_buff = std.fmt.allocPrint(self.allocator, "{s}/LOG", .{self.path_to_ZipponDB_dir}) catch return FileEngineError.MemoryError; cwd.makeDir(path_buff) catch |err| switch (err) { - error.PathAlreadyExists => {}, + error.PathAlreadyExists => return, else => return FileEngineError.CantMakeDir, }; + + self.allocator.free(path_buff); + path_buff = std.fmt.allocPrint(self.allocator, "{s}/LOG/log", .{self.path_to_ZipponDB_dir}) catch return FileEngineError.MemoryError; + + _ = cwd.createFile(path_buff, .{}) catch return FileEngineError.CantMakeFile; } /// Request a path to a schema file and then create the struct folder diff --git a/src/main.zig b/src/main.zig index 92dd767..c636306 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,6 +2,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; // TODO: Clean that +const DateTime = @import("types/date.zig").DateTime; const FileEngine = @import("fileEngine.zig").FileEngine; const cliTokenizer = @import("tokenizers/cli.zig").Tokenizer; const cliToken = @import("tokenizers/cli.zig").Token; @@ -25,6 +26,48 @@ const State = enum { end, }; +const log_allocator = std.heap.page_allocator; +var log_buff: [1024]u8 = undefined; +var log_path: []const u8 = undefined; + +const log = std.log.scoped(.cli); +pub const std_options = .{ + .logFn = myLog, +}; + +pub fn myLog( + comptime message_level: std.log.Level, + comptime scope: @Type(.EnumLiteral), + comptime format: []const u8, + args: anytype, +) void { + const level_txt = comptime message_level.asText(); + const prefix = if (scope == .default) " - " else "(" ++ @tagName(scope) ++ ") - "; + + const potential_file: ?std.fs.File = std.fs.cwd().openFile(log_path, .{ .mode = .write_only }) catch null; + + const now = DateTime.now(); + var date_format_buffer = std.ArrayList(u8).init(log_allocator); + defer date_format_buffer.deinit(); + now.format("YYYY/MM/DD-HH:mm:ss.SSSS", date_format_buffer.writer()) catch return; + + if (potential_file) |file| { + file.seekFromEnd(0) catch return; + const writer = file.writer(); + + writer.print("{s}{s}Time: {s} - ", .{ level_txt, prefix, date_format_buffer.items }) catch return; + writer.print(format, args) catch return; + writer.writeByte('\n') catch return; + file.close(); + } else { + const writer = std.io.getStdErr().writer(); + + writer.print("{s}{s}Time: {s} - ", .{ level_txt, prefix, date_format_buffer.items }) catch return; + writer.print(format, args) catch return; + writer.writeByte('\n') catch return; + } +} + // TODO: If an argument is given when starting the binary, it is the db path pub fn main() !void { var state: State = .expect_main_command; @@ -36,48 +79,9 @@ pub fn main() !void { .leak => std.log.debug("We fucked it up bro...\n", .{}), }; - const path_env_variable = utils.getEnvVariables(allocator, "ZIPPONDB_PATH"); - var file_engine: FileEngine = undefined; + var file_engine = try initFileEngine.init(allocator, null); defer file_engine.deinit(); - if (path_env_variable) |path| { - std.debug.print("Found envirionment variable ZIPPONDB_PATH: {s}.\n", .{path}); - var to_init = true; - _ = std.fs.cwd().openDir(path, .{}) catch { - std.debug.print("{s} directory not found, creating it\n", .{path}); - std.fs.cwd().makeDir(path) catch { - std.debug.print("{s} couldnt be make. Please use 'db new' or 'db use'.\n", .{path}); - file_engine = FileEngine.init(allocator, ""); - to_init = false; - }; - }; - if (to_init) { - file_engine = FileEngine.init(allocator, path); - try file_engine.checkAndCreateDirectories(); - //file_engine.createLog("main"); - file_engine.log("main", .Info, "Found envirionment variable ZIPPONDB_PATH: {s}", .{path}); - } - - // Check if the db have a schema - if (!file_engine.isSchemaFileInDir()) { - std.debug.print("Database don't have any schema. Checking if ZIPPONDB_SCHEMA env variable exist.\n", .{}); - const schema_env_variable = utils.getEnvVariables(allocator, "ZIPPONDB_SCHEMA"); - if (schema_env_variable) |schema| { - std.debug.print("Found envirionment variable ZIPPONDB_SCHEMA {s}.\n", .{schema}); - file_engine.initDataFolder(schema) catch { - std.debug.print("Couldn't use {s} as schema.\n", .{schema}); - }; - } else { - std.debug.print("No envirionment variable ZIPPONDB_SCHEMA found.\n", .{}); - } - } else { - std.debug.print("Database have a schema.\n", .{}); - } - } else { - std.debug.print("No envirionment variable ZIPPONDB_PATH found.\n", .{}); - file_engine = FileEngine.init(allocator, ""); - } - const line_buf = try allocator.alloc(u8, BUFFER_SIZE); defer allocator.free(line_buf); @@ -86,7 +90,7 @@ pub fn main() !void { const line = try std.io.getStdIn().reader().readUntilDelimiterOrEof(line_buf, '\n'); if (line) |line_str| { - file_engine.log("main", .Info, "Query received: {s}", .{line_str}); + log.debug("Query received: {s}", .{line_str}); const null_term_line_str = try allocator.dupeZ(u8, line_str[0..line_str.len]); defer allocator.free(null_term_line_str); @@ -175,7 +179,7 @@ pub fn main() !void { .expect_path_to_db => switch (token.tag) { .identifier => { file_engine.deinit(); - file_engine = FileEngine.init(allocator, try allocator.dupe(u8, toker.getTokenSlice(token))); + file_engine = try initFileEngine.init(allocator, try allocator.dupe(u8, toker.getTokenSlice(token))); send("Successfully started using the database!", .{}); state = .end; }, @@ -273,7 +277,10 @@ pub fn main() !void { .quit, .end => unreachable, }; - if (state == .quit) break; + if (state == .quit) { + log.info("Bye bye\n", .{}); + break; + } } } } @@ -287,7 +294,7 @@ pub fn runQuery(null_term_query_str: [:0]const u8, file_engine: *FileEngine) voi var parser = ziqlParser.init(allocator, &toker, file_engine); parser.parse() catch |err| { - file_engine.log("main", .Error, "Error parsing: {any}", .{err}); + log.err("Error parsing: {any}", .{err}); }; switch (gpa.deinit()) { @@ -296,4 +303,66 @@ pub fn runQuery(null_term_query_str: [:0]const u8, file_engine: *FileEngine) voi } } -// TODO: Put that in the FileEngine +/// Simple struct to manage the init of the FileEngine, mostly managing if env path is here and init the directories, ect +const initFileEngine = struct { + fn init(allocator: std.mem.Allocator, potential_path: ?[]const u8) !FileEngine { + if (potential_path) |p| { + log_path = try std.fmt.bufPrint(&log_buff, "{s}/LOG/log", .{p}); + log.info("Start using database path: {s}.", .{p}); + return try initWithPath(allocator, p); + } + + const path = utils.getEnvVariable(allocator, "ZIPPONDB_PATH"); + defer if (path) |p| allocator.free(p); + + if (path) |p| { + log_path = try std.fmt.bufPrint(&log_buff, "{s}/LOG/log", .{p}); + log.info("Found environment variable ZIPPONDB_PATH: {s}.", .{p}); + return try initWithPath(allocator, p); + } else { + log.info("No environment variable ZIPPONDB_PATH found.", .{}); + return FileEngine.init(allocator, ""); + } + } + + fn initWithPath(allocator: std.mem.Allocator, path: []const u8) !FileEngine { + try ensureDirectoryExists(path); + var file_engine = FileEngine.init(allocator, path); + try file_engine.checkAndCreateDirectories(); + + if (!file_engine.isSchemaFileInDir()) { + try initSchema(allocator, &file_engine); + } else { + std.debug.print("Database has a schema.\n", .{}); + } + + return file_engine; + } + + fn ensureDirectoryExists(path: []const u8) !void { + _ = std.fs.cwd().openDir(path, .{}) catch |err| { + if (err == error.FileNotFound) { + log.info("{s} directory not found, creating it\n", .{path}); + try std.fs.cwd().makeDir(path); + return; + } else { + return err; + } + }; + } + + fn initSchema(allocator: std.mem.Allocator, file_engine: *FileEngine) !void { + log.debug("Database doesn't have any schema. Checking if ZIPPONDB_SCHEMA env variable exists.", .{}); + const schema = utils.getEnvVariable(allocator, "ZIPPONDB_SCHEMA"); + defer if (schema) |s| allocator.free(s); + + if (schema) |s| { + log.debug("Found environment variable ZIPPONDB_SCHEMA: {s}.", .{s}); + file_engine.initDataFolder(s) catch { + std.debug.print("Couldn't use {s} as schema.\n", .{s}); + }; + } else { + log.debug("No environment variable ZIPPONDB_SCHEMA found.", .{}); + } + } +}; diff --git a/src/stuffs/utils.zig b/src/stuffs/utils.zig index bf0f04c..792d746 100644 --- a/src/stuffs/utils.zig +++ b/src/stuffs/utils.zig @@ -1,7 +1,7 @@ const std = @import("std"); const ZipponError = @import("errors.zig").ZipponError; -pub fn getEnvVariables(allocator: std.mem.Allocator, variable: []const u8) ?[]const u8 { +pub fn getEnvVariable(allocator: std.mem.Allocator, variable: []const u8) ?[]const u8 { var env_map = std.process.getEnvMap(allocator) catch return null; defer env_map.deinit();