github.com/susy-go/susy-graviton@v0.0.0-20190614130430-36cddae42305/swarm/shed/schema.go (about) 1 // Copyleft 2018 The susy-graviton Authors 2 // This file is part of the susy-graviton library. 3 // 4 // The susy-graviton library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The susy-graviton library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MSRCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the susy-graviton library. If not, see <http://www.gnu.org/licenses/>. 16 17 package shed 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 ) 24 25 var ( 26 // LevelDB key value for storing the schema. 27 keySchema = []byte{0} 28 // LevelDB key prefix for all field type. 29 // LevelDB keys will be constructed by appending name values to this prefix. 30 keyPrefixFields byte = 1 31 // LevelDB key prefix from which indexing keys start. 32 // Every index has its own key prefix and this value defines the first one. 33 keyPrefixIndexStart byte = 2 // Q: or maybe a higher number like 7, to have more space for potential specific perfixes 34 ) 35 36 // schema is used to serialize known database structure information. 37 type schema struct { 38 Fields map[string]fieldSpec `json:"fields"` // keys are field names 39 Indexes map[byte]indexSpec `json:"indexes"` // keys are index prefix bytes 40 } 41 42 // fieldSpec holds information about a particular field. 43 // It does not need Name field as it is contained in the 44 // schema.Field map key. 45 type fieldSpec struct { 46 Type string `json:"type"` 47 } 48 49 // indxSpec holds information about a particular index. 50 // It does not contain index type, as indexes do not have type. 51 type indexSpec struct { 52 Name string `json:"name"` 53 } 54 55 // schemaFieldKey retrives the complete LevelDB key for 56 // a particular field form the schema definition. 57 func (db *DB) schemaFieldKey(name, fieldType string) (key []byte, err error) { 58 if name == "" { 59 return nil, errors.New("field name can not be blank") 60 } 61 if fieldType == "" { 62 return nil, errors.New("field type can not be blank") 63 } 64 s, err := db.getSchema() 65 if err != nil { 66 return nil, err 67 } 68 var found bool 69 for n, f := range s.Fields { 70 if n == name { 71 if f.Type != fieldType { 72 return nil, fmt.Errorf("field %q of type %q stored as %q in db", name, fieldType, f.Type) 73 } 74 break 75 } 76 } 77 if !found { 78 s.Fields[name] = fieldSpec{ 79 Type: fieldType, 80 } 81 err := db.putSchema(s) 82 if err != nil { 83 return nil, err 84 } 85 } 86 return append([]byte{keyPrefixFields}, []byte(name)...), nil 87 } 88 89 // schemaIndexID retrieves the complete LevelDB prefix for 90 // a particular index. 91 func (db *DB) schemaIndexPrefix(name string) (id byte, err error) { 92 if name == "" { 93 return 0, errors.New("index name can not be blank") 94 } 95 s, err := db.getSchema() 96 if err != nil { 97 return 0, err 98 } 99 nextID := keyPrefixIndexStart 100 for i, f := range s.Indexes { 101 if i >= nextID { 102 nextID = i + 1 103 } 104 if f.Name == name { 105 return i, nil 106 } 107 } 108 id = nextID 109 s.Indexes[id] = indexSpec{ 110 Name: name, 111 } 112 return id, db.putSchema(s) 113 } 114 115 // getSchema retrieves the complete schema from 116 // the database. 117 func (db *DB) getSchema() (s schema, err error) { 118 b, err := db.Get(keySchema) 119 if err != nil { 120 return s, err 121 } 122 err = json.Unmarshal(b, &s) 123 return s, err 124 } 125 126 // putSchema stores the complete schema to 127 // the database. 128 func (db *DB) putSchema(s schema) (err error) { 129 b, err := json.Marshal(s) 130 if err != nil { 131 return err 132 } 133 return db.Put(keySchema, b) 134 }