github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/shard_version.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package db 13 14 import ( 15 "encoding/binary" 16 "os" 17 18 "github.com/pkg/errors" 19 ) 20 21 // ShardCodeBaseVersion must be increased whenever there are breaking changes - 22 // including those that we can handle in a non-breaking way 23 // the version checker can then decide on init if it should prevent startup 24 // completely. If it does not prevent startup, but there is still a version 25 // mismatch, the version can be used to make specific decisions 26 // 27 // CHANGELOG 28 // - Version 1 - Everything up until Weaviate v1.10.1 inclusive 29 // - Version 2 - Inverted Index is now stored in an always sorted fashion and 30 // doc ids are stored as BigEndian. To make this backward-compatible with v1, 31 // doc ids need to be read and written as Little Endian. In addition, an 32 // additional sort step is required in three places: during a MapList call, 33 // during a Map Cursor and during Map Compactions. BM25 is entirely disabled 34 // prior to this version 35 const ( 36 ShardCodeBaseVersion = uint16(2) 37 ShardCodeBaseMinimumVersionForStartup = uint16(1) 38 ) 39 40 type shardVersioner struct { 41 version uint16 42 43 // we don't need the file after initialization, but still need to track its 44 // path so we can delete it on .Drop() 45 path string 46 } 47 48 func newShardVersioner(baseDir string, dataPresent bool) (*shardVersioner, error) { 49 sv := &shardVersioner{} 50 51 return sv, sv.init(baseDir, dataPresent) 52 } 53 54 func (sv *shardVersioner) init(fileName string, dataPresent bool) error { 55 sv.path = fileName 56 57 f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0o666) 58 if err != nil { 59 return err 60 } 61 62 stat, err := f.Stat() 63 if err != nil { 64 return err 65 } 66 67 var version uint16 = 1 68 if stat.Size() > 0 { 69 // the file has existed before, we need to initialize with its content 70 err := binary.Read(f, binary.LittleEndian, &version) 71 if err != nil { 72 return errors.Wrap(err, "read initial version from file") 73 } 74 } else { 75 // if the version file does not yet exist, there are two scenarios: 76 // 1) We are just creating this class, which means its version is 77 // ShardCodeBaseVersion. 78 // 2) There is data present, so we must assume it was built with a version 79 // that did not yet have this versioner present, so we assume it's v1 80 if !dataPresent { 81 version = ShardCodeBaseVersion 82 } else { 83 version = 1 84 } 85 86 err := binary.Write(f, binary.LittleEndian, &version) 87 if err != nil { 88 return errors.Wrap(err, "write version back to file") 89 } 90 91 if err := f.Close(); err != nil { 92 return errors.Wrap(err, "close version file") 93 } 94 } 95 96 if version < ShardCodeBaseMinimumVersionForStartup { 97 return errors.Errorf("cannot start up shard: it was built with shard "+ 98 "version v%d, but this version of Weaviate requires at least shard version v%d", 99 version, ShardCodeBaseMinimumVersionForStartup) 100 } 101 102 sv.version = version 103 104 return nil 105 } 106 107 func (sv *shardVersioner) Drop() error { 108 err := os.Remove(sv.path) 109 if err != nil { 110 return errors.Wrap(err, "drop versioner file") 111 } 112 return nil 113 } 114 115 func (sv *shardVersioner) Version() uint16 { 116 return sv.version 117 }