github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/nbs/bs_manifest.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package nbs 16 17 import ( 18 "bytes" 19 "context" 20 "io" 21 "strings" 22 23 "github.com/dolthub/dolt/go/store/blobstore" 24 ) 25 26 const ( 27 manifestFile = "manifest" 28 ) 29 30 type blobstoreManifest struct { 31 name string 32 bs blobstore.Blobstore 33 } 34 35 func (bsm blobstoreManifest) Name() string { 36 return bsm.name 37 } 38 39 func manifestVersionAndContents(ctx context.Context, bs blobstore.Blobstore) (string, manifestContents, error) { 40 reader, ver, err := bs.Get(ctx, manifestFile, blobstore.AllRange) 41 42 if err != nil { 43 return "", manifestContents{}, err 44 } 45 46 defer reader.Close() 47 contents, err := fileManifestV5{}.parseManifest(reader) 48 49 if err != nil { 50 return "", manifestContents{}, err 51 } 52 53 return ver, contents, nil 54 } 55 56 // ParseIfExists looks for a manifest in the specified blobstore. If one exists 57 // will return true and the contents, else false and nil 58 func (bsm blobstoreManifest) ParseIfExists(ctx context.Context, stats *Stats, readHook func() error) (bool, manifestContents, error) { 59 if readHook != nil { 60 panic("Read hooks not supported") 61 } 62 63 _, contents, err := manifestVersionAndContents(ctx, bsm.bs) 64 65 if err != nil { 66 if blobstore.IsNotFoundError(err) { 67 return false, contents, nil 68 } 69 70 // io error 71 return true, contents, err 72 } 73 74 return true, contents, nil 75 } 76 77 // Update updates the contents of the manifest in the blobstore 78 func (bsm blobstoreManifest) Update(ctx context.Context, lastLock addr, newContents manifestContents, stats *Stats, writeHook func() error) (manifestContents, error) { 79 if writeHook != nil { 80 panic("Write hooks not supported") 81 } 82 83 ver, contents, err := manifestVersionAndContents(ctx, bsm.bs) 84 85 if err != nil && !blobstore.IsNotFoundError(err) { 86 return manifestContents{}, err 87 } 88 89 if contents.lock == lastLock { 90 buffer := bytes.NewBuffer(make([]byte, 64*1024)[:0]) 91 err := fileManifestV5{}.writeManifest(buffer, newContents) 92 93 if err != nil { 94 return manifestContents{}, err 95 } 96 97 _, err = bsm.bs.CheckAndPut(ctx, ver, manifestFile, buffer) 98 99 if err != nil { 100 if !blobstore.IsCheckAndPutError(err) { 101 return manifestContents{}, err 102 } 103 } else { 104 return newContents, nil 105 } 106 } 107 108 return contents, nil 109 } 110 111 func writeVer4Manifest(temp io.Writer, contents manifestContents) error { 112 strs := make([]string, 2*len(contents.specs)+4) 113 strs[0], strs[1], strs[2], strs[3] = storageVersion4, contents.vers, contents.lock.String(), contents.root.String() 114 tableInfo := strs[4:] 115 formatSpecs(contents.specs, tableInfo) 116 _, err := io.WriteString(temp, strings.Join(strs, ":")) 117 118 return err 119 }