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 }