A failing spec'd out bitcask, a start of something fun :)
This commit is contained in:
		
						commit
						e10a9e311f
					
				
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					zig-cache/
 | 
				
			||||||
 | 
					zig-out/
 | 
				
			||||||
 | 
					/release/
 | 
				
			||||||
 | 
					/debug/
 | 
				
			||||||
 | 
					/build/
 | 
				
			||||||
 | 
					/build-*/
 | 
				
			||||||
 | 
					/docgen_tmp/
 | 
				
			||||||
							
								
								
									
										7
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					# Bitcask - A Simple KV datastore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Do it simply and do it well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The Bitcask paper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					https://riak.com/assets/bitcask-intro.pdf
 | 
				
			||||||
							
								
								
									
										34
									
								
								build.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								build.zig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					const std = @import("std");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn build(b: *std.build.Builder) void {
 | 
				
			||||||
 | 
					    // Standard target options allows the person running `zig build` to choose
 | 
				
			||||||
 | 
					    // what target to build for. Here we do not override the defaults, which
 | 
				
			||||||
 | 
					    // means any target is allowed, and the default is native. Other options
 | 
				
			||||||
 | 
					    // for restricting supported target set are available.
 | 
				
			||||||
 | 
					    const target = b.standardTargetOptions(.{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Standard release options allow the person running `zig build` to select
 | 
				
			||||||
 | 
					    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
 | 
				
			||||||
 | 
					    const mode = b.standardReleaseOptions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const exe = b.addExecutable("bitcask", "src/main.zig");
 | 
				
			||||||
 | 
					    exe.setTarget(target);
 | 
				
			||||||
 | 
					    exe.setBuildMode(mode);
 | 
				
			||||||
 | 
					    exe.install();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const run_cmd = exe.run();
 | 
				
			||||||
 | 
					    run_cmd.step.dependOn(b.getInstallStep());
 | 
				
			||||||
 | 
					    if (b.args) |args| {
 | 
				
			||||||
 | 
					        run_cmd.addArgs(args);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const run_step = b.step("run", "Run the app");
 | 
				
			||||||
 | 
					    run_step.dependOn(&run_cmd.step);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const exe_tests = b.addTest("src/main.zig");
 | 
				
			||||||
 | 
					    exe_tests.setTarget(target);
 | 
				
			||||||
 | 
					    exe_tests.setBuildMode(mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const test_step = b.step("test", "Run unit tests");
 | 
				
			||||||
 | 
					    test_step.dependOn(&exe_tests.step);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										136
									
								
								src/Bitcask/bitcask.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/Bitcask/bitcask.zig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
				
			|||||||
 | 
					const std = @import("std");
 | 
				
			||||||
 | 
					const expect = std.testing.expect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const BitcaskFileError = error{
 | 
				
			||||||
 | 
					    AccessDenied,
 | 
				
			||||||
 | 
					    OutOfMemory,
 | 
				
			||||||
 | 
					    FileNotFound,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const BitCask = struct {
 | 
				
			||||||
 | 
					    const FILE_THRESHOLD_SIZE = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // std.StringArrayHashMap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // From the Bitcask paper, the API should look something like this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //** TODO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // What is the BitcaskHandel? How can I represent it?
 | 
				
			||||||
 | 
					    // Implement opening and closing files
 | 
				
			||||||
 | 
					    // Impement the spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ***
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:open(DirectoryName, Opts) Open a new or existing Bitcask datastore with additional options.
 | 
				
			||||||
 | 
					    // → BitCaskHandle | {error, any()} Valid options include read write (if this process is going to be a
 | 
				
			||||||
 | 
					    // writer and not just a reader) and sync on put (if this writer would
 | 
				
			||||||
 | 
					    // prefer to sync the write file after every write operation).
 | 
				
			||||||
 | 
					    // The directory must be readable and writable by this process, and
 | 
				
			||||||
 | 
					    // only one process may open a Bitcask with read write at a time.
 | 
				
			||||||
 | 
					    // bitcask:open(DirectoryName) Open a new or existing Bitcask datastore for read-only access.
 | 
				
			||||||
 | 
					    // → BitCaskHandle | {error, any()} The directory and all files in it must be readable by this process.
 | 
				
			||||||
 | 
					    fn open(directory_name: []const u8) BitcaskFileError!void {
 | 
				
			||||||
 | 
					        std.debug.print("Opening bitcask in dir {s}\n", .{directory_name});
 | 
				
			||||||
 | 
					        return error.FileNotFound;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:get(BitCaskHandle, Key) Retrieve a value by key from a Bitcask datastore.
 | 
				
			||||||
 | 
					    // → not found | {ok, Value}
 | 
				
			||||||
 | 
					    fn get(key: []const u8) error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        std.debug.print("Getting value with key {s}\n", .{key});
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:put(BitCaskHandle, Key, Value) Store a key and value in a Bitcask datastore.
 | 
				
			||||||
 | 
					    // → ok | {error, any()}
 | 
				
			||||||
 | 
					    fn put() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:delete(BitCaskHandle, Key) Delete a key from a Bitcask datastore.
 | 
				
			||||||
 | 
					    // → ok | {error, any()}
 | 
				
			||||||
 | 
					    fn delete() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:list keys(BitCaskHandle) List all keys in a Bitcask datastore.
 | 
				
			||||||
 | 
					    // → [Key] | {error, any()}
 | 
				
			||||||
 | 
					    fn list() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:fold(BitCaskHandle,Fun,Acc0) Fold over all K/V pairs in a Bitcask datastore.
 | 
				
			||||||
 | 
					    // → Acc Fun is expected to be of the form: F(K,V,Acc0) → Acc.
 | 
				
			||||||
 | 
					    fn fold() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:merge(DirectoryName) Merge several data files within a Bitcask datastore into a more
 | 
				
			||||||
 | 
					    // → ok | {error, any()} compact form. Also, produce hintfiles for faster startup.
 | 
				
			||||||
 | 
					    fn merge() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:sync(BitCaskHandle) Force any writes to sync to disk.
 | 
				
			||||||
 | 
					    // → ok
 | 
				
			||||||
 | 
					    fn sync() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bitcask:close(BitCaskHandle) Close a Bitcask data store and flush all pending writes (if any) to disk
 | 
				
			||||||
 | 
					    fn close() error{NotImplemented}!void {
 | 
				
			||||||
 | 
					        return error.NotImplemented;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: open" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.open("File");
 | 
				
			||||||
 | 
					    // bc.open("File") catch |err| {
 | 
				
			||||||
 | 
					    //     try expect(err == error.FileNotFound);
 | 
				
			||||||
 | 
					    // };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: get" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.get("key");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: put" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.put();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: delete" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.delete();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: list" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.list();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: fold" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.fold();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: merge" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.merge();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: sync" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.merge();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "Bitcask spec implementation: close" {
 | 
				
			||||||
 | 
					    const bc = BitCask;
 | 
				
			||||||
 | 
					    try bc.close();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								src/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/main.zig
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					const std = @import("std");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() !void {
 | 
				
			||||||
 | 
					    // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
 | 
				
			||||||
 | 
					    std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // stdout is for the actual output of your application, for example if you
 | 
				
			||||||
 | 
					    // are implementing gzip, then only the compressed bytes should be sent to
 | 
				
			||||||
 | 
					    // stdout, not any debugging messages.
 | 
				
			||||||
 | 
					    const stdout_file = std.io.getStdOut().writer();
 | 
				
			||||||
 | 
					    var bw = std.io.bufferedWriter(stdout_file);
 | 
				
			||||||
 | 
					    const stdout = bw.writer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try stdout.print("Run `zig build test` to run the tests.\n", .{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try bw.flush(); // don't forget to flush!
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "simple test" {
 | 
				
			||||||
 | 
					    var list = std.ArrayList(i32).init(std.testing.allocator);
 | 
				
			||||||
 | 
					    defer list.deinit(); // try commenting this out and see if zig detects the memory leak!
 | 
				
			||||||
 | 
					    try list.append(42);
 | 
				
			||||||
 | 
					    try std.testing.expectEqual(@as(i32, 42), list.pop());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user