github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/store/imagestore/remote.go (about) 1 // Copyright 2014 The rkt Authors 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 store implements a content-addressable-store on disk. 16 // It leverages the `diskv` package to store items in a simple 17 // key-value blob store: https://github.com/peterbourgon/diskv 18 package imagestore 19 20 import ( 21 "database/sql" 22 "errors" 23 "time" 24 ) 25 26 var ( 27 ErrRemoteNotFound = errors.New("remote target not found") 28 ) 29 30 func NewRemote(aciurl, sigurl string) *Remote { 31 r := &Remote{ 32 ACIURL: aciurl, 33 SigURL: sigurl, 34 } 35 return r 36 } 37 38 type Remote struct { 39 // ACIURL is the URL used to import an ACI. 40 ACIURL string 41 // SigURL is the URL used to import an ACI verification signature. 42 SigURL string 43 ETag string 44 // The key in the blob store under which the ACI has been saved. 45 BlobKey string 46 CacheMaxAge int 47 DownloadTime time.Time 48 } 49 50 func remoteRowScan(rows *sql.Rows, remote *Remote) error { 51 return rows.Scan(&remote.ACIURL, &remote.SigURL, &remote.ETag, &remote.BlobKey, &remote.CacheMaxAge, &remote.DownloadTime) 52 } 53 54 // GetRemote tries to retrieve a remote with the given aciURL. 55 // If remote doesn't exist, it returns ErrRemoteNotFound error. 56 func GetRemote(tx *sql.Tx, aciURL string) (*Remote, error) { 57 rows, err := tx.Query("SELECT * FROM remote WHERE aciurl == $1", aciURL) 58 if err != nil { 59 return nil, err 60 } 61 defer rows.Close() 62 63 if ok := rows.Next(); !ok { 64 return nil, ErrRemoteNotFound 65 } 66 67 remote := &Remote{} 68 if err := remoteRowScan(rows, remote); err != nil { 69 return nil, err 70 } 71 72 if err := rows.Err(); err != nil { 73 return nil, err 74 } 75 76 return remote, nil 77 } 78 79 // GetAllRemotes returns all the ACIInfos sorted by optional sortfields and 80 // with ascending or descending order. 81 func GetAllRemotes(tx *sql.Tx) ([]*Remote, error) { 82 var remotes []*Remote 83 query := "SELECT * from remote" 84 85 rows, err := tx.Query(query) 86 if err != nil { 87 return nil, err 88 89 } 90 defer rows.Close() 91 92 for rows.Next() { 93 r := &Remote{} 94 if err := remoteRowScan(rows, r); err != nil { 95 return nil, err 96 97 } 98 99 remotes = append(remotes, r) 100 101 } 102 103 if err := rows.Err(); err != nil { 104 return nil, err 105 106 } 107 108 return remotes, nil 109 110 } 111 112 // WriteRemote adds or updates the provided Remote. 113 func WriteRemote(tx *sql.Tx, remote *Remote) error { 114 // ql doesn't have an INSERT OR UPDATE function so 115 // it's faster to remove and reinsert the row 116 _, err := tx.Exec("DELETE FROM remote WHERE aciurl == $1", remote.ACIURL) 117 if err != nil { 118 return err 119 } 120 _, err = tx.Exec("INSERT INTO remote VALUES ($1, $2, $3, $4, $5, $6)", remote.ACIURL, remote.SigURL, remote.ETag, remote.BlobKey, remote.CacheMaxAge, remote.DownloadTime) 121 if err != nil { 122 return err 123 } 124 return nil 125 } 126 127 // RemoveRemote removes the remote with the given blobKey. 128 func RemoveRemote(tx *sql.Tx, blobKey string) error { 129 _, err := tx.Exec("DELETE FROM remote WHERE blobkey == $1", blobKey) 130 if err != nil { 131 return err 132 } 133 return nil 134 }