mirror of https://github.com/etcd-io/bbolt.git
104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/boltdb/bolt"
|
|
)
|
|
|
|
// Import converts an exported database dump into a new database.
|
|
func Import(path string, input string) {
|
|
f, err := os.Open(input)
|
|
if err != nil {
|
|
fatal(err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
// Read in entire dump.
|
|
var root []*rawMessage
|
|
if err := json.NewDecoder(f).Decode(&root); err != nil {
|
|
fatal(err)
|
|
}
|
|
|
|
// Open the database.
|
|
db, err := bolt.Open(path, 0600)
|
|
if err != nil {
|
|
fatal(err)
|
|
return
|
|
}
|
|
defer db.Close()
|
|
|
|
// Insert entire dump into database.
|
|
err = db.Update(func(tx *bolt.Tx) error {
|
|
// Loop over every message and create a bucket.
|
|
for _, message := range root {
|
|
// Validate that root messages are buckets.
|
|
if message.Type != "bucket" {
|
|
return fmt.Errorf("invalid root type: %q", message.Type)
|
|
}
|
|
|
|
// Create the bucket if it doesn't exist.
|
|
b, err := tx.CreateBucketIfNotExists(message.Key)
|
|
if err != nil {
|
|
return fmt.Errorf("create bucket: %s", err)
|
|
}
|
|
|
|
// Decode child messages.
|
|
var children []*rawMessage
|
|
if err := json.Unmarshal(message.Value, &children); err != nil {
|
|
return fmt.Errorf("decode children: %s", err)
|
|
}
|
|
|
|
// Import all the values into the bucket.
|
|
if err := importBucket(b, children); err != nil {
|
|
return fmt.Errorf("import bucket: %s", err)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
fatal("update: ", err)
|
|
}
|
|
}
|
|
|
|
func importBucket(b *bolt.Bucket, children []*rawMessage) error {
|
|
// Decode each message into a key/value pair.
|
|
for _, child := range children {
|
|
// Bucket messages are handled recursively.
|
|
if child.Type == "bucket" {
|
|
// Create the bucket if it doesn't exist.
|
|
subbucket, err := b.CreateBucketIfNotExists(child.Key)
|
|
if err != nil {
|
|
return fmt.Errorf("create bucket: %s", err)
|
|
}
|
|
|
|
// Decode child messages.
|
|
var subchildren []*rawMessage
|
|
if err := json.Unmarshal(child.Value, &subchildren); err != nil {
|
|
return fmt.Errorf("decode children: %s", err)
|
|
}
|
|
|
|
// Import subbucket.
|
|
if err := importBucket(subbucket, subchildren); err != nil {
|
|
return fmt.Errorf("import bucket: %s", err)
|
|
}
|
|
continue
|
|
}
|
|
|
|
// Non-bucket values are decoded from base64.
|
|
var value []byte
|
|
if err := json.Unmarshal(child.Value, &value); err != nil {
|
|
return fmt.Errorf("decode value: %s", err)
|
|
}
|
|
|
|
// Insert key/value into bucket.
|
|
if err := b.Put(child.Key, value); err != nil {
|
|
return fmt.Errorf("put: %s", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|