ref: 2ab7efc23fd2137ce88d328441900e0a439a3508
dir: /appl/cmd/dddb.b/
implement Dddb; include "sys.m"; sys: Sys; include "arg.m"; include "draw.m"; include "readdir.m"; readdir: Readdir; include "string.m"; strm: String; include "lists.m"; lists: Lists; include "arrays.m"; arrays: Arrays; include "convcs.m"; convcs: Convcs; include "config.b"; include "ctlfs.b"; include "nodereg.b"; stderr: ref Sys->FD; debug: int; DBVER: con "v0.1.0"; DCS: con "utf-8"; error(s: string) { sys->fprint(stderr, "dddb: %s\n", s); raise "dddb:error"; } Epoolnotfound : con "pool not found"; Epoolavail : con "pool not available"; Dddb: module { init: fn(nil: ref Draw->Context, args: list of string); # Configuration section Config: adt { name: string; sysn: string; addr: string; storage: string; fswrks: int; nodes: list of NodeConfig; open: fn(nodename: string, mtpt: string): Config; }; NodeConfig: adt { name: string; sysn: string; addr: string; keyfile: string; storage: string; psize: int; fswrks: int; new: fn(entry: ref Dbentry): NodeConfig; }; # Registry section RegTMsg: adt { pick { GetNodes => ChanClose => RefreshAll => Check or Refresh or Close => nodename: string; } }; RegRMsg: adt { pick { Error => err: string; StatusAll => status: list of ref RegRMsg.Status; Status => count: int; poolsize: int; NodeList => names: list of string; } }; NodePool: adt { cfg: NodeConfig; instances: list of string; init: fn(r: self ref NodePool): int; check: fn(r: self ref NodePool): int; refresh: fn(r: self ref NodePool): int; newinst: fn(r: self ref NodePool, mtpt: string): string; close: fn(r: self ref NodePool); }; DbRegistry: adt { nodepools: list of ref NodePool; # rchans: list of chan of ref RegRMsg; # tchans: list of chan of ref RegTMsg; new: fn(cfgs: list of NodeConfig): ref DbRegistry; init: fn(r: self ref DbRegistry); # run: fn(r: self ref DbRegistry); changen: fn(r: self ref DbRegistry): (chan of ref RegTMsg, chan of ref RegRMsg); close: fn(r: self ref DbRegistry); }; }; init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; arg := load Arg Arg->PATH; readdir = load Readdir Readdir->PATH; strm = load String String->PATH; lists = load Lists Lists->PATH; arrays = load Arrays Arrays->PATH; convcs = load Convcs Convcs->PATH; dial = load Dial Dial->PATH; auth = load Auth Auth->PATH; keyring = load Keyring Keyring->PATH; if(sys == nil) error("dddb: sys module not found"); if(arg == nil) error("dddb: arg module not found"); if(readdir == nil) error("dddb: readdir module not found"); if(strm == nil) error("dddb: strm module not found"); if(lists == nil) error("dddb: lists module not found"); if(convcs == nil) error("dddb: convcs module not found"); if(dial == nil) error("dddb: dial module not found"); if(auth == nil) error("dddb: auth module not found"); if(keyring == nil) error("dddb: keyring module not found"); convcs->init(nil); (btos, btoserr) := convcs->getbtos(DCS); if(btos == nil) error(sys->sprint("dddb: %s character set: %s", DCS, btoserr)); (stob, stoberr) := convcs->getstob(DCS); if(stob == nil) error(sys->sprint("dddb: %s character set: %s", DCS, stoberr)); stderr = sys->fildes(2); cfgpath: string = ""; keyfile: string = nil; algs: list of string = nil; arg->init(args); arg->setusage(arg->progname()+ " [-d] [-k keyfile] [-C algs] [-c config] nodename"); while((c := arg->opt()) != 0) case c { 'd' => debug++; 'c' => cfgpath = arg->earg(); 'k' => keyfile = arg->earg(); 'C' => algsstr := arg->earg(); (nil, algs) = sys->tokenize(algsstr, ","); * => sys->fprint(stderr, "bad option: -%c\n", c); arg->usage(); } args = arg->argv(); if(len args != 1) { sys->fprint(stderr, "dddb: bad usage\n"); arg->usage(); } nodename := hd args; if(debug) sys->fprint(stderr, "dddb: opening config file\n"); cfg := Config.open(nodename, cfgpath); if(debug) { sys->fprint(stderr, "dddb: database parms:\n"); sys->fprint(stderr, "cfg.name: %s\n", cfg.name); sys->fprint(stderr, "cfg.sysn: %s\n", cfg.sysn); sys->fprint(stderr, "cfg.storage: %s\n", cfg.storage); sys->fprint(stderr, "cfg.fswrks: %d\n", cfg.fswrks); } if(debug) sys->fprint(stderr, "dddb: creating and running node registry\n"); sys->pctl(Sys->NEWPGRP, nil); dbreg := DbRegistry.new(cfg.nodes); spawn dbreg.init(); # spawn dbreg.run(); if(debug) sys->fprint(stderr, "dddb: running ctlfs\n"); run_ctlfs(cfg, dbreg, keyfile, algs); sys->fprint(stderr, "dddb: performing shutdown\n"); dbreg.close(); sys->fprint(stderr, "dddb: all components shut off\n"); } user(): string { user := readfile("#c/user"); if(user == nil) return "none"; return user; } readfile(file: string): string { fd := sys->open(file, Sys->OREAD); if(fd == nil) return nil; buf := array[1024] of byte; n := sys->read(fd, buf, len buf); if(n < 0) return nil; return string buf[0:n]; } writefile(file: string, s: string): int { fd := sys->open(file, Sys->OWRITE); if(fd == nil) return -1; buf := array of byte s; n := sys->write(fd, buf, len buf); return n; } dir(name: string, perm: int, qid: big): Sys->Dir { d := sys->zerodir; user := user(); d.name = name; d.uid = user; d.gid = user; d.qid.path = qid; if (perm & Sys->DMDIR) d.qid.qtype = Sys->QTDIR; else d.qid.qtype = Sys->QTFILE; d.mode = perm; return d; } diru(name: string, perm: int, qid: big, user: string): Sys->Dir { d := sys->zerodir; d.name = name; d.uid = user; d.gid = user; d.qid.path = qid; if (perm & Sys->DMDIR) d.qid.qtype = Sys->QTDIR; else d.qid.qtype = Sys->QTFILE; d.mode = perm; return d; } joinstr(items: list of string, sep: string): string { s := ""; citem := hd items; items = tl items; s = s + citem; while(items != nil) { citem = hd items; items = tl items; s = s + sep + citem; } return s; }