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  }