storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/data-usage.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2019 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"net/http"
    24  
    25  	jsoniter "github.com/json-iterator/go"
    26  
    27  	"storj.io/minio/cmd/logger"
    28  	"storj.io/minio/pkg/hash"
    29  	"storj.io/minio/pkg/madmin"
    30  )
    31  
    32  const (
    33  	dataUsageRoot   = SlashSeparator
    34  	dataUsageBucket = minioMetaBucket + SlashSeparator + bucketMetaPrefix
    35  
    36  	dataUsageObjName   = ".usage.json"
    37  	dataUsageCacheName = ".usage-cache.bin"
    38  	dataUsageBloomName = ".bloomcycle.bin"
    39  )
    40  
    41  // storeDataUsageInBackend will store all objects sent on the gui channel until closed.
    42  func storeDataUsageInBackend(ctx context.Context, objAPI ObjectLayer, dui <-chan madmin.DataUsageInfo) {
    43  	for dataUsageInfo := range dui {
    44  		dataUsageJSON, err := json.Marshal(dataUsageInfo)
    45  		if err != nil {
    46  			logger.LogIf(ctx, err)
    47  			continue
    48  		}
    49  		size := int64(len(dataUsageJSON))
    50  		r, err := hash.NewReader(bytes.NewReader(dataUsageJSON), size, "", "", size)
    51  		if err != nil {
    52  			logger.LogIf(ctx, err)
    53  			continue
    54  		}
    55  		_, err = objAPI.PutObject(ctx, dataUsageBucket, dataUsageObjName, NewPutObjReader(r), ObjectOptions{})
    56  		if !isErrBucketNotFound(err) {
    57  			logger.LogIf(ctx, err)
    58  		}
    59  	}
    60  }
    61  
    62  func loadDataUsageFromBackend(ctx context.Context, objAPI ObjectLayer) (madmin.DataUsageInfo, error) {
    63  	r, err := objAPI.GetObjectNInfo(ctx, dataUsageBucket, dataUsageObjName, nil, http.Header{}, readLock, ObjectOptions{})
    64  	if err != nil {
    65  		if isErrObjectNotFound(err) || isErrBucketNotFound(err) {
    66  			return madmin.DataUsageInfo{}, nil
    67  		}
    68  		return madmin.DataUsageInfo{}, toObjectErr(err, dataUsageBucket, dataUsageObjName)
    69  	}
    70  	defer r.Close()
    71  
    72  	var dataUsageInfo madmin.DataUsageInfo
    73  	var json = jsoniter.ConfigCompatibleWithStandardLibrary
    74  	if err = json.NewDecoder(r).Decode(&dataUsageInfo); err != nil {
    75  		return madmin.DataUsageInfo{}, err
    76  	}
    77  
    78  	// For forward compatibility reasons, we need to add this code.
    79  	if len(dataUsageInfo.BucketsUsage) == 0 {
    80  		dataUsageInfo.BucketsUsage = make(map[string]madmin.BucketUsageInfo, len(dataUsageInfo.BucketSizes))
    81  		for bucket, size := range dataUsageInfo.BucketSizes {
    82  			dataUsageInfo.BucketsUsage[bucket] = madmin.BucketUsageInfo{Size: size}
    83  		}
    84  	}
    85  
    86  	// For backward compatibility reasons, we need to add this code.
    87  	if len(dataUsageInfo.BucketSizes) == 0 {
    88  		dataUsageInfo.BucketSizes = make(map[string]uint64, len(dataUsageInfo.BucketsUsage))
    89  		for bucket, bui := range dataUsageInfo.BucketsUsage {
    90  			dataUsageInfo.BucketSizes[bucket] = bui.Size
    91  		}
    92  	}
    93  
    94  	return dataUsageInfo, nil
    95  }