commit e06eb20b2f864c3be74cb958db559032afe8aaa4 Author: sdomino Date: Mon Dec 1 15:55:19 2014 -0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d3a228 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +# +.DS_Store +TODO diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..30cf8eb --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 nanobox-core + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c4fe9aa --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +scribble +==== \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..c106a17 --- /dev/null +++ b/main.go @@ -0,0 +1,218 @@ +package scribble + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/nanobox-core/nanobox-server/utils" +) + +// +type ( + + // Driver represents + Driver struct { + channels map[string]chan int + dir string + } + + // Transaction represents + Transaction struct { + Action string + Collection string + Resource string + Container interface{} + } +) + +// +var ( + debugging bool +) + +// Init +func (d *Driver) Init(opts map[string]string) int { + fmt.Printf("Creating database directory at '%v'...\n", opts["db_dir"]) + + debugging = (opts["debugging"] == "true") + + d.dir = opts["db_dir"] + + // + d.channels = make(map[string]chan int) + + // make a ping channel + ping := make(chan int) + d.channels["ping"] = ping + + // + if err := mkDir(d.dir); err != nil { + fmt.Printf("Unable to create dir '%v': %v", d.dir, err) + return 1 + } + + // + return 0 +} + +// Transact +func (d *Driver) Transact(trans Transaction) { + + // + done := d.getOrCreateChan(trans.Collection) + + // + switch trans.Action { + case "write": + go d.write(trans, done) + case "read": + go d.read(trans, done) + case "readall": + go d.readAll(trans, done) + case "delete": + go d.delete(trans, done) + default: + fmt.Println("Unsupported action ", trans.Action) + } + + // wait... + <-done +} + +// private + +// write +func (d *Driver) write(trans Transaction, done chan<- int) { + + // + dir := d.dir + "/" + trans.Collection + + // + if err := mkDir(dir); err != nil { + fmt.Println("Unable to create dir '%v': %v", dir, err) + os.Exit(1) + } + + // + file, err := os.Create(dir + "/" + trans.Resource) + if err != nil { + fmt.Printf("Unable to create file %v/%v: %v", trans.Collection, trans.Resource, err) + os.Exit(1) + } + + defer file.Close() + + // + b := utils.ToJSONIndent(trans.Container) + + _, err = file.WriteString(string(b)) + if err != nil { + fmt.Printf("Unable to write to file %v: %v", trans.Resource, err) + os.Exit(1) + } + + // release... + done <- 0 +} + +// read +func (d *Driver) read(trans Transaction, done chan<- int) interface{} { + + dir := d.dir + "/" + trans.Collection + + b, err := ioutil.ReadFile(dir + "/" + trans.Resource) + if err != nil { + fmt.Printf("Unable to read file %v/%v: %v", trans.Collection, trans.Resource, err) + os.Exit(1) + } + + if err := utils.FromJSON(b, trans.Container); err != nil { + panic(err) + } + + // release... + done <- 0 + + return trans.Container +} + +// readAll +func (d *Driver) readAll(trans Transaction, done chan<- int) { + + dir := d.dir + "/" + trans.Collection + + // + files, err := ioutil.ReadDir(dir) + + // if there is an error here it just means there are no evars so dont do anything + if err != nil { + } + + var f []string + + for _, file := range files { + b, err := ioutil.ReadFile(dir + "/" + file.Name()) + if err != nil { + panic(err) + } + + f = append(f, string(b)) + } + + // + if err := utils.FromJSON([]byte("["+strings.Join(f, ",")+"]"), trans.Container); err != nil { + panic(err) + } + + // release... + done <- 0 +} + +// delete +func (d *Driver) delete(trans Transaction, done chan<- int) { + + dir := d.dir + "/" + trans.Collection + + err := os.Remove(dir + "/" + trans.Resource) + if err != nil { + fmt.Printf("Unable to delete file %v/%v: %v", trans.Collection, trans.Resource, err) + os.Exit(1) + } + + // release... + done <- 0 +} + +// helpers + +// getChan +func (d *Driver) getOrCreateChan(channel string) chan int { + + c, ok := d.channels[channel] + + // if the chan doesn't exist make it + if !ok { + d.channels[channel] = make(chan int) + return d.channels[channel] + } + + return c +} + +// mkDir +func mkDir(d string) error { + + // + dir, _ := os.Stat(d) + + if dir == nil { + err := os.MkdirAll(d, 0755) + if err != nil { + return err + } + } + + return nil +}