コード例 #1
0
func realMain() int {
	var optr, optn bool
	flag.BoolVar(&optr, "r", false, "")
	flag.BoolVar(&optr, "read", false, "")
	flag.BoolVar(&optn, "n", false, "")
	flag.BoolVar(&optn, "new", false, "")
	flag.Usage = printUsage
	flag.Parse()

	if len(flag.Args()) == 0 {
		flag.Usage()
		return 0
	}

	if len(flag.Args()) != 1 {
		fmt.Fprintf(os.Stderr, "Error: illegal argument.\n")
		flag.Usage()
		return 1
	}

	path := flag.Arg(0)

	if optn {
		// only create new database
		if _, err := os.Stat(path); err == nil {
			fmt.Fprintf(os.Stderr, "Error: '%s' is already exists.\n", path)
			return 1
		}

		ds, err := bucketstore.Open(path, 0600, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v", err)
			return 1
		}
		ds.Close()
		return 0
	}

	// setup datastore options
	options := bucketstore.NewOptions()
	if optr {
		options.ReadOnly = true
	}

	// setup shell
	sh := shell.NewShell()
	sh.Path = path
	sh.Options = options

	if err := sh.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		return 1
	}

	return 0
}
コード例 #2
0
ファイル: shell.go プロジェクト: kohkimakimoto/bucketstore
func (sh *Shell) Run() error {
	// if the stdin is pipe, runs as a non-interactive mode
	if stat, _ := sh.Stdin.Stat(); (stat.Mode() & os.ModeCharDevice) == 0 {
		scanner := bufio.NewScanner(sh.Stdin)
		for scanner.Scan() {
			if err := sh.ExecCommand(scanner.Text()); err != nil {
				return err
			}
		}
		if err := scanner.Err(); err != nil {
			return err
		}

		return nil
	}

	// the following code runs on interactive mode

	if _, err := os.Stat(sh.Path); err != nil {
		// file not found.
		fmt.Printf("Database file '%s' was not found.\n", sh.Path)
		fmt.Print("Do you create initial database file? [y|N]: ")
		reader := bufio.NewReader(os.Stdin)
		if str, err := reader.ReadString('\n'); err == nil {
			str = strings.TrimRight(str, "\r\n")
			if str != "y" {
				return fmt.Errorf("the database has not been created.")
			}
		}

		// create new database.
		ds, err := bucketstore.Open(sh.Path, 0600, sh.Options)
		if err != nil {
			return err
		}
		ds.Close()
	}

	fmt.Println("Welcome to Bucketstore client. (hit ^D to exit)")
	fmt.Println("You can see the help by typing 'help' command.")

	fd := int(sh.Stdin.Fd())
	oldState, err := terminal.MakeRaw(fd)
	if err != nil {
		return err
	}
	defer terminal.Restore(fd, oldState)
	term := terminal.NewTerminal(&shell{r: sh.Stdin, w: sh.Stdout}, "["+filepath.Base(sh.Path)+"]> ")
	if term == nil {
		return fmt.Errorf("could not create terminal")
	}

	for {
		line, err := term.ReadLine()
		if err != nil {
			break
		}

		if err := sh.ExecCommand(line); err != nil {
			return err
		}

		if sh.exit {
			break
		}
	}

	return nil
}
コード例 #3
0
ファイル: example.go プロジェクト: kohkimakimoto/bucketstore
func main() {
	// open database
	db, err := bucketstore.Open("my.db", 0600, nil)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	bucket := db.Bucket("MyBucket")

	// put key/value item
	err = bucket.PutRaw([]byte("user001"), []byte(`{"name": "kohkimakimoto", "age": 36}`))
	if err != nil {
		panic(err)
	}

	// get value
	v, err := bucket.GetRaw([]byte("user001"))
	if err != nil {
		panic(err)
	}

	fmt.Println(string(v))
	// {"age":36,"name":"kohkimakimoto"}

	err = bucket.Delete([]byte("user001"))
	if err != nil {
		panic(err)
	}

	// put data
	err = bucket.PutRaw([]byte("user001"), []byte(`{"name": "hoge", "age": 20}`))
	if err != nil {
		panic(err)
	}
	err = bucket.PutRaw([]byte("user002"), []byte(`{"name": "foo", "age": 31}`))
	if err != nil {
		panic(err)
	}
	err = bucket.PutRaw([]byte("user003"), []byte(`{"name": "bar", "age": 18}`))
	if err != nil {
		panic(err)
	}
	err = bucket.PutRaw([]byte("user004"), []byte(`{"name": "aaa", "age": 40}`))
	if err != nil {
		panic(err)
	}
	err = bucket.PutRaw([]byte("user005"), []byte(`{"name": "xxx", "age": 41}`))
	if err != nil {
		panic(err)
	}
	err = bucket.PutRaw([]byte("user006"), []byte(`{"name": "ccc", "age": 50}`))
	if err != nil {
		panic(err)
	}

	// query
	q := bucket.Query()
	q.Filter = &bucketstore.PropValueRangeFilter{
		Property: "age",
		Min:      20,
		Max:      40,
	}
	items, err := q.AsList()
	if err != nil {
		panic(err)
	}

	for _, item := range items {
		fmt.Println(string(item.Key), string(item.Value))
	}
	// user001 {"age":20,"name":"hoge"}
	// user002 {"age":31,"name":"foo"}
	// user004 {"age":40,"name":"aaa"}

}
コード例 #4
0
ファイル: shell.go プロジェクト: kohkimakimoto/bucketstore
func (sh *Shell) ExecCommand(line string) error {
	// in order to prevent locking the database, get a new datastore instance by each commands.
	ds, err := bucketstore.Open(sh.Path, 0600, sh.Options)
	if err != nil {
		return err
	}
	sh.DB = ds
	defer func() {
		ds.Close()
		sh.DB = nil
	}()

	tokens, err := Tokenize(line)
	if err != nil {
		sh.outputError(fmt.Sprintf("%v", err), false)
		return nil
	}

	if len(tokens) == 0 {
		return nil
	}

	// parse global options
	var pretty bool
	var removedIndexes = []int{}
	for i, token := range tokens {
		if token.DataType == DataTypeTerm && strings.HasPrefix(token.Buf, "-") {
			switch token.Buf {
			case "-p":
				pretty = true
				removedIndexes = append(removedIndexes, i)
			}
		}
	}

	// remove global options from tokens
	for i, idx := range removedIndexes {
		removedI := idx - i
		tokens = append(tokens[:removedI], tokens[removedI+1:]...)
	}

	defer func() {
		if err := recover(); err != nil {
			sh.outputError(fmt.Sprintf("%v", err), pretty)
		}
	}()

	if len(tokens) >= 1 {
		if tokens[0].DataType != DataTypeTerm {
			sh.outputError("syntax error: it is not a valid command.", pretty)
			return nil
		}

		if fn, ok := Cmds[tokens[0].Buf]; ok {
			res, err := fn(sh, tokens[1:])
			if err != nil {
				sh.outputError(fmt.Sprintf("%v", err), pretty)
			}

			if res != nil {
				sh.output(res, pretty)
			}
		} else {
			sh.outputError(fmt.Sprintf("unknown command: %s", tokens[0].Buf), pretty)
		}
	}

	return nil
}