// Open opens a database at the provided path. // If the file does not exist then it will be created automatically. func Open(path string) (*DB, error) { db := &DB{} db.keys = btree.New(16, nil) db.exps = btree.New(16, &exctx{db}) db.idxs = make(map[string]*index) db.config = Config{ SyncPolicy: EverySecond, AutoShrinkPercentage: 100, AutoShrinkMinSize: 32 * 1024 * 1024, } db.persist = path != ":memory:" if db.persist { var err error // Hardcoding 0666 as the default mode. db.file, err = os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0666) if err != nil { return nil, err } if err := db.load(); err != nil { _ = db.file.Close() return nil, err } db.bufw = bufio.NewWriter(db.file) } // start the background manager. go db.backgroundManager() return db, nil }
// createIndex is called by CreateIndex() and CreateSpatialIndex() func (db *DB) createIndex( name string, pattern string, less func(a, b string) bool, rect func(item string) (min, max []float64), ) error { db.mu.Lock() defer db.mu.Unlock() if db.closed { return ErrDatabaseClosed } if name == "" { return ErrIndexExists } if _, ok := db.idxs[name]; ok { return ErrIndexExists } idx := &index{ name: name, pattern: pattern, less: less, rect: rect, db: db, } if less != nil { idx.btr = btree.New(16, idx) } if rect != nil { idx.rtr = rtree.New(idx) } db.keys.Ascend(func(item btree.Item) bool { dbi := item.(*dbItem) if !wildcardMatch(dbi.key, idx.pattern) { return true } if less != nil { idx.btr.ReplaceOrInsert(dbi) } if rect != nil { idx.rtr.Insert(dbi) } return true }) db.idxs[name] = idx return nil }