Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | store: put/get testimony via consistent interface; file system and bolt implementation |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
4950d4133b9dae36903e76b02419c352 |
User & Date: | dnc 2019-12-11 20:21:53 |
Context
2019-12-13
| ||
04:19 | model: NewAuthority helper formats authority string consistently check-in: e0fadea8cc user: dnc tags: trunk | |
2019-12-11
| ||
20:21 | store: put/get testimony via consistent interface; file system and bolt implementation check-in: 4950d4133b user: dnc tags: trunk | |
20:20 | model: helpers for tests (in other packages) check-in: 40f95cd722 user: dnc tags: trunk | |
Changes
Added store/boltstore/boltstore.go.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
// Copyright (C) 2019 David N. Cohen // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. package boltstore import ( "log" "github.com/boltdb/bolt" "src.d10.dev/hancock/model" ) type boltStore struct { *bolt.DB bucket []byte } func NewBoltStore(db *bolt.DB) (*boltStore, error) { this := &boltStore{db, []byte("hancockd")} err := db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists(this.bucket) return err }) return this, err } func (this *boltStore) PutTestimony(testimony model.Testimony) (*model.TestimonyKey, error) { log.Println("boltStore.PutTestimony()") // troubleshoot // use key format consistent with kademlia tkey := testimony.Key() key := tkey.KID().Sum() value, err := model.Encode(testimony) if err != nil { return nil, err } // persist to underlying db err = this.DB.Batch(func(tx *bolt.Tx) error { b := tx.Bucket(this.bucket) return b.Put(key, value) }) return tkey, err } func (this *boltStore) GetTestimony(tkey model.TestimonyKey) (testimony *model.Testimony, err error) { log.Println("boltStore.FindTestimony()", this) // troubleshoot key := tkey.KID().Sum() err = this.DB.View(func(tx *bolt.Tx) (err error) { b := tx.Bucket(this.bucket) v := b.Get(key) if v != nil { testimony = new(model.Testimony) err = model.Decode(testimony, v) } return }) return } |
Added store/boltstore/boltstore_test.go.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
// Copyright (C) 2019 David N. Cohen // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. package boltstore import ( "io/ioutil" "os" "path/filepath" "reflect" "testing" "github.com/boltdb/bolt" "src.d10.dev/hancock/model/modeltest" "src.d10.dev/hancock/store" ) // Ensure interface properly defined and implemented func TestStoreIsImplemented(t *testing.T) { var _ store.Store = &boltStore{} // compile time test } func TestBoltStore(t *testing.T) { testimony, err := modeltest.NewTestTestimony("hello world") if err != nil { t.Error(err) return } dir, err := ioutil.TempDir("", "TestBoltStore") if err != nil { t.Error(err) return } db, err := bolt.Open(filepath.Join(dir, "TestBoltStore.db"), 0600, nil) if err != nil { t.Error(err) return } defer db.Close() s, err := NewBoltStore(db) if err != nil { t.Error(err) return } k, err := s.PutTestimony(*testimony) if err != nil { t.Error(err) return } test, err := s.GetTestimony(*k) if err != nil { t.Error(err) } if !reflect.DeepEqual(test, testimony) { t.Errorf("got \n%v, wanted \n%v; see boltstore in %q", test, testimony, dir) } else { // passed test, clean up t.Logf("put, then got, testimony (%v)", k) defer os.RemoveAll(dir) } } |
Added store/store.go.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
// Copyright (C) 2019 David N. Cohen // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. package store import ( "fmt" "io/ioutil" "os" "path/filepath" "src.d10.dev/hancock/model" ) type Store interface { PutTestimony(model.Testimony) (*model.TestimonyKey, error) GetTestimony(model.TestimonyKey) (*model.Testimony, error) } type fileStore struct { directory string } func NewFileStore(directory string) fileStore { return fileStore{directory: directory} } func (this fileStore) PutTestimony(testimony model.Testimony) (*model.TestimonyKey, error) { tkey := testimony.Key() // filepath.Join() turns the key values into directories. If we // used flat file names, we might exceed filesystem limits for // number of files. path := filepath.Join(this.directory, filepath.Join(tkey.Split()...)) err := os.MkdirAll(filepath.Dir(path), os.ModePerm) if err != nil { return nil, fmt.Errorf("failed to store testimony file (%q): %w", path, err) } encoded, err := model.Encode(testimony) err = ioutil.WriteFile(path, encoded, 0644) if err != nil { return nil, fmt.Errorf("failed to store testimony file (%q): %w", path, err) } return tkey, nil } func (this fileStore) GetTestimony(key model.TestimonyKey) (*model.Testimony, error) { path := filepath.Join(this.directory, filepath.Join(key.Split()...)) encoded, err := ioutil.ReadFile(path) if err != nil { return nil, err } testimony := &model.Testimony{} err = model.Decode(testimony, encoded) if err != nil { return nil, err } return testimony, nil } |
Added store/store_test.go.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package store import ( "io/ioutil" "os" "reflect" "testing" "src.d10.dev/hancock/model/modeltest" ) func TestFileStore(t *testing.T) { testimony, err := modeltest.NewTestTestimony("hello world") if err != nil { t.Error(err) return } var _ Store = NewFileStore("TestFileStore") // compile time test that interface is implemented dir, err := ioutil.TempDir("", "TestFileStore") if err != nil { t.Error(err) return } var store Store = NewFileStore(dir) k, err := store.PutTestimony(*testimony) if err != nil { t.Error(err) return } //t.Logf("stored testimony (%v) to store (%v)", k, store) test, err := store.GetTestimony(*k) if err != nil { t.Error(err) return } if !reflect.DeepEqual(test, testimony) { t.Errorf("got %v, wanted %v; files in %q", test, testimony, dir) } else { // passed test, clean up t.Logf("put, then got, testimony (%v)", k) defer os.RemoveAll(dir) } } |