Files
jormun-db/main.odin
2026-02-15 08:55:22 -05:00

138 lines
4.0 KiB
Odin

package main
import "core:fmt"
import "core:mem"
import "core:os"
import "core:strconv"
//import "core:strings" // I know we'll use in future but because we're not right now, compiler is complaining
import "rocksdb"
Config :: struct {
host: string,
port: int,
data_dir: string,
verbose: bool,
}
main :: proc() {
// Parse configuration
config := parse_config()
// Print banner
print_banner(config)
// Create data directory
os.make_directory(config.data_dir)
// Initialize storage engine
db, err := rocksdb.db_open(config.data_dir, true)
if err != .None {
fmt.eprintln("Failed to initialize storage:", err)
os.exit(1)
}
defer rocksdb.db_close(&db)
fmt.printfln("Storage engine initialized at %s", config.data_dir)
fmt.printfln("Starting DynamoDB-compatible server on %s:%d", config.host, config.port)
// Create HTTP server
server_config := default_server_config()
// For now, use a simple echo handler until we implement the full DynamoDB handler
server, server_ok := server_init(
context.allocator,
config.host,
config.port,
handle_http_request,
&db,
server_config,
)
if !server_ok {
fmt.eprintln("Failed to initialize HTTP server")
os.exit(1)
}
defer server_stop(&server)
fmt.println("Ready to accept connections!")
// Start server (blocks)
if !server_start(&server) {
fmt.eprintln("Server failed to start")
os.exit(1)
}
}
// Temporary HTTP request handler
// TODO: Replace with full DynamoDB handler once dynamodb/handler.odin is implemented
handle_http_request :: proc(ctx: rawptr, request: ^HTTP_Request, request_alloc: mem.Allocator) -> HTTP_Response {
//db := cast(^rocksdb.DB)ctx // I know we'll use in future but because we're not right now, compiler is complaining
response := response_init(request_alloc)
response_add_header(&response, "Content-Type", "application/x-amz-json-1.0")
response_add_header(&response, "x-amzn-RequestId", "local-request-id")
// Get X-Amz-Target header
target := request_get_header(request, "X-Amz-Target")
if t, ok := target.?; ok {
// Echo back the operation for now
body := fmt.aprintf("{{\"operation\":\"%s\",\"status\":\"not_implemented\"}}", t)
response_set_body(&response, transmute([]byte)body)
} else {
response_set_status(&response, .Bad_Request)
response_set_body(&response, transmute([]byte)string("{\"error\":\"Missing X-Amz-Target header\"}"))
}
return response
}
parse_config :: proc() -> Config {
config := Config{
host = "0.0.0.0",
port = 8002,
data_dir = "./data",
verbose = false,
}
// Environment variables
if port_str, env_ok := os.lookup_env("JORMUN_PORT"); env_ok {
if port, parse_ok := strconv.parse_int(port_str); parse_ok {
config.port = port
}
}
if host, ok := os.lookup_env("JORMUN_HOST"); ok {
config.host = host
}
if data_dir, ok := os.lookup_env("JORMUN_DATA_DIR"); ok {
config.data_dir = data_dir
}
if verbose, ok := os.lookup_env("JORMUN_VERBOSE"); ok {
config.verbose = verbose == "1"
}
// TODO: Parse command line arguments
return config
}
print_banner :: proc(config: Config) {
banner := `
╔═══════════════════════════════════════════════╗
║ ║
║ ╦╔═╗╦═╗╔╦╗╦ ╦╔╗╔╔╦╗╔╗ ║
║ ║║ ║╠╦╝║║║║ ║║║║ ║║╠╩╗ ║
║ ╚╝╚═╝╩╚═╩ ╩╚═╝╝╚╝═╩╝╚═╝ ║
║ ║
║ DynamoDB-Compatible Database ║
║ Powered by RocksDB + Odin ║
║ ║
╚═══════════════════════════════════════════════╝
`
fmt.println(banner)
fmt.printfln(" Port: %d | Data Dir: %s\n", config.port, config.data_dir)
}