github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/store/imagestore/aciinfo.go (about) 1 // Copyright 2015 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 imagestore 16 17 import ( 18 "database/sql" 19 "fmt" 20 "strings" 21 "time" 22 ) 23 24 // ACIFetchInfo is used to store information about the fetching process of an ACI. 25 type ACIFetchInfo struct { 26 // Latest defines if the ACI was imported using the latest pattern 27 // (no version label was provided on ACI discovery). 28 Latest bool 29 } 30 31 // ACIInfo is used to store information about an ACI. 32 type ACIInfo struct { 33 // BlobKey is the key in the blob/imageManifest store of the related 34 // ACI file and is the db primary key. 35 BlobKey string 36 // Name is the name of the ACI. 37 Name string 38 // ImportTime is the time this ACI was imported in the store. 39 ImportTime time.Time 40 // LastUsed is the last time this image was read 41 LastUsed time.Time 42 // Size is the size in bytes of this image in the store 43 Size int64 44 // TreeStoreSize is the size in bytes of this image in the tree store 45 TreeStoreSize int64 46 // Latest defines if the ACI was imported using the latest pattern (no 47 // version label was provided on ACI discovery) 48 Latest bool 49 } 50 51 func NewACIInfo(blobKey string, latest bool, t time.Time, size int64, treeStoreSize int64) *ACIInfo { 52 return &ACIInfo{ 53 BlobKey: blobKey, 54 Latest: latest, 55 ImportTime: t, 56 LastUsed: time.Now(), 57 Size: size, 58 TreeStoreSize: treeStoreSize, 59 } 60 } 61 62 func aciinfoRowScan(rows *sql.Rows, aciinfo *ACIInfo) error { 63 // This ordering MUST match that in schema.go 64 return rows.Scan(&aciinfo.BlobKey, &aciinfo.Name, &aciinfo.ImportTime, &aciinfo.LastUsed, &aciinfo.Latest, &aciinfo.Size, &aciinfo.TreeStoreSize) 65 } 66 67 // GetAciInfosWithKeyPrefix returns all the ACIInfos with a blobkey starting with the given prefix. 68 func GetACIInfosWithKeyPrefix(tx *sql.Tx, prefix string) ([]*ACIInfo, error) { 69 var aciinfos []*ACIInfo 70 rows, err := tx.Query("SELECT * from aciinfo WHERE hasPrefix(blobkey, $1)", prefix) 71 if err != nil { 72 return nil, err 73 } 74 defer rows.Close() 75 for rows.Next() { 76 aciinfo := &ACIInfo{} 77 if err := aciinfoRowScan(rows, aciinfo); err != nil { 78 return nil, err 79 } 80 aciinfos = append(aciinfos, aciinfo) 81 } 82 if err := rows.Err(); err != nil { 83 return nil, err 84 } 85 return aciinfos, err 86 } 87 88 // GetAciInfosWithName returns all the ACIInfos for a given name. found will be 89 // false if no aciinfo exists. 90 func GetACIInfosWithName(tx *sql.Tx, name string) ([]*ACIInfo, bool, error) { 91 var aciinfos []*ACIInfo 92 found := false 93 rows, err := tx.Query("SELECT * from aciinfo WHERE name == $1", name) 94 if err != nil { 95 return nil, false, err 96 } 97 defer rows.Close() 98 for rows.Next() { 99 found = true 100 aciinfo := &ACIInfo{} 101 if err := aciinfoRowScan(rows, aciinfo); err != nil { 102 return nil, false, err 103 } 104 aciinfos = append(aciinfos, aciinfo) 105 } 106 if err := rows.Err(); err != nil { 107 return nil, false, err 108 } 109 return aciinfos, found, err 110 } 111 112 // GetAciInfosWithBlobKey returns the ACIInfo with the given blobKey. found will be 113 // false if no aciinfo exists. 114 func GetACIInfoWithBlobKey(tx *sql.Tx, blobKey string) (*ACIInfo, bool, error) { 115 aciinfo := &ACIInfo{} 116 found := false 117 rows, err := tx.Query("SELECT * from aciinfo WHERE blobkey == $1", blobKey) 118 if err != nil { 119 return nil, false, err 120 } 121 defer rows.Close() 122 for rows.Next() { 123 found = true 124 if err := aciinfoRowScan(rows, aciinfo); err != nil { 125 return nil, false, err 126 } 127 // No more than one row for blobkey must exist. 128 break 129 } 130 if err := rows.Err(); err != nil { 131 return nil, false, err 132 } 133 return aciinfo, found, err 134 } 135 136 // GetAllACIInfos returns all the ACIInfos sorted by optional sortfields and 137 // with ascending or descending order. 138 func GetAllACIInfos(tx *sql.Tx, sortfields []string, ascending bool) ([]*ACIInfo, error) { 139 var aciinfos []*ACIInfo 140 query := "SELECT * from aciinfo" 141 if len(sortfields) > 0 { 142 query += fmt.Sprintf(" ORDER BY %s ", strings.Join(sortfields, ", ")) 143 if ascending { 144 query += "ASC" 145 } else { 146 query += "DESC" 147 } 148 } 149 rows, err := tx.Query(query) 150 if err != nil { 151 return nil, err 152 } 153 defer rows.Close() 154 for rows.Next() { 155 aciinfo := &ACIInfo{} 156 if err := aciinfoRowScan(rows, aciinfo); err != nil { 157 return nil, err 158 } 159 aciinfos = append(aciinfos, aciinfo) 160 } 161 if err := rows.Err(); err != nil { 162 return nil, err 163 } 164 return aciinfos, err 165 } 166 167 // WriteACIInfo adds or updates the provided aciinfo. 168 func WriteACIInfo(tx *sql.Tx, aciinfo *ACIInfo) error { 169 // ql doesn't have an INSERT OR UPDATE function so 170 // it's faster to remove and reinsert the row 171 _, err := tx.Exec("DELETE from aciinfo where blobkey == $1", aciinfo.BlobKey) 172 if err != nil { 173 return err 174 } 175 _, err = tx.Exec("INSERT into aciinfo (blobkey, name, importtime, lastused, latest, size, treestoresize) VALUES ($1, $2, $3, $4, $5, $6, $7)", aciinfo.BlobKey, aciinfo.Name, aciinfo.ImportTime, aciinfo.LastUsed, aciinfo.Latest, aciinfo.Size, aciinfo.TreeStoreSize) 176 if err != nil { 177 return err 178 } 179 180 return nil 181 } 182 183 // RemoveACIInfo removes the ACIInfo with the given blobKey. 184 func RemoveACIInfo(tx *sql.Tx, blobKey string) error { 185 _, err := tx.Exec("DELETE from aciinfo where blobkey == $1", blobKey) 186 if err != nil { 187 return err 188 } 189 return nil 190 }