github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/share-db-v1.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"os"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/minio/mc/pkg/probe"
    26  	"github.com/minio/pkg/v2/quick"
    27  )
    28  
    29  // shareEntryV1 - container for each download/upload entries.
    30  type shareEntryV1 struct {
    31  	URL         string        `json:"share"` // Object URL.
    32  	VersionID   string        `json:"versionID"`
    33  	Date        time.Time     `json:"date"`
    34  	Expiry      time.Duration `json:"expiry"`
    35  	ContentType string        `json:"contentType,omitempty"` // Only used by upload cmd.
    36  }
    37  
    38  // JSON file to persist previously shared uploads.
    39  type shareDBV1 struct {
    40  	Version string `json:"version"`
    41  	mutex   *sync.Mutex
    42  
    43  	// key is unique share URL.
    44  	Shares map[string]shareEntryV1 `json:"shares"`
    45  }
    46  
    47  // Instantiate a new uploads structure for persistence.
    48  func newShareDBV1() *shareDBV1 {
    49  	s := &shareDBV1{
    50  		Version: "1",
    51  	}
    52  	s.Shares = make(map[string]shareEntryV1)
    53  	s.mutex = &sync.Mutex{}
    54  	return s
    55  }
    56  
    57  // Set upload info for each share.
    58  func (s *shareDBV1) Set(objectURL, shareURL string, expiry time.Duration, contentType string) {
    59  	s.mutex.Lock()
    60  	defer s.mutex.Unlock()
    61  
    62  	s.Shares[shareURL] = shareEntryV1{
    63  		URL:         objectURL,
    64  		Date:        UTCNow(),
    65  		Expiry:      expiry,
    66  		ContentType: contentType,
    67  	}
    68  }
    69  
    70  // Delete upload info if it exists.
    71  func (s *shareDBV1) Delete(objectURL string) {
    72  	s.mutex.Lock()
    73  	defer s.mutex.Unlock()
    74  
    75  	delete(s.Shares, objectURL)
    76  }
    77  
    78  // Delete all expired uploads.
    79  func (s *shareDBV1) deleteAllExpired() {
    80  	for shareURL, share := range s.Shares {
    81  		if (share.Expiry - time.Since(share.Date)) <= 0 {
    82  			// Expired entry. Safe to drop.
    83  			delete(s.Shares, shareURL)
    84  		}
    85  	}
    86  }
    87  
    88  // Load shareDB entries from disk. Any entries held in memory are reset.
    89  func (s *shareDBV1) Load(filename string) *probe.Error {
    90  	s.mutex.Lock()
    91  	defer s.mutex.Unlock()
    92  
    93  	// Check if the db file exist.
    94  	if _, e := os.Stat(filename); e != nil {
    95  		return probe.NewError(e)
    96  	}
    97  
    98  	// Initialize and load using quick package.
    99  	qs, e := quick.NewConfig(newShareDBV1(), nil)
   100  	if e != nil {
   101  		return probe.NewError(e).Trace(filename)
   102  	}
   103  	e = qs.Load(filename)
   104  	if e != nil {
   105  		return probe.NewError(e).Trace(filename)
   106  	}
   107  
   108  	// Copy map over.
   109  	for k, v := range qs.Data().(*shareDBV1).Shares {
   110  		s.Shares[k] = v
   111  	}
   112  
   113  	// Filter out expired entries and save changes back to disk.
   114  	s.deleteAllExpired()
   115  	s.save(filename)
   116  
   117  	return nil
   118  }
   119  
   120  // Persist share uploads to disk.
   121  func (s shareDBV1) save(filename string) *probe.Error {
   122  	// Initialize a new quick file.
   123  	qs, e := quick.NewConfig(s, nil)
   124  	if e != nil {
   125  		return probe.NewError(e).Trace(filename)
   126  	}
   127  	if e := qs.Save(filename); e != nil {
   128  		return probe.NewError(e).Trace(filename)
   129  	}
   130  	return nil
   131  }
   132  
   133  // Persist share uploads to disk.
   134  func (s shareDBV1) Save(filename string) *probe.Error {
   135  	s.mutex.Lock()
   136  	defer s.mutex.Unlock()
   137  
   138  	return s.save(filename)
   139  }