mirror of
https://github.com/pgsty/minio.git
synced 2026-08-10 08:13:28 +03:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 92788e4cf4 | |||
| 8a698fef71 | |||
| b49ce1713f | |||
| c2b54d92f6 | |||
| f965434022 | |||
| a3ac62596c | |||
| 2faba02d6b | |||
| ee158e1610 | |||
| fa68efb1e7 | |||
| 8c53a4405a | |||
| c32f699105 | |||
| 53aa8f5650 | |||
| 56887f3208 | |||
| 92180bc793 | |||
| 22aa16ab12 | |||
| 526b829a09 | |||
| c44f311c4f | |||
| 9ea5d08ecd | |||
| 35deb1a8e2 | |||
| c7f7c47388 | |||
| cb7dab17cb | |||
| cd419a35fe | |||
| e06168596f | |||
| 4c8197a119 | |||
| 23c10350f3 |
@@ -1,8 +0,0 @@
|
||||
|
||||
[codespell]
|
||||
# certs_test.go - has lots of ceritificates.
|
||||
skip = go.mod,go.sum,*.txt,LICENSE,*.zip,.git,*.pdf,*.svg,.codespellrc,CREDITS,certs_test.go
|
||||
check-hidden = true
|
||||
ignore-regex = \b(newfolder/afile|filterIn|HelpES)\b
|
||||
ignore-words-list = inout,bui,to,bu,te,ot,toi,ist,parms,flate
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Codespell
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
name: Check for spelling errors
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Codespell
|
||||
uses: codespell-project/actions-codespell@v2
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: Test GitHub Action
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check spelling of repo
|
||||
uses: crate-ci/typos@master
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
[files]
|
||||
extend-exclude = [
|
||||
".git/",
|
||||
"docs/",
|
||||
]
|
||||
ignore-hidden = false
|
||||
|
||||
[default]
|
||||
extend-ignore-re = [
|
||||
"Patrick Collison",
|
||||
"Copyright 2014 Unknwon",
|
||||
"[0-9A-Za-z/+=]{64}",
|
||||
"ZXJuZXQxDjAMBgNVBA-some-junk-Q4wDAYDVQQLEwVNaW5pbzEOMAwGA1UEAxMF",
|
||||
"eyJmb28iOiJiYXIifQ",
|
||||
'http\.Header\{"X-Amz-Server-Side-Encryptio":',
|
||||
'sessionToken',
|
||||
]
|
||||
|
||||
[default.extend-words]
|
||||
"encrypter" = "encrypter"
|
||||
"requestor" = "requestor"
|
||||
|
||||
[default.extend-identifiers]
|
||||
"bui" = "bui"
|
||||
"toi" = "toi"
|
||||
"ot" = "ot"
|
||||
"dm2nd" = "dm2nd"
|
||||
"HashiCorp" = "HashiCorp"
|
||||
"ParseND" = "ParseND"
|
||||
"ParseNDStream" = "ParseNDStream"
|
||||
"TestGetPartialObjectMisAligned" = "TestGetPartialObjectMisAligned"
|
||||
@@ -1072,6 +1072,10 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
|
||||
if serviceAccount == siteReplicatorSvcAcc && globalSiteReplicationSys.isEnabled() {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidArgument), r.URL)
|
||||
return
|
||||
}
|
||||
// We do not care if service account is readable or not at this point,
|
||||
// since this is a delete call we shall allow it to be deleted if possible.
|
||||
svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, serviceAccount)
|
||||
@@ -1200,7 +1204,7 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ
|
||||
|
||||
// Rely on older value if usage loading fails from disk.
|
||||
bucketStorageCache.Relax = true
|
||||
bucketStorageCache.Update = func() (interface{}, error) {
|
||||
bucketStorageCache.Update = func() (DataUsageInfo, error) {
|
||||
ctx, done := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer done()
|
||||
|
||||
@@ -1208,11 +1212,7 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
})
|
||||
|
||||
var dataUsageInfo DataUsageInfo
|
||||
v, _ := bucketStorageCache.Get()
|
||||
if v != nil {
|
||||
dataUsageInfo, _ = v.(DataUsageInfo)
|
||||
}
|
||||
dataUsageInfo, _ := bucketStorageCache.Get()
|
||||
|
||||
// If etcd, dns federation configured list buckets from etcd.
|
||||
var err error
|
||||
|
||||
+42
-22
@@ -1192,7 +1192,7 @@ type healInitParams struct {
|
||||
}
|
||||
|
||||
// extractHealInitParams - Validates params for heal init API.
|
||||
func extractHealInitParams(vars map[string]string, qParms url.Values, r io.Reader) (hip healInitParams, err APIErrorCode) {
|
||||
func extractHealInitParams(vars map[string]string, qParams url.Values, r io.Reader) (hip healInitParams, err APIErrorCode) {
|
||||
hip.bucket = vars[mgmtBucket]
|
||||
hip.objPrefix = vars[mgmtPrefix]
|
||||
|
||||
@@ -1213,13 +1213,13 @@ func extractHealInitParams(vars map[string]string, qParms url.Values, r io.Reade
|
||||
return
|
||||
}
|
||||
|
||||
if len(qParms[mgmtClientToken]) > 0 {
|
||||
hip.clientToken = qParms[mgmtClientToken][0]
|
||||
if len(qParams[mgmtClientToken]) > 0 {
|
||||
hip.clientToken = qParams[mgmtClientToken][0]
|
||||
}
|
||||
if _, ok := qParms[mgmtForceStart]; ok {
|
||||
if _, ok := qParams[mgmtForceStart]; ok {
|
||||
hip.forceStart = true
|
||||
}
|
||||
if _, ok := qParms[mgmtForceStop]; ok {
|
||||
if _, ok := qParams[mgmtForceStop]; ok {
|
||||
hip.forceStop = true
|
||||
}
|
||||
|
||||
@@ -1984,7 +1984,6 @@ func (a adminAPIHandlers) TraceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// The ConsoleLogHandler handler sends console logs to the connected HTTP client.
|
||||
func (a adminAPIHandlers) ConsoleLogHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
objectAPI, _ := validateAdminReq(ctx, w, r, policy.ConsoleLogAdminAction)
|
||||
if objectAPI == nil {
|
||||
return
|
||||
@@ -2009,44 +2008,65 @@ func (a adminAPIHandlers) ConsoleLogHandler(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
setEventStreamHeaders(w)
|
||||
|
||||
logCh := make(chan log.Info, 4000)
|
||||
|
||||
logCh := make(chan log.Info, 1000)
|
||||
peers, _ := newPeerRestClients(globalEndpoints)
|
||||
|
||||
encodedCh := make(chan []byte, 1000+len(peers)*1000)
|
||||
err = globalConsoleSys.Subscribe(logCh, ctx.Done(), node, limitLines, logKind, nil)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
// Convert local entries to JSON
|
||||
go func() {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case li := <-logCh:
|
||||
if !li.SendLog(node, logKind) {
|
||||
continue
|
||||
}
|
||||
buf.Reset()
|
||||
if err := enc.Encode(li); err != nil {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case encodedCh <- append(grid.GetByteBuffer()[:0], buf.Bytes()...):
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Collect from matching peers
|
||||
for _, peer := range peers {
|
||||
if peer == nil {
|
||||
continue
|
||||
}
|
||||
if node == "" || strings.EqualFold(peer.host.Name, node) {
|
||||
peer.ConsoleLog(logCh, ctx.Done())
|
||||
peer.ConsoleLog(ctx, logKind, encodedCh)
|
||||
}
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
|
||||
keepAliveTicker := time.NewTicker(500 * time.Millisecond)
|
||||
defer keepAliveTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case log, ok := <-logCh:
|
||||
case log, ok := <-encodedCh:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if log.SendLog(node, logKind) {
|
||||
if err := enc.Encode(log); err != nil {
|
||||
return
|
||||
}
|
||||
if len(logCh) == 0 {
|
||||
// Flush if nothing is queued
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
_, err = w.Write(log)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
grid.PutByteBuffer(log)
|
||||
if len(logCh) == 0 {
|
||||
// Flush if nothing is queued
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
case <-keepAliveTicker.C:
|
||||
if len(logCh) > 0 {
|
||||
|
||||
@@ -348,7 +348,7 @@ func TestExtractHealInitParams(t *testing.T) {
|
||||
}
|
||||
return v
|
||||
}
|
||||
qParmsArr := []url.Values{
|
||||
qParamsArr := []url.Values{
|
||||
// Invalid cases
|
||||
mkParams("", true, true),
|
||||
mkParams("111", true, true),
|
||||
@@ -373,9 +373,9 @@ func TestExtractHealInitParams(t *testing.T) {
|
||||
body := `{"recursive": false, "dryRun": true, "remove": false, "scanMode": 0}`
|
||||
|
||||
// Test all combinations!
|
||||
for pIdx, parms := range qParmsArr {
|
||||
for pIdx, params := range qParamsArr {
|
||||
for vIdx, vars := range varsArr {
|
||||
_, err := extractHealInitParams(vars, parms, bytes.NewReader([]byte(body)))
|
||||
_, err := extractHealInitParams(vars, params, bytes.NewReader([]byte(body)))
|
||||
isErrCase := false
|
||||
if pIdx < 4 || vIdx < 1 {
|
||||
isErrCase = true
|
||||
|
||||
+3
-3
@@ -390,7 +390,7 @@ const (
|
||||
ErrParseExpectedIdentForGroupName
|
||||
ErrParseExpectedIdentForAlias
|
||||
ErrParseUnsupportedCallWithStar
|
||||
ErrParseNonUnaryAgregateFunctionCall
|
||||
ErrParseNonUnaryAggregateFunctionCall
|
||||
ErrParseMalformedJoin
|
||||
ErrParseExpectedIdentForAt
|
||||
ErrParseAsteriskIsNotAloneInSelectList
|
||||
@@ -1899,8 +1899,8 @@ var errorCodes = errorCodeMap{
|
||||
Description: "Only COUNT with (*) as a parameter is supported in the SQL expression.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrParseNonUnaryAgregateFunctionCall: {
|
||||
Code: "ParseNonUnaryAgregateFunctionCall",
|
||||
ErrParseNonUnaryAggregateFunctionCall: {
|
||||
Code: "ParseNonUnaryAggregateFunctionCall",
|
||||
Description: "Only one argument is supported for aggregate functions in the SQL expression.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
+1
-1
@@ -944,7 +944,7 @@ func writeSuccessResponseHeadersOnly(w http.ResponseWriter) {
|
||||
writeResponse(w, http.StatusOK, nil, mimeNone)
|
||||
}
|
||||
|
||||
// writeErrorRespone writes error headers
|
||||
// writeErrorResponse writes error headers
|
||||
func writeErrorResponse(ctx context.Context, w http.ResponseWriter, err APIError, reqURL *url.URL) {
|
||||
if err.HTTPStatusCode == http.StatusServiceUnavailable {
|
||||
// Set retry-after header to indicate user-agents to retry request after 120secs.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -294,6 +294,11 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
// Expired credentials must return error right away.
|
||||
if cred.IsTemp() && cred.IsExpired() {
|
||||
return nil, toAPIErrorCode(r.Context(), errInvalidAccessKeyID)
|
||||
}
|
||||
|
||||
secret := globalActiveCred.SecretKey
|
||||
if cred.IsServiceAccount() {
|
||||
token = cred.SessionToken
|
||||
|
||||
@@ -237,7 +237,7 @@ func TestIsRequestPresignedSignatureV2(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsRequestPresignedSignatureV4 - Test validates the logic for presign signature verision v4 detection.
|
||||
// TestIsRequestPresignedSignatureV4 - Test validates the logic for presign signature version v4 detection.
|
||||
func TestIsRequestPresignedSignatureV4(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputQueryKey string
|
||||
|
||||
@@ -580,7 +580,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 2.
|
||||
// Test case with invalid accessKey to produce and validate Signature MisMatch error.
|
||||
// Test case with invalid accessKey to produce and validate Signature Mismatch error.
|
||||
{
|
||||
bucketName: bucketName,
|
||||
accessKey: "abcd",
|
||||
|
||||
+19
-9
@@ -395,12 +395,15 @@ func enqueueTransitionImmediate(obj ObjectInfo, src lcEventSrc) {
|
||||
//
|
||||
// 1. when a restored (via PostRestoreObject API) object expires.
|
||||
// 2. when a transitioned object expires (based on an ILM rule).
|
||||
func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *ObjectInfo, lcOpts lifecycle.ObjectOpts, lcEvent lifecycle.Event, src lcEventSrc) error {
|
||||
func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *ObjectInfo, lcEvent lifecycle.Event, src lcEventSrc) error {
|
||||
traceFn := globalLifecycleSys.trace(*oi)
|
||||
var opts ObjectOptions
|
||||
opts.Versioned = globalBucketVersioningSys.PrefixEnabled(oi.Bucket, oi.Name)
|
||||
opts.VersionID = lcOpts.VersionID
|
||||
opts.Expiration = ExpirationOptions{Expire: true}
|
||||
opts := ObjectOptions{
|
||||
Versioned: globalBucketVersioningSys.PrefixEnabled(oi.Bucket, oi.Name),
|
||||
Expiration: ExpirationOptions{Expire: true},
|
||||
}
|
||||
if lcEvent.Action.DeleteVersioned() {
|
||||
opts.VersionID = oi.VersionID
|
||||
}
|
||||
tags := newLifecycleAuditEvent(src, lcEvent).Tags()
|
||||
if lcEvent.Action.DeleteRestored() {
|
||||
// delete locally restored copy of object or object version
|
||||
@@ -435,13 +438,13 @@ func expireTransitionedObject(ctx context.Context, objectAPI ObjectLayer, oi *Ob
|
||||
defer auditLogLifecycle(ctx, *oi, ILMExpiry, tags, traceFn)
|
||||
|
||||
eventName := event.ObjectRemovedDelete
|
||||
if lcOpts.DeleteMarker {
|
||||
if oi.DeleteMarker {
|
||||
eventName = event.ObjectRemovedDeleteMarkerCreated
|
||||
}
|
||||
objInfo := ObjectInfo{
|
||||
Name: oi.Name,
|
||||
VersionID: lcOpts.VersionID,
|
||||
DeleteMarker: lcOpts.DeleteMarker,
|
||||
VersionID: oi.VersionID,
|
||||
DeleteMarker: oi.DeleteMarker,
|
||||
}
|
||||
// Notify object deleted event.
|
||||
sendEvent(eventArgs{
|
||||
@@ -471,7 +474,14 @@ func genTransitionObjName(bucket string) (string, error) {
|
||||
// storage specified by the transition ARN, the metadata is left behind on source cluster and original content
|
||||
// is moved to the transition tier. Note that in the case of encrypted objects, entire encrypted stream is moved
|
||||
// to the transition tier without decrypting or re-encrypting.
|
||||
func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo, lae lcAuditEvent) error {
|
||||
func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo, lae lcAuditEvent) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
globalScannerMetrics.timeILM(lae.Action)(1)
|
||||
}()
|
||||
|
||||
opts := ObjectOptions{
|
||||
Transition: TransitionOptions{
|
||||
Status: lifecycle.TransitionPending,
|
||||
|
||||
@@ -289,7 +289,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
// Extract all the litsObjectsV1 query params to their native values.
|
||||
// Extract all the listObjectsV1 query params to their native values.
|
||||
prefix, marker, delimiter, maxKeys, encodingType, s3Error := getListObjectsV1Args(r.Form)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||
|
||||
+11
-10
@@ -25,6 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
|
||||
@@ -42,7 +43,7 @@ func NewBucketQuotaSys() *BucketQuotaSys {
|
||||
return &BucketQuotaSys{}
|
||||
}
|
||||
|
||||
var bucketStorageCache timedValue
|
||||
var bucketStorageCache = cachevalue.New[DataUsageInfo]()
|
||||
|
||||
// Init initialize bucket quota.
|
||||
func (sys *BucketQuotaSys) Init(objAPI ObjectLayer) {
|
||||
@@ -52,7 +53,7 @@ func (sys *BucketQuotaSys) Init(objAPI ObjectLayer) {
|
||||
bucketStorageCache.TTL = 10 * time.Second
|
||||
// Rely on older value if usage loading fails from disk.
|
||||
bucketStorageCache.Relax = true
|
||||
bucketStorageCache.Update = func() (interface{}, error) {
|
||||
bucketStorageCache.Update = func() (DataUsageInfo, error) {
|
||||
ctx, done := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer done()
|
||||
|
||||
@@ -63,23 +64,23 @@ func (sys *BucketQuotaSys) Init(objAPI ObjectLayer) {
|
||||
|
||||
// GetBucketUsageInfo return bucket usage info for a given bucket
|
||||
func (sys *BucketQuotaSys) GetBucketUsageInfo(bucket string) (BucketUsageInfo, error) {
|
||||
v, err := bucketStorageCache.Get()
|
||||
dui, err := bucketStorageCache.Get()
|
||||
timedout := OperationTimedOut{}
|
||||
if err != nil && !errors.Is(err, context.DeadlineExceeded) && !errors.As(err, &timedout) {
|
||||
if v != nil {
|
||||
if len(dui.BucketsUsage) > 0 {
|
||||
logger.LogOnceIf(GlobalContext, fmt.Errorf("unable to retrieve usage information for bucket: %s, relying on older value cached in-memory: err(%v)", bucket, err), "bucket-usage-cache-"+bucket)
|
||||
} else {
|
||||
logger.LogOnceIf(GlobalContext, errors.New("unable to retrieve usage information for bucket: %s, no reliable usage value available - quota will not be enforced"), "bucket-usage-empty-"+bucket)
|
||||
}
|
||||
}
|
||||
|
||||
var bui BucketUsageInfo
|
||||
dui, ok := v.(DataUsageInfo)
|
||||
if ok {
|
||||
bui = dui.BucketsUsage[bucket]
|
||||
if len(dui.BucketsUsage) > 0 {
|
||||
bui, ok := dui.BucketsUsage[bucket]
|
||||
if ok {
|
||||
return bui, nil
|
||||
}
|
||||
}
|
||||
|
||||
return bui, nil
|
||||
return BucketUsageInfo{}, nil
|
||||
}
|
||||
|
||||
// parseBucketQuota parses BucketQuota from json
|
||||
|
||||
@@ -464,7 +464,7 @@ func (r *ReplicationStats) getLatestReplicationStats(bucket string) (s BucketSta
|
||||
return r.calculateBucketReplicationStats(bucket, bucketStats)
|
||||
}
|
||||
|
||||
func (r *ReplicationStats) incQ(bucket string, sz int64, isDeleleRepl bool, opType replication.Type) {
|
||||
func (r *ReplicationStats) incQ(bucket string, sz int64, isDeleteRepl bool, opType replication.Type) {
|
||||
r.qCache.Lock()
|
||||
defer r.qCache.Unlock()
|
||||
v, ok := r.qCache.bucketStats[bucket]
|
||||
|
||||
+47
-19
@@ -529,17 +529,27 @@ func (f *folderScanner) scanFolder(ctx context.Context, folder cachedFolder, int
|
||||
len(existingFolders)+len(newFolders) >= dataScannerCompactAtFolders ||
|
||||
len(existingFolders)+len(newFolders) >= dataScannerForceCompactAtFolders
|
||||
|
||||
if len(existingFolders)+len(newFolders) > int(scannerExcessFolders.Load()) {
|
||||
if totalFolders := len(existingFolders) + len(newFolders); totalFolders > int(scannerExcessFolders.Load()) {
|
||||
prefixName := strings.TrimSuffix(folder.name, "/") + "/"
|
||||
sendEvent(eventArgs{
|
||||
EventName: event.PrefixManyFolders,
|
||||
BucketName: f.root,
|
||||
Object: ObjectInfo{
|
||||
Name: strings.TrimSuffix(folder.name, "/") + "/",
|
||||
Size: int64(len(existingFolders) + len(newFolders)),
|
||||
Name: prefixName,
|
||||
Size: int64(totalFolders),
|
||||
},
|
||||
UserAgent: "scanner",
|
||||
UserAgent: "Scanner",
|
||||
Host: globalMinioHost,
|
||||
})
|
||||
auditLogInternal(context.Background(), AuditLogOptions{
|
||||
Event: "scanner:manyprefixes",
|
||||
APIName: "Scanner",
|
||||
Bucket: f.root,
|
||||
Object: prefixName,
|
||||
Tags: map[string]interface{}{
|
||||
"x-minio-prefixes-total": strconv.Itoa(totalFolders),
|
||||
},
|
||||
})
|
||||
}
|
||||
if !into.Compacted && shouldCompact {
|
||||
into.Compacted = true
|
||||
@@ -953,15 +963,6 @@ func (i *scannerItem) applyLifecycle(ctx context.Context, o ObjectLayer, oi Obje
|
||||
console.Debugf(applyActionsLogPrefix+" lifecycle: %q Initial scan: %v\n", i.objectPath(), lcEvt.Action)
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if lcEvt.Action != lifecycle.NoneAction {
|
||||
numVersions := uint64(1)
|
||||
if lcEvt.Action == lifecycle.DeleteAllVersionsAction {
|
||||
numVersions = uint64(oi.NumVersions)
|
||||
}
|
||||
globalScannerMetrics.timeILM(lcEvt.Action)(numVersions)
|
||||
}
|
||||
}()
|
||||
|
||||
switch lcEvt.Action {
|
||||
// This version doesn't contribute towards sizeS only when it is permanently deleted.
|
||||
@@ -1107,18 +1108,18 @@ func (i *scannerItem) applyVersionActions(ctx context.Context, o ObjectLayer, fi
|
||||
Object: ObjectInfo{
|
||||
Name: i.objectPath(),
|
||||
},
|
||||
UserAgent: "Internal: [Scanner]",
|
||||
UserAgent: "Scanner",
|
||||
Host: globalLocalNodeName,
|
||||
RespElements: map[string]string{"x-minio-versions": strconv.Itoa(len(fivs))},
|
||||
RespElements: map[string]string{"x-minio-versions": strconv.Itoa(len(objInfos))},
|
||||
})
|
||||
|
||||
auditLogInternal(context.Background(), AuditLogOptions{
|
||||
Event: "scanner:manyversions",
|
||||
APIName: ILMExpiry,
|
||||
APIName: "Scanner",
|
||||
Bucket: i.bucket,
|
||||
Object: i.objectPath(),
|
||||
Tags: map[string]interface{}{
|
||||
"x-minio-versions": strconv.Itoa(len(fivs)),
|
||||
"x-minio-versions": strconv.Itoa(len(objInfos)),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1218,7 +1219,17 @@ func applyTransitionRule(event lifecycle.Event, src lcEventSrc, obj ObjectInfo)
|
||||
}
|
||||
|
||||
func applyExpiryOnTransitionedObject(ctx context.Context, objLayer ObjectLayer, obj ObjectInfo, lcEvent lifecycle.Event, src lcEventSrc) bool {
|
||||
if err := expireTransitionedObject(ctx, objLayer, &obj, obj.ToLifecycleOpts(), lcEvent, src); err != nil {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Note: DeleteAllVersions action is not supported for
|
||||
// transitioned objects
|
||||
globalScannerMetrics.timeILM(lcEvent.Action)(1)
|
||||
}()
|
||||
|
||||
if err = expireTransitionedObject(ctx, objLayer, &obj, lcEvent, src); err != nil {
|
||||
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
||||
return false
|
||||
}
|
||||
@@ -1245,8 +1256,25 @@ func applyExpiryOnNonTransitionedObjects(ctx context.Context, objLayer ObjectLay
|
||||
if lcEvent.Action.DeleteAll() {
|
||||
opts.DeletePrefix = true
|
||||
}
|
||||
var (
|
||||
dobj ObjectInfo
|
||||
err error
|
||||
)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dobj, err := objLayer.DeleteObject(ctx, obj.Bucket, obj.Name, opts)
|
||||
if lcEvent.Action != lifecycle.NoneAction {
|
||||
numVersions := uint64(1)
|
||||
if lcEvent.Action == lifecycle.DeleteAllVersionsAction {
|
||||
numVersions = uint64(obj.NumVersions)
|
||||
}
|
||||
globalScannerMetrics.timeILM(lcEvent.Action)(numVersions)
|
||||
}
|
||||
}()
|
||||
|
||||
dobj, err = objLayer.DeleteObject(ctx, obj.Bucket, obj.Name, opts)
|
||||
if err != nil {
|
||||
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
||||
return false
|
||||
|
||||
+4
-8
@@ -24,6 +24,7 @@ import (
|
||||
"time"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
|
||||
@@ -62,7 +63,7 @@ func storeDataUsageInBackend(ctx context.Context, objAPI ObjectLayer, dui <-chan
|
||||
}
|
||||
}
|
||||
|
||||
var prefixUsageCache timedValue
|
||||
var prefixUsageCache = cachevalue.New[map[string]uint64]()
|
||||
|
||||
// loadPrefixUsageFromBackend returns prefix usages found in passed buckets
|
||||
//
|
||||
@@ -81,7 +82,7 @@ func loadPrefixUsageFromBackend(ctx context.Context, objAPI ObjectLayer, bucket
|
||||
|
||||
// No need to fail upon Update() error, fallback to old value.
|
||||
prefixUsageCache.Relax = true
|
||||
prefixUsageCache.Update = func() (interface{}, error) {
|
||||
prefixUsageCache.Update = func() (map[string]uint64, error) {
|
||||
m := make(map[string]uint64)
|
||||
for _, pool := range z.serverPools {
|
||||
for _, er := range pool.sets {
|
||||
@@ -109,12 +110,7 @@ func loadPrefixUsageFromBackend(ctx context.Context, objAPI ObjectLayer, bucket
|
||||
}
|
||||
})
|
||||
|
||||
v, _ := prefixUsageCache.Get()
|
||||
if v != nil {
|
||||
return v.(map[string]uint64), nil
|
||||
}
|
||||
|
||||
return map[string]uint64{}, nil
|
||||
return prefixUsageCache.Get()
|
||||
}
|
||||
|
||||
func loadDataUsageFromBackend(ctx context.Context, objAPI ObjectLayer) (DataUsageInfo, error) {
|
||||
|
||||
+1
-8
@@ -567,13 +567,6 @@ func (endpoints Endpoints) GetAllStrings() (all []string) {
|
||||
func hostResolveToLocalhost(endpoint Endpoint) bool {
|
||||
hostIPs, err := getHostIP(endpoint.Hostname())
|
||||
if err != nil {
|
||||
// Log the message to console about the host resolving
|
||||
reqInfo := (&logger.ReqInfo{}).AppendTags(
|
||||
"host",
|
||||
endpoint.Hostname(),
|
||||
)
|
||||
ctx := logger.SetReqInfo(GlobalContext, reqInfo)
|
||||
logger.LogOnceIf(ctx, err, endpoint.Hostname(), logger.ErrorKind)
|
||||
return false
|
||||
}
|
||||
var loopback int
|
||||
@@ -867,7 +860,7 @@ func (p PoolEndpointList) UpdateIsLocal() error {
|
||||
))
|
||||
ctx := logger.SetReqInfo(GlobalContext,
|
||||
reqInfo)
|
||||
logger.LogOnceIf(ctx, err, endpoint.Hostname(), logger.ErrorKind)
|
||||
logger.LogOnceIf(ctx, fmt.Errorf("Unable to resolve DNS for %s: %w", endpoint, err), endpoint.Hostname(), logger.ErrorKind)
|
||||
}
|
||||
} else {
|
||||
resolvedList[endpoint] = true
|
||||
|
||||
@@ -58,8 +58,8 @@ func commonETags(etags []string) (etag string, maxima int) {
|
||||
}
|
||||
|
||||
// commonTime returns a maximally occurring time from a list of time.
|
||||
func commonTimeAndOccurence(times []time.Time, group time.Duration) (maxTime time.Time, maxima int) {
|
||||
timeOccurenceMap := make(map[int64]int, len(times))
|
||||
func commonTimeAndOccurrence(times []time.Time, group time.Duration) (maxTime time.Time, maxima int) {
|
||||
timeOccurrenceMap := make(map[int64]int, len(times))
|
||||
groupNano := group.Nanoseconds()
|
||||
// Ignore the uuid sentinel and count the rest.
|
||||
for _, t := range times {
|
||||
@@ -68,7 +68,7 @@ func commonTimeAndOccurence(times []time.Time, group time.Duration) (maxTime tim
|
||||
}
|
||||
nano := t.UnixNano()
|
||||
if group > 0 {
|
||||
for k := range timeOccurenceMap {
|
||||
for k := range timeOccurrenceMap {
|
||||
if k == nano {
|
||||
// We add to ourself later
|
||||
continue
|
||||
@@ -79,12 +79,12 @@ func commonTimeAndOccurence(times []time.Time, group time.Duration) (maxTime tim
|
||||
}
|
||||
// We are within the limit
|
||||
if diff < groupNano {
|
||||
timeOccurenceMap[k]++
|
||||
timeOccurrenceMap[k]++
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add ourself...
|
||||
timeOccurenceMap[nano]++
|
||||
timeOccurrenceMap[nano]++
|
||||
}
|
||||
|
||||
maxima = 0 // Counter for remembering max occurrence of elements.
|
||||
@@ -92,7 +92,7 @@ func commonTimeAndOccurence(times []time.Time, group time.Duration) (maxTime tim
|
||||
|
||||
// Find the common cardinality from previously collected
|
||||
// occurrences of elements.
|
||||
for nano, count := range timeOccurenceMap {
|
||||
for nano, count := range timeOccurrenceMap {
|
||||
if count < maxima {
|
||||
continue
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func commonTimeAndOccurence(times []time.Time, group time.Duration) (maxTime tim
|
||||
// commonTime returns a maximally occurring time from a list of time if it
|
||||
// occurs >= quorum, else return timeSentinel
|
||||
func commonTime(modTimes []time.Time, quorum int) time.Time {
|
||||
if modTime, count := commonTimeAndOccurence(modTimes, 0); count >= quorum {
|
||||
if modTime, count := commonTimeAndOccurrence(modTimes, 0); count >= quorum {
|
||||
return modTime
|
||||
}
|
||||
|
||||
|
||||
@@ -614,7 +614,7 @@ func TestHealingDanglingObject(t *testing.T) {
|
||||
resetGlobalHealState()
|
||||
defer resetGlobalHealState()
|
||||
|
||||
// Set globalStoragClass.STANDARD to EC:4 for this test
|
||||
// Set globalStorageClass.STANDARD to EC:4 for this test
|
||||
saveSC := globalStorageClass
|
||||
defer func() {
|
||||
globalStorageClass.Update(saveSC)
|
||||
|
||||
@@ -937,7 +937,11 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s
|
||||
onlineDisks[i] = nil
|
||||
}
|
||||
|
||||
mrfCheck <- fi.ShallowCopy()
|
||||
select {
|
||||
case mrfCheck <- fi.ShallowCopy():
|
||||
case <-ctx.Done():
|
||||
return fi, onlineMeta, onlineDisks, toObjectErr(ctx.Err(), bucket, object)
|
||||
}
|
||||
|
||||
return fi, onlineMeta, onlineDisks, nil
|
||||
}
|
||||
@@ -960,7 +964,7 @@ func (er erasureObjects) getObjectInfo(ctx context.Context, bucket, object strin
|
||||
return objInfo, nil
|
||||
}
|
||||
|
||||
// getObjectInfoAndQuroum - wrapper for reading object metadata and constructs ObjectInfo, additionally returns write quorum for the object.
|
||||
// getObjectInfoAndQuorum - wrapper for reading object metadata and constructs ObjectInfo, additionally returns write quorum for the object.
|
||||
func (er erasureObjects) getObjectInfoAndQuorum(ctx context.Context, bucket, object string, opts ObjectOptions) (objInfo ObjectInfo, wquorum int, err error) {
|
||||
fi, _, _, err := er.getObjectFileInfo(ctx, bucket, object, opts, false)
|
||||
if err != nil {
|
||||
|
||||
+19
-36
@@ -39,6 +39,7 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio-go/v7/pkg/tags"
|
||||
"github.com/minio/minio/internal/bpool"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
"github.com/minio/minio/internal/config/storageclass"
|
||||
xioutil "github.com/minio/minio/internal/ioutil"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
@@ -1001,20 +1002,10 @@ func (z *erasureServerPools) PutObject(ctx context.Context, bucket string, objec
|
||||
}
|
||||
|
||||
object = encodeDirObject(object)
|
||||
|
||||
if z.SinglePool() {
|
||||
if !isMinioMetaBucketName(bucket) {
|
||||
avail, err := hasSpaceFor(getDiskInfos(ctx, z.serverPools[0].getHashedSet(object).getDisks()...), data.Size())
|
||||
if err != nil {
|
||||
logger.LogOnceIf(ctx, err, "erasure-write-quorum")
|
||||
return ObjectInfo{}, toObjectErr(errErasureWriteQuorum)
|
||||
}
|
||||
if !avail {
|
||||
return ObjectInfo{}, toObjectErr(errDiskFull)
|
||||
}
|
||||
}
|
||||
return z.serverPools[0].PutObject(ctx, bucket, object, data, opts)
|
||||
}
|
||||
|
||||
if !opts.NoLock {
|
||||
ns := z.NewNSLock(bucket, object)
|
||||
lkctx, err := ns.GetLock(ctx, globalOperationTimeout)
|
||||
@@ -1196,6 +1187,13 @@ func (z *erasureServerPools) DeleteObjects(ctx context.Context, bucket string, o
|
||||
}
|
||||
|
||||
func (z *erasureServerPools) CopyObject(ctx context.Context, srcBucket, srcObject, dstBucket, dstObject string, srcInfo ObjectInfo, srcOpts, dstOpts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
if err := checkCopyObjArgs(ctx, srcBucket, srcObject); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
}
|
||||
if err := checkCopyObjArgs(ctx, dstBucket, dstObject); err != nil {
|
||||
return ObjectInfo{}, err
|
||||
}
|
||||
|
||||
srcObject = encodeDirObject(srcObject)
|
||||
dstObject = encodeDirObject(dstObject)
|
||||
|
||||
@@ -1574,21 +1572,11 @@ func (z *erasureServerPools) ListMultipartUploads(ctx context.Context, bucket, p
|
||||
|
||||
// Initiate a new multipart upload on a hashedSet based on object name.
|
||||
func (z *erasureServerPools) NewMultipartUpload(ctx context.Context, bucket, object string, opts ObjectOptions) (*NewMultipartUploadResult, error) {
|
||||
if err := checkNewMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
if err := checkNewMultipartArgs(ctx, bucket, object); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if z.SinglePool() {
|
||||
if !isMinioMetaBucketName(bucket) {
|
||||
avail, err := hasSpaceFor(getDiskInfos(ctx, z.serverPools[0].getHashedSet(object).getDisks()...), -1)
|
||||
if err != nil {
|
||||
logger.LogIf(ctx, err)
|
||||
return nil, toObjectErr(errErasureWriteQuorum)
|
||||
}
|
||||
if !avail {
|
||||
return nil, toObjectErr(errDiskFull)
|
||||
}
|
||||
}
|
||||
return z.serverPools[0].NewMultipartUpload(ctx, bucket, object, opts)
|
||||
}
|
||||
|
||||
@@ -1621,7 +1609,7 @@ func (z *erasureServerPools) NewMultipartUpload(ctx context.Context, bucket, obj
|
||||
|
||||
// Copies a part of an object from source hashedSet to destination hashedSet.
|
||||
func (z *erasureServerPools) CopyObjectPart(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64, srcInfo ObjectInfo, srcOpts, dstOpts ObjectOptions) (PartInfo, error) {
|
||||
if err := checkNewMultipartArgs(ctx, srcBucket, srcObject, z); err != nil {
|
||||
if err := checkNewMultipartArgs(ctx, srcBucket, srcObject); err != nil {
|
||||
return PartInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1631,7 +1619,7 @@ func (z *erasureServerPools) CopyObjectPart(ctx context.Context, srcBucket, srcO
|
||||
|
||||
// PutObjectPart - writes part of an object to hashedSet based on the object name.
|
||||
func (z *erasureServerPools) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *PutObjReader, opts ObjectOptions) (PartInfo, error) {
|
||||
if err := checkPutObjectPartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
if err := checkPutObjectPartArgs(ctx, bucket, object, uploadID); err != nil {
|
||||
return PartInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1663,7 +1651,7 @@ func (z *erasureServerPools) PutObjectPart(ctx context.Context, bucket, object,
|
||||
}
|
||||
|
||||
func (z *erasureServerPools) GetMultipartInfo(ctx context.Context, bucket, object, uploadID string, opts ObjectOptions) (MultipartInfo, error) {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID); err != nil {
|
||||
return MultipartInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1694,7 +1682,7 @@ func (z *erasureServerPools) GetMultipartInfo(ctx context.Context, bucket, objec
|
||||
|
||||
// ListObjectParts - lists all uploaded parts to an object in hashedSet.
|
||||
func (z *erasureServerPools) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int, opts ObjectOptions) (ListPartsInfo, error) {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, uploadID); err != nil {
|
||||
return ListPartsInfo{}, err
|
||||
}
|
||||
|
||||
@@ -1723,7 +1711,7 @@ func (z *erasureServerPools) ListObjectParts(ctx context.Context, bucket, object
|
||||
|
||||
// Aborts an in-progress multipart operation on hashedSet based on the object name.
|
||||
func (z *erasureServerPools) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string, opts ObjectOptions) error {
|
||||
if err := checkAbortMultipartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
if err := checkAbortMultipartArgs(ctx, bucket, object, uploadID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1754,7 +1742,7 @@ func (z *erasureServerPools) AbortMultipartUpload(ctx context.Context, bucket, o
|
||||
|
||||
// CompleteMultipartUpload - completes a pending multipart transaction, on hashedSet based on object name.
|
||||
func (z *erasureServerPools) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []CompletePart, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
if err = checkCompleteMultipartArgs(ctx, bucket, object, uploadID, z); err != nil {
|
||||
if err = checkCompleteMultipartArgs(ctx, bucket, object, uploadID); err != nil {
|
||||
return objInfo, err
|
||||
}
|
||||
|
||||
@@ -1853,7 +1841,7 @@ func (z *erasureServerPools) deleteAll(ctx context.Context, bucket, prefix strin
|
||||
}
|
||||
}
|
||||
|
||||
var listBucketsCache timedValue
|
||||
var listBucketsCache = cachevalue.New[[]BucketInfo]()
|
||||
|
||||
// List all buckets from one of the serverPools, we are not doing merge
|
||||
// sort here just for simplification. As per design it is assumed
|
||||
@@ -1864,7 +1852,7 @@ func (z *erasureServerPools) ListBuckets(ctx context.Context, opts BucketOptions
|
||||
listBucketsCache.TTL = time.Second
|
||||
|
||||
listBucketsCache.Relax = true
|
||||
listBucketsCache.Update = func() (interface{}, error) {
|
||||
listBucketsCache.Update = func() ([]BucketInfo, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
buckets, err = z.s3Peer.ListBuckets(ctx, opts)
|
||||
cancel()
|
||||
@@ -1881,12 +1869,7 @@ func (z *erasureServerPools) ListBuckets(ctx context.Context, opts BucketOptions
|
||||
}
|
||||
})
|
||||
|
||||
v, _ := listBucketsCache.Get()
|
||||
if v != nil {
|
||||
return v.([]BucketInfo), nil
|
||||
}
|
||||
|
||||
return buckets, nil
|
||||
return listBucketsCache.Get()
|
||||
}
|
||||
|
||||
buckets, err = z.s3Peer.ListBuckets(ctx, opts)
|
||||
|
||||
+12
-16
@@ -325,15 +325,18 @@ func (s *erasureSets) GetLockers(setIndex int) func() ([]dsync.NetLocker, string
|
||||
}
|
||||
}
|
||||
|
||||
func (s *erasureSets) GetEndpointStrings(setIndex int) func() []string {
|
||||
return func() []string {
|
||||
eps := make([]string, s.setDriveCount)
|
||||
copy(eps, s.endpointStrings[setIndex*s.setDriveCount:setIndex*s.setDriveCount+s.setDriveCount])
|
||||
return eps
|
||||
}
|
||||
}
|
||||
|
||||
func (s *erasureSets) GetEndpoints(setIndex int) func() []Endpoint {
|
||||
return func() []Endpoint {
|
||||
s.erasureDisksMu.RLock()
|
||||
defer s.erasureDisksMu.RUnlock()
|
||||
|
||||
eps := make([]Endpoint, s.setDriveCount)
|
||||
for i := 0; i < s.setDriveCount; i++ {
|
||||
eps[i] = s.endpoints.Endpoints[setIndex*s.setDriveCount+i]
|
||||
}
|
||||
copy(eps, s.endpoints.Endpoints[setIndex*s.setDriveCount:setIndex*s.setDriveCount+s.setDriveCount])
|
||||
return eps
|
||||
}
|
||||
}
|
||||
@@ -463,7 +466,6 @@ func newErasureSets(ctx context.Context, endpoints PoolEndpoints, storageDisks [
|
||||
return
|
||||
}
|
||||
disk.SetDiskLoc(s.poolIndex, m, n)
|
||||
s.endpointStrings[m*setDriveCount+n] = disk.String()
|
||||
s.erasureDisks[m][n] = disk
|
||||
}(disk, i, j)
|
||||
}
|
||||
@@ -478,6 +480,7 @@ func newErasureSets(ctx context.Context, endpoints PoolEndpoints, storageDisks [
|
||||
getDisks: s.GetDisks(i),
|
||||
getLockers: s.GetLockers(i),
|
||||
getEndpoints: s.GetEndpoints(i),
|
||||
getEndpointStrings: s.GetEndpointStrings(i),
|
||||
nsMutex: mutex,
|
||||
}
|
||||
}(i)
|
||||
@@ -571,18 +574,11 @@ func auditObjectErasureSet(ctx context.Context, object string, set *erasureObjec
|
||||
return
|
||||
}
|
||||
|
||||
object = decodeDirObject(object)
|
||||
endpoints := set.getEndpoints()
|
||||
disksEndpoints := make([]string, 0, len(endpoints))
|
||||
for _, endpoint := range endpoints {
|
||||
disksEndpoints = append(disksEndpoints, endpoint.String())
|
||||
}
|
||||
|
||||
op := auditObjectOp{
|
||||
Name: object,
|
||||
Name: decodeDirObject(object),
|
||||
Pool: set.poolIndex + 1,
|
||||
Set: set.setIndex + 1,
|
||||
Disks: disksEndpoints,
|
||||
Disks: set.getEndpointStrings(),
|
||||
}
|
||||
|
||||
logger.GetReqInfo(ctx).AppendTags("objectLocation", op)
|
||||
|
||||
+5
-1
@@ -58,10 +58,14 @@ type erasureObjects struct {
|
||||
// getLockers returns list of remote and local lockers.
|
||||
getLockers func() ([]dsync.NetLocker, string)
|
||||
|
||||
// getEndpoints returns list of endpoint strings belonging this set.
|
||||
// getEndpoints returns list of endpoint belonging this set.
|
||||
// some may be local and some remote.
|
||||
getEndpoints func() []Endpoint
|
||||
|
||||
// getEndpoints returns list of endpoint strings belonging this set.
|
||||
// some may be local and some remote.
|
||||
getEndpointStrings func() []string
|
||||
|
||||
// Locker mutex map.
|
||||
nsMutex *nsLockMap
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
// Tests validate bucket LocationConstraint.
|
||||
func TestIsValidLocationContraint(t *testing.T) {
|
||||
func TestIsValidLocationConstraint(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
|
||||
@@ -113,6 +113,10 @@ func metricsRequestAuthenticate(req *http.Request) (*xjwt.MapClaims, []string, b
|
||||
return nil, errInvalidAccessKeyID
|
||||
}
|
||||
cred := u.Credentials
|
||||
// Expired credentials return error.
|
||||
if cred.IsTemp() && cred.IsExpired() {
|
||||
return nil, errInvalidAccessKeyID
|
||||
}
|
||||
return []byte(cred.SecretKey), nil
|
||||
} // this means claims.AccessKey == rootAccessKey
|
||||
if !globalAPIConfig.permitRootAccess() {
|
||||
|
||||
+10
-7
@@ -17,6 +17,8 @@
|
||||
|
||||
package cmd
|
||||
|
||||
//go:generate msgp -file=$GOFILE -unexported
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
@@ -36,12 +38,9 @@ type lockRequesterInfo struct {
|
||||
TimeLastRefresh time.Time // Timestamp for last lock refresh.
|
||||
Source string // Contains line, function and filename requesting the lock.
|
||||
Group bool // indicates if it was a group lock.
|
||||
// Owner represents the UUID of the owner who originally requested the lock
|
||||
// useful in expiry.
|
||||
Owner string
|
||||
// Quorum represents the quorum required for this lock to be active.
|
||||
Quorum int
|
||||
idx int
|
||||
Owner string // Owner represents the UUID of the owner who originally requested the lock.
|
||||
Quorum int // Quorum represents the quorum required for this lock to be active.
|
||||
idx int `msg:"-"` // index of the lock in the lockMap.
|
||||
}
|
||||
|
||||
// isWriteLock returns whether the lock is a write or read lock.
|
||||
@@ -50,6 +49,8 @@ func isWriteLock(lri []lockRequesterInfo) bool {
|
||||
}
|
||||
|
||||
// localLocker implements Dsync.NetLocker
|
||||
//
|
||||
//msgp:ignore localLocker
|
||||
type localLocker struct {
|
||||
mutex sync.Mutex
|
||||
lockMap map[string][]lockRequesterInfo
|
||||
@@ -238,7 +239,9 @@ func (l *localLocker) stats() lockStats {
|
||||
return st
|
||||
}
|
||||
|
||||
func (l *localLocker) DupLockMap() map[string][]lockRequesterInfo {
|
||||
type localLockMap map[string][]lockRequesterInfo
|
||||
|
||||
func (l *localLocker) DupLockMap() localLockMap {
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
|
||||
@@ -0,0 +1,620 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *localLockMap) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var zb0004 uint32
|
||||
zb0004, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
if (*z) == nil {
|
||||
(*z) = make(localLockMap, zb0004)
|
||||
} else if len((*z)) > 0 {
|
||||
for key := range *z {
|
||||
delete((*z), key)
|
||||
}
|
||||
}
|
||||
for zb0004 > 0 {
|
||||
zb0004--
|
||||
var zb0001 string
|
||||
var zb0002 []lockRequesterInfo
|
||||
zb0001, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
var zb0005 uint32
|
||||
zb0005, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
if cap(zb0002) >= int(zb0005) {
|
||||
zb0002 = (zb0002)[:zb0005]
|
||||
} else {
|
||||
zb0002 = make([]lockRequesterInfo, zb0005)
|
||||
}
|
||||
for zb0003 := range zb0002 {
|
||||
err = zb0002[zb0003].DecodeMsg(dc)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, zb0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
(*z)[zb0001] = zb0002
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z localLockMap) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteMapHeader(uint32(len(z)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0006, zb0007 := range z {
|
||||
err = en.WriteString(zb0006)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(zb0007)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0006)
|
||||
return
|
||||
}
|
||||
for zb0008 := range zb0007 {
|
||||
err = zb0007[zb0008].EncodeMsg(en)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0006, zb0008)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z localLockMap) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z)))
|
||||
for zb0006, zb0007 := range z {
|
||||
o = msgp.AppendString(o, zb0006)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(zb0007)))
|
||||
for zb0008 := range zb0007 {
|
||||
o, err = zb0007[zb0008].MarshalMsg(o)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0006, zb0008)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *localLockMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var zb0004 uint32
|
||||
zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
if (*z) == nil {
|
||||
(*z) = make(localLockMap, zb0004)
|
||||
} else if len((*z)) > 0 {
|
||||
for key := range *z {
|
||||
delete((*z), key)
|
||||
}
|
||||
}
|
||||
for zb0004 > 0 {
|
||||
var zb0001 string
|
||||
var zb0002 []lockRequesterInfo
|
||||
zb0004--
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
var zb0005 uint32
|
||||
zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
if cap(zb0002) >= int(zb0005) {
|
||||
zb0002 = (zb0002)[:zb0005]
|
||||
} else {
|
||||
zb0002 = make([]lockRequesterInfo, zb0005)
|
||||
}
|
||||
for zb0003 := range zb0002 {
|
||||
bts, err = zb0002[zb0003].UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, zb0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
(*z)[zb0001] = zb0002
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z localLockMap) Msgsize() (s int) {
|
||||
s = msgp.MapHeaderSize
|
||||
if z != nil {
|
||||
for zb0006, zb0007 := range z {
|
||||
_ = zb0007
|
||||
s += msgp.StringPrefixSize + len(zb0006) + msgp.ArrayHeaderSize
|
||||
for zb0008 := range zb0007 {
|
||||
s += zb0007[zb0008].Msgsize()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *lockRequesterInfo) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Name":
|
||||
z.Name, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
case "Writer":
|
||||
z.Writer, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writer")
|
||||
return
|
||||
}
|
||||
case "UID":
|
||||
z.UID, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UID")
|
||||
return
|
||||
}
|
||||
case "Timestamp":
|
||||
z.Timestamp, err = dc.ReadTime()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Timestamp")
|
||||
return
|
||||
}
|
||||
case "TimeLastRefresh":
|
||||
z.TimeLastRefresh, err = dc.ReadTime()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "TimeLastRefresh")
|
||||
return
|
||||
}
|
||||
case "Source":
|
||||
z.Source, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Source")
|
||||
return
|
||||
}
|
||||
case "Group":
|
||||
z.Group, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Group")
|
||||
return
|
||||
}
|
||||
case "Owner":
|
||||
z.Owner, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Owner")
|
||||
return
|
||||
}
|
||||
case "Quorum":
|
||||
z.Quorum, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Quorum")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *lockRequesterInfo) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 9
|
||||
// write "Name"
|
||||
err = en.Append(0x89, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Name)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
// write "Writer"
|
||||
err = en.Append(0xa6, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Writer)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writer")
|
||||
return
|
||||
}
|
||||
// write "UID"
|
||||
err = en.Append(0xa3, 0x55, 0x49, 0x44)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.UID)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UID")
|
||||
return
|
||||
}
|
||||
// write "Timestamp"
|
||||
err = en.Append(0xa9, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteTime(z.Timestamp)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Timestamp")
|
||||
return
|
||||
}
|
||||
// write "TimeLastRefresh"
|
||||
err = en.Append(0xaf, 0x54, 0x69, 0x6d, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteTime(z.TimeLastRefresh)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "TimeLastRefresh")
|
||||
return
|
||||
}
|
||||
// write "Source"
|
||||
err = en.Append(0xa6, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Source)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Source")
|
||||
return
|
||||
}
|
||||
// write "Group"
|
||||
err = en.Append(0xa5, 0x47, 0x72, 0x6f, 0x75, 0x70)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Group)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Group")
|
||||
return
|
||||
}
|
||||
// write "Owner"
|
||||
err = en.Append(0xa5, 0x4f, 0x77, 0x6e, 0x65, 0x72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Owner)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Owner")
|
||||
return
|
||||
}
|
||||
// write "Quorum"
|
||||
err = en.Append(0xa6, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.Quorum)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Quorum")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *lockRequesterInfo) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 9
|
||||
// string "Name"
|
||||
o = append(o, 0x89, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
||||
o = msgp.AppendString(o, z.Name)
|
||||
// string "Writer"
|
||||
o = append(o, 0xa6, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72)
|
||||
o = msgp.AppendBool(o, z.Writer)
|
||||
// string "UID"
|
||||
o = append(o, 0xa3, 0x55, 0x49, 0x44)
|
||||
o = msgp.AppendString(o, z.UID)
|
||||
// string "Timestamp"
|
||||
o = append(o, 0xa9, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70)
|
||||
o = msgp.AppendTime(o, z.Timestamp)
|
||||
// string "TimeLastRefresh"
|
||||
o = append(o, 0xaf, 0x54, 0x69, 0x6d, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68)
|
||||
o = msgp.AppendTime(o, z.TimeLastRefresh)
|
||||
// string "Source"
|
||||
o = append(o, 0xa6, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65)
|
||||
o = msgp.AppendString(o, z.Source)
|
||||
// string "Group"
|
||||
o = append(o, 0xa5, 0x47, 0x72, 0x6f, 0x75, 0x70)
|
||||
o = msgp.AppendBool(o, z.Group)
|
||||
// string "Owner"
|
||||
o = append(o, 0xa5, 0x4f, 0x77, 0x6e, 0x65, 0x72)
|
||||
o = msgp.AppendString(o, z.Owner)
|
||||
// string "Quorum"
|
||||
o = append(o, 0xa6, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d)
|
||||
o = msgp.AppendInt(o, z.Quorum)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *lockRequesterInfo) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Name":
|
||||
z.Name, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
case "Writer":
|
||||
z.Writer, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writer")
|
||||
return
|
||||
}
|
||||
case "UID":
|
||||
z.UID, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UID")
|
||||
return
|
||||
}
|
||||
case "Timestamp":
|
||||
z.Timestamp, bts, err = msgp.ReadTimeBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Timestamp")
|
||||
return
|
||||
}
|
||||
case "TimeLastRefresh":
|
||||
z.TimeLastRefresh, bts, err = msgp.ReadTimeBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "TimeLastRefresh")
|
||||
return
|
||||
}
|
||||
case "Source":
|
||||
z.Source, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Source")
|
||||
return
|
||||
}
|
||||
case "Group":
|
||||
z.Group, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Group")
|
||||
return
|
||||
}
|
||||
case "Owner":
|
||||
z.Owner, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Owner")
|
||||
return
|
||||
}
|
||||
case "Quorum":
|
||||
z.Quorum, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Quorum")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *lockRequesterInfo) Msgsize() (s int) {
|
||||
s = 1 + 5 + msgp.StringPrefixSize + len(z.Name) + 7 + msgp.BoolSize + 4 + msgp.StringPrefixSize + len(z.UID) + 10 + msgp.TimeSize + 16 + msgp.TimeSize + 7 + msgp.StringPrefixSize + len(z.Source) + 6 + msgp.BoolSize + 6 + msgp.StringPrefixSize + len(z.Owner) + 7 + msgp.IntSize
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *lockStats) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Total":
|
||||
z.Total, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Total")
|
||||
return
|
||||
}
|
||||
case "Writes":
|
||||
z.Writes, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writes")
|
||||
return
|
||||
}
|
||||
case "Reads":
|
||||
z.Reads, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Reads")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z lockStats) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 3
|
||||
// write "Total"
|
||||
err = en.Append(0x83, 0xa5, 0x54, 0x6f, 0x74, 0x61, 0x6c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.Total)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Total")
|
||||
return
|
||||
}
|
||||
// write "Writes"
|
||||
err = en.Append(0xa6, 0x57, 0x72, 0x69, 0x74, 0x65, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.Writes)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writes")
|
||||
return
|
||||
}
|
||||
// write "Reads"
|
||||
err = en.Append(0xa5, 0x52, 0x65, 0x61, 0x64, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.Reads)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Reads")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z lockStats) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 3
|
||||
// string "Total"
|
||||
o = append(o, 0x83, 0xa5, 0x54, 0x6f, 0x74, 0x61, 0x6c)
|
||||
o = msgp.AppendInt(o, z.Total)
|
||||
// string "Writes"
|
||||
o = append(o, 0xa6, 0x57, 0x72, 0x69, 0x74, 0x65, 0x73)
|
||||
o = msgp.AppendInt(o, z.Writes)
|
||||
// string "Reads"
|
||||
o = append(o, 0xa5, 0x52, 0x65, 0x61, 0x64, 0x73)
|
||||
o = msgp.AppendInt(o, z.Reads)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *lockStats) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Total":
|
||||
z.Total, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Total")
|
||||
return
|
||||
}
|
||||
case "Writes":
|
||||
z.Writes, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Writes")
|
||||
return
|
||||
}
|
||||
case "Reads":
|
||||
z.Reads, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Reads")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z lockStats) Msgsize() (s int) {
|
||||
s = 1 + 6 + msgp.IntSize + 7 + msgp.IntSize + 6 + msgp.IntSize
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshallocalLockMap(t *testing.T) {
|
||||
v := localLockMap{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsglocalLockMap(b *testing.B) {
|
||||
v := localLockMap{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsglocalLockMap(b *testing.B) {
|
||||
v := localLockMap{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshallocalLockMap(b *testing.B) {
|
||||
v := localLockMap{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodelocalLockMap(t *testing.T) {
|
||||
v := localLockMap{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodelocalLockMap Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := localLockMap{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodelocalLockMap(b *testing.B) {
|
||||
v := localLockMap{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodelocalLockMap(b *testing.B) {
|
||||
v := localLockMap{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshallockRequesterInfo(t *testing.T) {
|
||||
v := lockRequesterInfo{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsglockRequesterInfo(b *testing.B) {
|
||||
v := lockRequesterInfo{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsglockRequesterInfo(b *testing.B) {
|
||||
v := lockRequesterInfo{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshallockRequesterInfo(b *testing.B) {
|
||||
v := lockRequesterInfo{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodelockRequesterInfo(t *testing.T) {
|
||||
v := lockRequesterInfo{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodelockRequesterInfo Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := lockRequesterInfo{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodelockRequesterInfo(b *testing.B) {
|
||||
v := lockRequesterInfo{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodelockRequesterInfo(b *testing.B) {
|
||||
v := lockRequesterInfo{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshallockStats(t *testing.T) {
|
||||
v := lockStats{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsglockStats(b *testing.B) {
|
||||
v := lockStats{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsglockStats(b *testing.B) {
|
||||
v := lockStats{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshallockStats(b *testing.B) {
|
||||
v := lockStats{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodelockStats(t *testing.T) {
|
||||
v := lockStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodelockStats Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := lockStats{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodelockStats(b *testing.B) {
|
||||
v := lockStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodelockStats(b *testing.B) {
|
||||
v := lockStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-5
@@ -42,6 +42,8 @@ import (
|
||||
"github.com/minio/pkg/v2/console"
|
||||
)
|
||||
|
||||
//go:generate msgp -file $GOFILE -unexported
|
||||
|
||||
type listPathOptions struct {
|
||||
// ID of the listing.
|
||||
// This will be used to persist the list.
|
||||
@@ -99,18 +101,18 @@ type listPathOptions struct {
|
||||
|
||||
// Versioning config is used for if the path
|
||||
// has versioning enabled.
|
||||
Versioning *versioning.Versioning
|
||||
Versioning *versioning.Versioning `msg:"-"`
|
||||
|
||||
// Lifecycle performs filtering based on lifecycle.
|
||||
// This will filter out objects if the most recent version should be deleted by lifecycle.
|
||||
// Is not transferred across request calls.
|
||||
Lifecycle *lifecycle.Lifecycle
|
||||
Lifecycle *lifecycle.Lifecycle `msg:"-"`
|
||||
|
||||
// Retention configuration, needed to be passed along with lifecycle if set.
|
||||
Retention lock.Retention
|
||||
Retention lock.Retention `msg:"-"`
|
||||
|
||||
// Replication configuration
|
||||
Replication replicationConfig
|
||||
Replication replicationConfig `msg:"-"`
|
||||
|
||||
// StopDiskAtLimit will stop listing on each disk when limit number off objects has been returned.
|
||||
StopDiskAtLimit bool
|
||||
@@ -217,7 +219,10 @@ func (o *listPathOptions) gatherResults(ctx context.Context, in <-chan metaCache
|
||||
// Do not return io.EOF
|
||||
if resCh != nil {
|
||||
resErr = nil
|
||||
resCh <- results
|
||||
select {
|
||||
case resCh <- results:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
resCh = nil
|
||||
returned = true
|
||||
}
|
||||
@@ -767,6 +772,7 @@ func (er *erasureObjects) listPath(ctx context.Context, o listPathOptions, resul
|
||||
})
|
||||
}
|
||||
|
||||
//msgp:ignore metaCacheRPC
|
||||
type metaCacheRPC struct {
|
||||
o listPathOptions
|
||||
mu sync.Mutex
|
||||
@@ -917,6 +923,7 @@ func (er *erasureObjects) saveMetaCacheStream(ctx context.Context, mc *metaCache
|
||||
return nil
|
||||
}
|
||||
|
||||
//msgp:ignore listPathRawOptions
|
||||
type listPathRawOptions struct {
|
||||
disks []StorageAPI
|
||||
fallbackDisks []StorageAPI
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *listPathOptions) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "ID":
|
||||
z.ID, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "ID")
|
||||
return
|
||||
}
|
||||
case "Bucket":
|
||||
z.Bucket, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bucket")
|
||||
return
|
||||
}
|
||||
case "BaseDir":
|
||||
z.BaseDir, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "BaseDir")
|
||||
return
|
||||
}
|
||||
case "Prefix":
|
||||
z.Prefix, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Prefix")
|
||||
return
|
||||
}
|
||||
case "FilterPrefix":
|
||||
z.FilterPrefix, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "FilterPrefix")
|
||||
return
|
||||
}
|
||||
case "Marker":
|
||||
z.Marker, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Marker")
|
||||
return
|
||||
}
|
||||
case "Limit":
|
||||
z.Limit, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Limit")
|
||||
return
|
||||
}
|
||||
case "AskDisks":
|
||||
z.AskDisks, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "AskDisks")
|
||||
return
|
||||
}
|
||||
case "InclDeleted":
|
||||
z.InclDeleted, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "InclDeleted")
|
||||
return
|
||||
}
|
||||
case "Recursive":
|
||||
z.Recursive, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Recursive")
|
||||
return
|
||||
}
|
||||
case "Separator":
|
||||
z.Separator, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Separator")
|
||||
return
|
||||
}
|
||||
case "Create":
|
||||
z.Create, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Create")
|
||||
return
|
||||
}
|
||||
case "IncludeDirectories":
|
||||
z.IncludeDirectories, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "IncludeDirectories")
|
||||
return
|
||||
}
|
||||
case "Transient":
|
||||
z.Transient, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Transient")
|
||||
return
|
||||
}
|
||||
case "Versioned":
|
||||
z.Versioned, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Versioned")
|
||||
return
|
||||
}
|
||||
case "StopDiskAtLimit":
|
||||
z.StopDiskAtLimit, err = dc.ReadBool()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StopDiskAtLimit")
|
||||
return
|
||||
}
|
||||
case "pool":
|
||||
z.pool, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "pool")
|
||||
return
|
||||
}
|
||||
case "set":
|
||||
z.set, err = dc.ReadInt()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "set")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *listPathOptions) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 18
|
||||
// write "ID"
|
||||
err = en.Append(0xde, 0x0, 0x12, 0xa2, 0x49, 0x44)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.ID)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "ID")
|
||||
return
|
||||
}
|
||||
// write "Bucket"
|
||||
err = en.Append(0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Bucket)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bucket")
|
||||
return
|
||||
}
|
||||
// write "BaseDir"
|
||||
err = en.Append(0xa7, 0x42, 0x61, 0x73, 0x65, 0x44, 0x69, 0x72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.BaseDir)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "BaseDir")
|
||||
return
|
||||
}
|
||||
// write "Prefix"
|
||||
err = en.Append(0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Prefix)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Prefix")
|
||||
return
|
||||
}
|
||||
// write "FilterPrefix"
|
||||
err = en.Append(0xac, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.FilterPrefix)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "FilterPrefix")
|
||||
return
|
||||
}
|
||||
// write "Marker"
|
||||
err = en.Append(0xa6, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Marker)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Marker")
|
||||
return
|
||||
}
|
||||
// write "Limit"
|
||||
err = en.Append(0xa5, 0x4c, 0x69, 0x6d, 0x69, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.Limit)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Limit")
|
||||
return
|
||||
}
|
||||
// write "AskDisks"
|
||||
err = en.Append(0xa8, 0x41, 0x73, 0x6b, 0x44, 0x69, 0x73, 0x6b, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.AskDisks)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "AskDisks")
|
||||
return
|
||||
}
|
||||
// write "InclDeleted"
|
||||
err = en.Append(0xab, 0x49, 0x6e, 0x63, 0x6c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.InclDeleted)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "InclDeleted")
|
||||
return
|
||||
}
|
||||
// write "Recursive"
|
||||
err = en.Append(0xa9, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Recursive)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Recursive")
|
||||
return
|
||||
}
|
||||
// write "Separator"
|
||||
err = en.Append(0xa9, 0x53, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Separator)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Separator")
|
||||
return
|
||||
}
|
||||
// write "Create"
|
||||
err = en.Append(0xa6, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Create)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Create")
|
||||
return
|
||||
}
|
||||
// write "IncludeDirectories"
|
||||
err = en.Append(0xb2, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.IncludeDirectories)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "IncludeDirectories")
|
||||
return
|
||||
}
|
||||
// write "Transient"
|
||||
err = en.Append(0xa9, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x65, 0x6e, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Transient)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Transient")
|
||||
return
|
||||
}
|
||||
// write "Versioned"
|
||||
err = en.Append(0xa9, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.Versioned)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Versioned")
|
||||
return
|
||||
}
|
||||
// write "StopDiskAtLimit"
|
||||
err = en.Append(0xaf, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x69, 0x73, 0x6b, 0x41, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteBool(z.StopDiskAtLimit)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StopDiskAtLimit")
|
||||
return
|
||||
}
|
||||
// write "pool"
|
||||
err = en.Append(0xa4, 0x70, 0x6f, 0x6f, 0x6c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.pool)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "pool")
|
||||
return
|
||||
}
|
||||
// write "set"
|
||||
err = en.Append(0xa3, 0x73, 0x65, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt(z.set)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "set")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *listPathOptions) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 18
|
||||
// string "ID"
|
||||
o = append(o, 0xde, 0x0, 0x12, 0xa2, 0x49, 0x44)
|
||||
o = msgp.AppendString(o, z.ID)
|
||||
// string "Bucket"
|
||||
o = append(o, 0xa6, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74)
|
||||
o = msgp.AppendString(o, z.Bucket)
|
||||
// string "BaseDir"
|
||||
o = append(o, 0xa7, 0x42, 0x61, 0x73, 0x65, 0x44, 0x69, 0x72)
|
||||
o = msgp.AppendString(o, z.BaseDir)
|
||||
// string "Prefix"
|
||||
o = append(o, 0xa6, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78)
|
||||
o = msgp.AppendString(o, z.Prefix)
|
||||
// string "FilterPrefix"
|
||||
o = append(o, 0xac, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78)
|
||||
o = msgp.AppendString(o, z.FilterPrefix)
|
||||
// string "Marker"
|
||||
o = append(o, 0xa6, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x72)
|
||||
o = msgp.AppendString(o, z.Marker)
|
||||
// string "Limit"
|
||||
o = append(o, 0xa5, 0x4c, 0x69, 0x6d, 0x69, 0x74)
|
||||
o = msgp.AppendInt(o, z.Limit)
|
||||
// string "AskDisks"
|
||||
o = append(o, 0xa8, 0x41, 0x73, 0x6b, 0x44, 0x69, 0x73, 0x6b, 0x73)
|
||||
o = msgp.AppendString(o, z.AskDisks)
|
||||
// string "InclDeleted"
|
||||
o = append(o, 0xab, 0x49, 0x6e, 0x63, 0x6c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64)
|
||||
o = msgp.AppendBool(o, z.InclDeleted)
|
||||
// string "Recursive"
|
||||
o = append(o, 0xa9, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65)
|
||||
o = msgp.AppendBool(o, z.Recursive)
|
||||
// string "Separator"
|
||||
o = append(o, 0xa9, 0x53, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72)
|
||||
o = msgp.AppendString(o, z.Separator)
|
||||
// string "Create"
|
||||
o = append(o, 0xa6, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65)
|
||||
o = msgp.AppendBool(o, z.Create)
|
||||
// string "IncludeDirectories"
|
||||
o = append(o, 0xb2, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73)
|
||||
o = msgp.AppendBool(o, z.IncludeDirectories)
|
||||
// string "Transient"
|
||||
o = append(o, 0xa9, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x65, 0x6e, 0x74)
|
||||
o = msgp.AppendBool(o, z.Transient)
|
||||
// string "Versioned"
|
||||
o = append(o, 0xa9, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64)
|
||||
o = msgp.AppendBool(o, z.Versioned)
|
||||
// string "StopDiskAtLimit"
|
||||
o = append(o, 0xaf, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x69, 0x73, 0x6b, 0x41, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74)
|
||||
o = msgp.AppendBool(o, z.StopDiskAtLimit)
|
||||
// string "pool"
|
||||
o = append(o, 0xa4, 0x70, 0x6f, 0x6f, 0x6c)
|
||||
o = msgp.AppendInt(o, z.pool)
|
||||
// string "set"
|
||||
o = append(o, 0xa3, 0x73, 0x65, 0x74)
|
||||
o = msgp.AppendInt(o, z.set)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *listPathOptions) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "ID":
|
||||
z.ID, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "ID")
|
||||
return
|
||||
}
|
||||
case "Bucket":
|
||||
z.Bucket, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bucket")
|
||||
return
|
||||
}
|
||||
case "BaseDir":
|
||||
z.BaseDir, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "BaseDir")
|
||||
return
|
||||
}
|
||||
case "Prefix":
|
||||
z.Prefix, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Prefix")
|
||||
return
|
||||
}
|
||||
case "FilterPrefix":
|
||||
z.FilterPrefix, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "FilterPrefix")
|
||||
return
|
||||
}
|
||||
case "Marker":
|
||||
z.Marker, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Marker")
|
||||
return
|
||||
}
|
||||
case "Limit":
|
||||
z.Limit, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Limit")
|
||||
return
|
||||
}
|
||||
case "AskDisks":
|
||||
z.AskDisks, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "AskDisks")
|
||||
return
|
||||
}
|
||||
case "InclDeleted":
|
||||
z.InclDeleted, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "InclDeleted")
|
||||
return
|
||||
}
|
||||
case "Recursive":
|
||||
z.Recursive, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Recursive")
|
||||
return
|
||||
}
|
||||
case "Separator":
|
||||
z.Separator, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Separator")
|
||||
return
|
||||
}
|
||||
case "Create":
|
||||
z.Create, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Create")
|
||||
return
|
||||
}
|
||||
case "IncludeDirectories":
|
||||
z.IncludeDirectories, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "IncludeDirectories")
|
||||
return
|
||||
}
|
||||
case "Transient":
|
||||
z.Transient, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Transient")
|
||||
return
|
||||
}
|
||||
case "Versioned":
|
||||
z.Versioned, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Versioned")
|
||||
return
|
||||
}
|
||||
case "StopDiskAtLimit":
|
||||
z.StopDiskAtLimit, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StopDiskAtLimit")
|
||||
return
|
||||
}
|
||||
case "pool":
|
||||
z.pool, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "pool")
|
||||
return
|
||||
}
|
||||
case "set":
|
||||
z.set, bts, err = msgp.ReadIntBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "set")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *listPathOptions) Msgsize() (s int) {
|
||||
s = 3 + 3 + msgp.StringPrefixSize + len(z.ID) + 7 + msgp.StringPrefixSize + len(z.Bucket) + 8 + msgp.StringPrefixSize + len(z.BaseDir) + 7 + msgp.StringPrefixSize + len(z.Prefix) + 13 + msgp.StringPrefixSize + len(z.FilterPrefix) + 7 + msgp.StringPrefixSize + len(z.Marker) + 6 + msgp.IntSize + 9 + msgp.StringPrefixSize + len(z.AskDisks) + 12 + msgp.BoolSize + 10 + msgp.BoolSize + 10 + msgp.StringPrefixSize + len(z.Separator) + 7 + msgp.BoolSize + 19 + msgp.BoolSize + 10 + msgp.BoolSize + 10 + msgp.BoolSize + 16 + msgp.BoolSize + 5 + msgp.IntSize + 4 + msgp.IntSize
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshallistPathOptions(t *testing.T) {
|
||||
v := listPathOptions{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsglistPathOptions(b *testing.B) {
|
||||
v := listPathOptions{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsglistPathOptions(b *testing.B) {
|
||||
v := listPathOptions{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshallistPathOptions(b *testing.B) {
|
||||
v := listPathOptions{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodelistPathOptions(t *testing.T) {
|
||||
v := listPathOptions{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodelistPathOptions Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := listPathOptions{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodelistPathOptions(b *testing.B) {
|
||||
v := listPathOptions{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodelistPathOptions(b *testing.B) {
|
||||
v := listPathOptions{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -299,7 +299,11 @@ func (s *xlStorage) WalkDir(ctx context.Context, opts WalkDirOptions, wr io.Writ
|
||||
// If directory entry on stack before this, pop it now.
|
||||
for len(dirStack) > 0 && dirStack[len(dirStack)-1] < meta.name {
|
||||
pop := dirStack[len(dirStack)-1]
|
||||
out <- metaCacheEntry{name: pop}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case out <- metaCacheEntry{name: pop}:
|
||||
}
|
||||
if opts.Recursive {
|
||||
// Scan folder we found. Should be in correct sort order where we are.
|
||||
err := scanDir(pop)
|
||||
@@ -368,7 +372,11 @@ func (s *xlStorage) WalkDir(ctx context.Context, opts WalkDirOptions, wr io.Writ
|
||||
return ctx.Err()
|
||||
}
|
||||
pop := dirStack[len(dirStack)-1]
|
||||
out <- metaCacheEntry{name: pop}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case out <- metaCacheEntry{name: pop}:
|
||||
}
|
||||
if opts.Recursive {
|
||||
// Scan folder we found. Should be in correct sort order where we are.
|
||||
logger.LogIf(ctx, scanDir(pop))
|
||||
|
||||
+19
-12
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/minio/kes-go"
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/bucket/lifecycle"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
xioutil "github.com/minio/minio/internal/ioutil"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
"github.com/minio/minio/internal/mcontext"
|
||||
@@ -42,6 +43,8 @@ import (
|
||||
"github.com/prometheus/procfs"
|
||||
)
|
||||
|
||||
//go:generate msgp -file=$GOFILE -unexported -io=false
|
||||
|
||||
var (
|
||||
nodeCollector *minioNodeCollector
|
||||
clusterCollector *minioClusterCollector
|
||||
@@ -328,7 +331,7 @@ type Metric struct {
|
||||
|
||||
// MetricsGroup are a group of metrics that are initialized together.
|
||||
type MetricsGroup struct {
|
||||
metricsCache timedValue
|
||||
metricsCache *cachevalue.Cache[[]Metric] `msg:"-"`
|
||||
cacheInterval time.Duration
|
||||
metricsGroupOpts MetricsGroupOpts
|
||||
}
|
||||
@@ -352,10 +355,11 @@ type MetricsGroupOpts struct {
|
||||
// RegisterRead register the metrics populator function to be used
|
||||
// to populate new values upon cache invalidation.
|
||||
func (g *MetricsGroup) RegisterRead(read func(ctx context.Context) []Metric) {
|
||||
g.metricsCache = cachevalue.New[[]Metric]()
|
||||
g.metricsCache.Once.Do(func() {
|
||||
g.metricsCache.Relax = true
|
||||
g.metricsCache.TTL = g.cacheInterval
|
||||
g.metricsCache.Update = func() (interface{}, error) {
|
||||
g.metricsCache.Update = func() ([]Metric, error) {
|
||||
if g.metricsGroupOpts.dependGlobalObjectAPI {
|
||||
objLayer := newObjectLayerFn()
|
||||
// Service not initialized yet
|
||||
@@ -418,14 +422,14 @@ func (g *MetricsGroup) RegisterRead(read func(ctx context.Context) []Metric) {
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Metric) copyMetric() Metric {
|
||||
func (m *Metric) clone() Metric {
|
||||
metric := Metric{
|
||||
Description: m.Description,
|
||||
Value: m.Value,
|
||||
HistogramBucketLabel: m.HistogramBucketLabel,
|
||||
StaticLabels: make(map[string]string),
|
||||
VariableLabels: make(map[string]string),
|
||||
Histogram: make(map[string]uint64),
|
||||
StaticLabels: make(map[string]string, len(m.StaticLabels)),
|
||||
VariableLabels: make(map[string]string, len(m.VariableLabels)),
|
||||
Histogram: make(map[string]uint64, len(m.Histogram)),
|
||||
}
|
||||
for k, v := range m.StaticLabels {
|
||||
metric.StaticLabels[k] = v
|
||||
@@ -443,15 +447,14 @@ func (m *Metric) copyMetric() Metric {
|
||||
// once the TTL expires "read()" registered function is called
|
||||
// to return the new values and updated.
|
||||
func (g *MetricsGroup) Get() (metrics []Metric) {
|
||||
c, _ := g.metricsCache.Get()
|
||||
m, ok := c.([]Metric)
|
||||
if !ok {
|
||||
m, _ := g.metricsCache.Get()
|
||||
if len(m) == 0 {
|
||||
return []Metric{}
|
||||
}
|
||||
|
||||
metrics = make([]Metric, 0, len(m))
|
||||
for i := range m {
|
||||
metrics = append(metrics, m[i].copyMetric())
|
||||
metrics = append(metrics, m[i].clone())
|
||||
}
|
||||
return metrics
|
||||
}
|
||||
@@ -536,7 +539,7 @@ func getNodeDriveTimeoutErrorsMD() MetricDescription {
|
||||
}
|
||||
}
|
||||
|
||||
func getNodeDriveAvailablityErrorsMD() MetricDescription {
|
||||
func getNodeDriveAvailabilityErrorsMD() MetricDescription {
|
||||
return MetricDescription{
|
||||
Namespace: nodeMetricNamespace,
|
||||
Subsystem: driveSubsystem,
|
||||
@@ -3464,7 +3467,7 @@ func getLocalStorageMetrics(opts MetricsGroupOpts) *MetricsGroup {
|
||||
})
|
||||
|
||||
metrics = append(metrics, Metric{
|
||||
Description: getNodeDriveAvailablityErrorsMD(),
|
||||
Description: getNodeDriveAvailabilityErrorsMD(),
|
||||
Value: float64(disk.Metrics.TotalErrorsAvailability),
|
||||
VariableLabels: map[string]string{"drive": disk.DrivePath},
|
||||
})
|
||||
@@ -3989,6 +3992,7 @@ func collectMetric(metric Metric, labels []string, values []string, metricName s
|
||||
}
|
||||
}
|
||||
|
||||
//msgp:ignore minioBucketCollector
|
||||
type minioBucketCollector struct {
|
||||
metricsGroups []*MetricsGroup
|
||||
desc *prometheus.Desc
|
||||
@@ -4024,6 +4028,7 @@ func (c *minioBucketCollector) Collect(out chan<- prometheus.Metric) {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
//msgp:ignore minioClusterCollector
|
||||
type minioClusterCollector struct {
|
||||
metricsGroups []*MetricsGroup
|
||||
desc *prometheus.Desc
|
||||
@@ -4083,6 +4088,8 @@ func ReportMetrics(ctx context.Context, metricsGroups []*MetricsGroup) <-chan Me
|
||||
}
|
||||
|
||||
// minioNodeCollector is the Custom Collector
|
||||
//
|
||||
//msgp:ignore minioNodeCollector
|
||||
type minioNodeCollector struct {
|
||||
metricsGroups []*MetricsGroup
|
||||
desc *prometheus.Desc
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *Metric) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 6
|
||||
// string "Description"
|
||||
o = append(o, 0x86, 0xab, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e)
|
||||
o, err = z.Description.MarshalMsg(o)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Description")
|
||||
return
|
||||
}
|
||||
// string "StaticLabels"
|
||||
o = append(o, 0xac, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73)
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z.StaticLabels)))
|
||||
for za0001, za0002 := range z.StaticLabels {
|
||||
o = msgp.AppendString(o, za0001)
|
||||
o = msgp.AppendString(o, za0002)
|
||||
}
|
||||
// string "Value"
|
||||
o = append(o, 0xa5, 0x56, 0x61, 0x6c, 0x75, 0x65)
|
||||
o = msgp.AppendFloat64(o, z.Value)
|
||||
// string "VariableLabels"
|
||||
o = append(o, 0xae, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73)
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z.VariableLabels)))
|
||||
for za0003, za0004 := range z.VariableLabels {
|
||||
o = msgp.AppendString(o, za0003)
|
||||
o = msgp.AppendString(o, za0004)
|
||||
}
|
||||
// string "HistogramBucketLabel"
|
||||
o = append(o, 0xb4, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c)
|
||||
o = msgp.AppendString(o, z.HistogramBucketLabel)
|
||||
// string "Histogram"
|
||||
o = append(o, 0xa9, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d)
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z.Histogram)))
|
||||
for za0005, za0006 := range z.Histogram {
|
||||
o = msgp.AppendString(o, za0005)
|
||||
o = msgp.AppendUint64(o, za0006)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Metric) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Description":
|
||||
bts, err = z.Description.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Description")
|
||||
return
|
||||
}
|
||||
case "StaticLabels":
|
||||
var zb0002 uint32
|
||||
zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StaticLabels")
|
||||
return
|
||||
}
|
||||
if z.StaticLabels == nil {
|
||||
z.StaticLabels = make(map[string]string, zb0002)
|
||||
} else if len(z.StaticLabels) > 0 {
|
||||
for key := range z.StaticLabels {
|
||||
delete(z.StaticLabels, key)
|
||||
}
|
||||
}
|
||||
for zb0002 > 0 {
|
||||
var za0001 string
|
||||
var za0002 string
|
||||
zb0002--
|
||||
za0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StaticLabels")
|
||||
return
|
||||
}
|
||||
za0002, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "StaticLabels", za0001)
|
||||
return
|
||||
}
|
||||
z.StaticLabels[za0001] = za0002
|
||||
}
|
||||
case "Value":
|
||||
z.Value, bts, err = msgp.ReadFloat64Bytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Value")
|
||||
return
|
||||
}
|
||||
case "VariableLabels":
|
||||
var zb0003 uint32
|
||||
zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "VariableLabels")
|
||||
return
|
||||
}
|
||||
if z.VariableLabels == nil {
|
||||
z.VariableLabels = make(map[string]string, zb0003)
|
||||
} else if len(z.VariableLabels) > 0 {
|
||||
for key := range z.VariableLabels {
|
||||
delete(z.VariableLabels, key)
|
||||
}
|
||||
}
|
||||
for zb0003 > 0 {
|
||||
var za0003 string
|
||||
var za0004 string
|
||||
zb0003--
|
||||
za0003, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "VariableLabels")
|
||||
return
|
||||
}
|
||||
za0004, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "VariableLabels", za0003)
|
||||
return
|
||||
}
|
||||
z.VariableLabels[za0003] = za0004
|
||||
}
|
||||
case "HistogramBucketLabel":
|
||||
z.HistogramBucketLabel, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "HistogramBucketLabel")
|
||||
return
|
||||
}
|
||||
case "Histogram":
|
||||
var zb0004 uint32
|
||||
zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Histogram")
|
||||
return
|
||||
}
|
||||
if z.Histogram == nil {
|
||||
z.Histogram = make(map[string]uint64, zb0004)
|
||||
} else if len(z.Histogram) > 0 {
|
||||
for key := range z.Histogram {
|
||||
delete(z.Histogram, key)
|
||||
}
|
||||
}
|
||||
for zb0004 > 0 {
|
||||
var za0005 string
|
||||
var za0006 uint64
|
||||
zb0004--
|
||||
za0005, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Histogram")
|
||||
return
|
||||
}
|
||||
za0006, bts, err = msgp.ReadUint64Bytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Histogram", za0005)
|
||||
return
|
||||
}
|
||||
z.Histogram[za0005] = za0006
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *Metric) Msgsize() (s int) {
|
||||
s = 1 + 12 + z.Description.Msgsize() + 13 + msgp.MapHeaderSize
|
||||
if z.StaticLabels != nil {
|
||||
for za0001, za0002 := range z.StaticLabels {
|
||||
_ = za0002
|
||||
s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002)
|
||||
}
|
||||
}
|
||||
s += 6 + msgp.Float64Size + 15 + msgp.MapHeaderSize
|
||||
if z.VariableLabels != nil {
|
||||
for za0003, za0004 := range z.VariableLabels {
|
||||
_ = za0004
|
||||
s += msgp.StringPrefixSize + len(za0003) + msgp.StringPrefixSize + len(za0004)
|
||||
}
|
||||
}
|
||||
s += 21 + msgp.StringPrefixSize + len(z.HistogramBucketLabel) + 10 + msgp.MapHeaderSize
|
||||
if z.Histogram != nil {
|
||||
for za0005, za0006 := range z.Histogram {
|
||||
_ = za0006
|
||||
s += msgp.StringPrefixSize + len(za0005) + msgp.Uint64Size
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *MetricDescription) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 5
|
||||
// string "Namespace"
|
||||
o = append(o, 0x85, 0xa9, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65)
|
||||
o = msgp.AppendString(o, string(z.Namespace))
|
||||
// string "Subsystem"
|
||||
o = append(o, 0xa9, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d)
|
||||
o = msgp.AppendString(o, string(z.Subsystem))
|
||||
// string "Name"
|
||||
o = append(o, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
||||
o = msgp.AppendString(o, string(z.Name))
|
||||
// string "Help"
|
||||
o = append(o, 0xa4, 0x48, 0x65, 0x6c, 0x70)
|
||||
o = msgp.AppendString(o, z.Help)
|
||||
// string "Type"
|
||||
o = append(o, 0xa4, 0x54, 0x79, 0x70, 0x65)
|
||||
o = msgp.AppendString(o, string(z.Type))
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricDescription) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Namespace":
|
||||
{
|
||||
var zb0002 string
|
||||
zb0002, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Namespace")
|
||||
return
|
||||
}
|
||||
z.Namespace = MetricNamespace(zb0002)
|
||||
}
|
||||
case "Subsystem":
|
||||
{
|
||||
var zb0003 string
|
||||
zb0003, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Subsystem")
|
||||
return
|
||||
}
|
||||
z.Subsystem = MetricSubsystem(zb0003)
|
||||
}
|
||||
case "Name":
|
||||
{
|
||||
var zb0004 string
|
||||
zb0004, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
z.Name = MetricName(zb0004)
|
||||
}
|
||||
case "Help":
|
||||
z.Help, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Help")
|
||||
return
|
||||
}
|
||||
case "Type":
|
||||
{
|
||||
var zb0005 string
|
||||
zb0005, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Type")
|
||||
return
|
||||
}
|
||||
z.Type = MetricType(zb0005)
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *MetricDescription) Msgsize() (s int) {
|
||||
s = 1 + 10 + msgp.StringPrefixSize + len(string(z.Namespace)) + 10 + msgp.StringPrefixSize + len(string(z.Subsystem)) + 5 + msgp.StringPrefixSize + len(string(z.Name)) + 5 + msgp.StringPrefixSize + len(z.Help) + 5 + msgp.StringPrefixSize + len(string(z.Type))
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z MetricName) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendString(o, string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricName) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var zb0001 string
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
(*z) = MetricName(zb0001)
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z MetricName) Msgsize() (s int) {
|
||||
s = msgp.StringPrefixSize + len(string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z MetricNamespace) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendString(o, string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricNamespace) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var zb0001 string
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
(*z) = MetricNamespace(zb0001)
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z MetricNamespace) Msgsize() (s int) {
|
||||
s = msgp.StringPrefixSize + len(string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z MetricSubsystem) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendString(o, string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricSubsystem) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var zb0001 string
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
(*z) = MetricSubsystem(zb0001)
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z MetricSubsystem) Msgsize() (s int) {
|
||||
s = msgp.StringPrefixSize + len(string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z MetricType) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendString(o, string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricType) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var zb0001 string
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
(*z) = MetricType(zb0001)
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z MetricType) Msgsize() (s int) {
|
||||
s = msgp.StringPrefixSize + len(string(z))
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *MetricsGroup) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "cacheInterval"
|
||||
o = append(o, 0x82, 0xad, 0x63, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c)
|
||||
o = msgp.AppendDuration(o, z.cacheInterval)
|
||||
// string "metricsGroupOpts"
|
||||
o = append(o, 0xb0, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4f, 0x70, 0x74, 0x73)
|
||||
o, err = z.metricsGroupOpts.MarshalMsg(o)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "metricsGroupOpts")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricsGroup) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "cacheInterval":
|
||||
z.cacheInterval, bts, err = msgp.ReadDurationBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "cacheInterval")
|
||||
return
|
||||
}
|
||||
case "metricsGroupOpts":
|
||||
bts, err = z.metricsGroupOpts.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "metricsGroupOpts")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *MetricsGroup) Msgsize() (s int) {
|
||||
s = 1 + 14 + msgp.DurationSize + 17 + z.metricsGroupOpts.Msgsize()
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *MetricsGroupOpts) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 12
|
||||
// string "dependGlobalObjectAPI"
|
||||
o = append(o, 0x8c, 0xb5, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x50, 0x49)
|
||||
o = msgp.AppendBool(o, z.dependGlobalObjectAPI)
|
||||
// string "dependGlobalAuthNPlugin"
|
||||
o = append(o, 0xb7, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x4e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e)
|
||||
o = msgp.AppendBool(o, z.dependGlobalAuthNPlugin)
|
||||
// string "dependGlobalSiteReplicationSys"
|
||||
o = append(o, 0xbe, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x73)
|
||||
o = msgp.AppendBool(o, z.dependGlobalSiteReplicationSys)
|
||||
// string "dependGlobalNotificationSys"
|
||||
o = append(o, 0xbb, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x73)
|
||||
o = msgp.AppendBool(o, z.dependGlobalNotificationSys)
|
||||
// string "dependGlobalKMS"
|
||||
o = append(o, 0xaf, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4b, 0x4d, 0x53)
|
||||
o = msgp.AppendBool(o, z.dependGlobalKMS)
|
||||
// string "bucketOnly"
|
||||
o = append(o, 0xaa, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x4f, 0x6e, 0x6c, 0x79)
|
||||
o = msgp.AppendBool(o, z.bucketOnly)
|
||||
// string "dependGlobalLambdaTargetList"
|
||||
o = append(o, 0xbc, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4c, 0x61, 0x6d, 0x62, 0x64, 0x61, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4c, 0x69, 0x73, 0x74)
|
||||
o = msgp.AppendBool(o, z.dependGlobalLambdaTargetList)
|
||||
// string "dependGlobalIAMSys"
|
||||
o = append(o, 0xb2, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x41, 0x4d, 0x53, 0x79, 0x73)
|
||||
o = msgp.AppendBool(o, z.dependGlobalIAMSys)
|
||||
// string "dependGlobalLockServer"
|
||||
o = append(o, 0xb6, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4c, 0x6f, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72)
|
||||
o = msgp.AppendBool(o, z.dependGlobalLockServer)
|
||||
// string "dependGlobalIsDistErasure"
|
||||
o = append(o, 0xb9, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x73, 0x44, 0x69, 0x73, 0x74, 0x45, 0x72, 0x61, 0x73, 0x75, 0x72, 0x65)
|
||||
o = msgp.AppendBool(o, z.dependGlobalIsDistErasure)
|
||||
// string "dependGlobalBackgroundHealState"
|
||||
o = append(o, 0xbf, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x65, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65)
|
||||
o = msgp.AppendBool(o, z.dependGlobalBackgroundHealState)
|
||||
// string "dependBucketTargetSys"
|
||||
o = append(o, 0xb5, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x79, 0x73)
|
||||
o = msgp.AppendBool(o, z.dependBucketTargetSys)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MetricsGroupOpts) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "dependGlobalObjectAPI":
|
||||
z.dependGlobalObjectAPI, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalObjectAPI")
|
||||
return
|
||||
}
|
||||
case "dependGlobalAuthNPlugin":
|
||||
z.dependGlobalAuthNPlugin, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalAuthNPlugin")
|
||||
return
|
||||
}
|
||||
case "dependGlobalSiteReplicationSys":
|
||||
z.dependGlobalSiteReplicationSys, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalSiteReplicationSys")
|
||||
return
|
||||
}
|
||||
case "dependGlobalNotificationSys":
|
||||
z.dependGlobalNotificationSys, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalNotificationSys")
|
||||
return
|
||||
}
|
||||
case "dependGlobalKMS":
|
||||
z.dependGlobalKMS, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalKMS")
|
||||
return
|
||||
}
|
||||
case "bucketOnly":
|
||||
z.bucketOnly, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "bucketOnly")
|
||||
return
|
||||
}
|
||||
case "dependGlobalLambdaTargetList":
|
||||
z.dependGlobalLambdaTargetList, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalLambdaTargetList")
|
||||
return
|
||||
}
|
||||
case "dependGlobalIAMSys":
|
||||
z.dependGlobalIAMSys, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalIAMSys")
|
||||
return
|
||||
}
|
||||
case "dependGlobalLockServer":
|
||||
z.dependGlobalLockServer, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalLockServer")
|
||||
return
|
||||
}
|
||||
case "dependGlobalIsDistErasure":
|
||||
z.dependGlobalIsDistErasure, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalIsDistErasure")
|
||||
return
|
||||
}
|
||||
case "dependGlobalBackgroundHealState":
|
||||
z.dependGlobalBackgroundHealState, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependGlobalBackgroundHealState")
|
||||
return
|
||||
}
|
||||
case "dependBucketTargetSys":
|
||||
z.dependBucketTargetSys, bts, err = msgp.ReadBoolBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "dependBucketTargetSys")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *MetricsGroupOpts) Msgsize() (s int) {
|
||||
s = 1 + 22 + msgp.BoolSize + 24 + msgp.BoolSize + 31 + msgp.BoolSize + 28 + msgp.BoolSize + 16 + msgp.BoolSize + 11 + msgp.BoolSize + 29 + msgp.BoolSize + 19 + msgp.BoolSize + 23 + msgp.BoolSize + 26 + msgp.BoolSize + 32 + msgp.BoolSize + 22 + msgp.BoolSize
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshalMetric(t *testing.T) {
|
||||
v := Metric{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalMetricDescription(t *testing.T) {
|
||||
v := MetricDescription{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMetricDescription(b *testing.B) {
|
||||
v := MetricDescription{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMetricDescription(b *testing.B) {
|
||||
v := MetricDescription{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMetricDescription(b *testing.B) {
|
||||
v := MetricDescription{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalMetricsGroup(t *testing.T) {
|
||||
v := MetricsGroup{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMetricsGroup(b *testing.B) {
|
||||
v := MetricsGroup{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMetricsGroup(b *testing.B) {
|
||||
v := MetricsGroup{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMetricsGroup(b *testing.B) {
|
||||
v := MetricsGroup{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalMetricsGroupOpts(t *testing.T) {
|
||||
v := MetricsGroupOpts{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMetricsGroupOpts(b *testing.B) {
|
||||
v := MetricsGroupOpts{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMetricsGroupOpts(b *testing.B) {
|
||||
v := MetricsGroupOpts{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMetricsGroupOpts(b *testing.B) {
|
||||
v := MetricsGroupOpts{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -680,13 +680,13 @@ func isErrBucketNotFound(err error) bool {
|
||||
return errors.As(err, &bkNotFound)
|
||||
}
|
||||
|
||||
// isErrReadQuorum check if the error type is InsufficentReadQuorum
|
||||
// isErrReadQuorum check if the error type is InsufficientReadQuorum
|
||||
func isErrReadQuorum(err error) bool {
|
||||
var rquorum InsufficientReadQuorum
|
||||
return errors.As(err, &rquorum)
|
||||
}
|
||||
|
||||
// isErrWriteQuorum check if the error type is InsufficentWriteQuorum
|
||||
// isErrWriteQuorum check if the error type is InsufficientWriteQuorum
|
||||
func isErrWriteQuorum(err error) bool {
|
||||
var rquorum InsufficientWriteQuorum
|
||||
return errors.As(err, &rquorum)
|
||||
|
||||
@@ -27,6 +27,11 @@ import (
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
|
||||
// Checks on CopyObject arguments, bucket and object.
|
||||
func checkCopyObjArgs(ctx context.Context, bucket, object string) error {
|
||||
return checkBucketAndObjectNames(ctx, bucket, object)
|
||||
}
|
||||
|
||||
// Checks on GetObject arguments, bucket and object.
|
||||
func checkGetObjArgs(ctx context.Context, bucket, object string) error {
|
||||
return checkBucketAndObjectNames(ctx, bucket, object)
|
||||
@@ -106,42 +111,42 @@ func checkListMultipartArgs(ctx context.Context, bucket, prefix, keyMarker, uplo
|
||||
}
|
||||
|
||||
// Checks for NewMultipartUpload arguments validity, also validates if bucket exists.
|
||||
func checkNewMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
func checkNewMultipartArgs(ctx context.Context, bucket, object string) error {
|
||||
return checkObjectArgs(ctx, bucket, object)
|
||||
}
|
||||
|
||||
func checkMultipartObjectArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
func checkMultipartObjectArgs(ctx context.Context, bucket, object, uploadID string) error {
|
||||
_, err := base64.RawURLEncoding.DecodeString(uploadID)
|
||||
if err != nil {
|
||||
return MalformedUploadID{
|
||||
UploadID: uploadID,
|
||||
}
|
||||
}
|
||||
return checkObjectArgs(ctx, bucket, object, obj)
|
||||
return checkObjectArgs(ctx, bucket, object)
|
||||
}
|
||||
|
||||
// Checks for PutObjectPart arguments validity, also validates if bucket exists.
|
||||
func checkPutObjectPartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
func checkPutObjectPartArgs(ctx context.Context, bucket, object, uploadID string) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID)
|
||||
}
|
||||
|
||||
// Checks for ListParts arguments validity, also validates if bucket exists.
|
||||
func checkListPartsArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
func checkListPartsArgs(ctx context.Context, bucket, object, uploadID string) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID)
|
||||
}
|
||||
|
||||
// Checks for CompleteMultipartUpload arguments validity, also validates if bucket exists.
|
||||
func checkCompleteMultipartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
func checkCompleteMultipartArgs(ctx context.Context, bucket, object, uploadID string) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID)
|
||||
}
|
||||
|
||||
// Checks for AbortMultipartUpload arguments validity, also validates if bucket exists.
|
||||
func checkAbortMultipartArgs(ctx context.Context, bucket, object, uploadID string, obj ObjectLayer) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID, obj)
|
||||
func checkAbortMultipartArgs(ctx context.Context, bucket, object, uploadID string) error {
|
||||
return checkMultipartObjectArgs(ctx, bucket, object, uploadID)
|
||||
}
|
||||
|
||||
// Checks Object arguments validity.
|
||||
func checkObjectArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
|
||||
func checkObjectArgs(ctx context.Context, bucket, object string) error {
|
||||
// Verify if bucket is valid.
|
||||
if !isMinioMetaBucketName(bucket) && s3utils.CheckValidBucketNameStrict(bucket) != nil {
|
||||
return BucketNameInvalid{Bucket: bucket}
|
||||
|
||||
@@ -227,7 +227,7 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
inputSHA256 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
// flag indicating whether the test should pass.
|
||||
shouldPass bool
|
||||
// expected error output.
|
||||
@@ -287,27 +287,27 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH
|
||||
// Test case - 14.
|
||||
// Input with size more than the size of actual data inside the reader.
|
||||
{
|
||||
bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "e2fc714c4727ee9395f324cd2e7f3335", intputDataSize: int64(len("abcd") + 1),
|
||||
bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "e2fc714c4727ee9395f324cd2e7f3335", inputDataSize: int64(len("abcd") + 1),
|
||||
expectedError: hash.BadDigest{ExpectedMD5: "e2fc714c4727ee9395f324cd2e7f3335", CalculatedMD5: "e2fc714c4727ee9395f324cd2e7f331f"},
|
||||
},
|
||||
// Test case - 15.
|
||||
// Input with size less than the size of actual data inside the reader.
|
||||
{
|
||||
bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "900150983cd24fb0d6963f7d28e17f73", intputDataSize: int64(len("abcd") - 1),
|
||||
bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "900150983cd24fb0d6963f7d28e17f73", inputDataSize: int64(len("abcd") - 1),
|
||||
expectedError: ioutil.ErrOverread,
|
||||
},
|
||||
|
||||
// Test case - 16-19.
|
||||
// Validating for success cases.
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "e2fc714c4727ee9395f324cd2e7f331f", inputSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589", intputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 2, inputReaderData: "efgh", inputMd5: "1f7690ebdd9b4caf8fab49ca1757bf27", inputSHA256: "e5e088a0b66163a0a26a5e053d2a4496dc16ab6e0e3dd1adf2d16aa84a078c9d", intputDataSize: int64(len("efgh")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 3, inputReaderData: "ijkl", inputMd5: "09a0877d04abf8759f99adec02baf579", inputSHA256: "005c19658919186b85618c5870463eec8d9b8c1a9d00208a5352891ba5bbe086", intputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 4, inputReaderData: "mnop", inputMd5: "e132e96a5ddad6da8b07bba6f6131fef", inputSHA256: "f1afc31479522d6cff1ed068f93998f05a8cd3b22f5c37d7f307084f62d1d270", intputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 1, inputReaderData: "abcd", inputMd5: "e2fc714c4727ee9395f324cd2e7f331f", inputSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589", inputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 2, inputReaderData: "efgh", inputMd5: "1f7690ebdd9b4caf8fab49ca1757bf27", inputSHA256: "e5e088a0b66163a0a26a5e053d2a4496dc16ab6e0e3dd1adf2d16aa84a078c9d", inputDataSize: int64(len("efgh")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 3, inputReaderData: "ijkl", inputMd5: "09a0877d04abf8759f99adec02baf579", inputSHA256: "005c19658919186b85618c5870463eec8d9b8c1a9d00208a5352891ba5bbe086", inputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
{bucketName: bucket, objName: object, uploadID: uploadID, PartID: 4, inputReaderData: "mnop", inputMd5: "e132e96a5ddad6da8b07bba6f6131fef", inputSHA256: "f1afc31479522d6cff1ed068f93998f05a8cd3b22f5c37d7f307084f62d1d270", inputDataSize: int64(len("abcd")), shouldPass: true},
|
||||
}
|
||||
|
||||
// Validate all the test cases.
|
||||
for i, testCase := range testCases {
|
||||
actualInfo, actualErr := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.intputDataSize, testCase.inputMd5, testCase.inputSHA256), opts)
|
||||
actualInfo, actualErr := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.inputDataSize, testCase.inputMd5, testCase.inputSHA256), opts)
|
||||
// All are test cases above are expected to fail.
|
||||
if actualErr != nil && testCase.shouldPass {
|
||||
t.Errorf("Test %d: %s: Expected to pass, but failed with: <ERROR> %s.", i+1, instanceType, actualErr.Error())
|
||||
@@ -410,7 +410,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
expectedMd5 string
|
||||
}{
|
||||
// Case 1-4.
|
||||
@@ -439,7 +439,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan
|
||||
sha256sum := ""
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for _, testCase := range createPartCases {
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.intputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.inputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
@@ -1263,7 +1263,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
expectedMd5 string
|
||||
}{
|
||||
// Case 1-4.
|
||||
@@ -1277,7 +1277,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks
|
||||
sha256sum := ""
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for _, testCase := range createPartCases {
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.intputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.inputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
@@ -1500,7 +1500,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler)
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
expectedMd5 string
|
||||
}{
|
||||
// Case 1-4.
|
||||
@@ -1514,7 +1514,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler)
|
||||
sha256sum := ""
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for _, testCase := range createPartCases {
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.intputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
_, err := obj.PutObjectPart(context.Background(), testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, mustGetPutObjReader(t, bytes.NewBufferString(testCase.inputReaderData), testCase.inputDataSize, testCase.inputMd5, sha256sum), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
@@ -1744,7 +1744,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
}{
|
||||
// Case 1-4.
|
||||
// Creating sequence of parts for same uploadID.
|
||||
@@ -1761,7 +1761,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
||||
var opts ObjectOptions
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for _, part := range parts {
|
||||
_, err = obj.PutObjectPart(context.Background(), part.bucketName, part.objName, part.uploadID, part.PartID, mustGetPutObjReader(t, bytes.NewBufferString(part.inputReaderData), part.intputDataSize, part.inputMd5, sha256sum), opts)
|
||||
_, err = obj.PutObjectPart(context.Background(), part.bucketName, part.objName, part.uploadID, part.PartID, mustGetPutObjReader(t, bytes.NewBufferString(part.inputReaderData), part.inputDataSize, part.inputMd5, sha256sum), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
}
|
||||
|
||||
@@ -70,12 +70,12 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl
|
||||
invalidMD5Header := md5Header([]byte("meh"))
|
||||
|
||||
testCases := []struct {
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
inputSHA256 string
|
||||
intputDataSize int64
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
inputSHA256 string
|
||||
inputDataSize int64
|
||||
// expected error output.
|
||||
expectedMd5 string
|
||||
expectedError error
|
||||
@@ -106,7 +106,7 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl
|
||||
7: {
|
||||
bucketName: bucket, objName: object, inputData: []byte("abcd"),
|
||||
inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331f"},
|
||||
inputSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031580", intputDataSize: int64(len("abcd")),
|
||||
inputSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031580", inputDataSize: int64(len("abcd")),
|
||||
expectedError: hash.SHA256Mismatch{
|
||||
ExpectedSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031580",
|
||||
CalculatedSHA256: "88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589",
|
||||
@@ -116,76 +116,76 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl
|
||||
// Input with size more than the size of actual data inside the reader.
|
||||
8: {
|
||||
bucketName: bucket, objName: object, inputData: []byte("abcd"),
|
||||
inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331e"}, intputDataSize: int64(len("abcd") + 1),
|
||||
inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331e"}, inputDataSize: int64(len("abcd") + 1),
|
||||
expectedError: hash.BadDigest{ExpectedMD5: "e2fc714c4727ee9395f324cd2e7f331e", CalculatedMD5: "e2fc714c4727ee9395f324cd2e7f331f"},
|
||||
},
|
||||
|
||||
// Input with size less than the size of actual data inside the reader.
|
||||
9: {
|
||||
bucketName: bucket, objName: object, inputData: []byte("abcd"),
|
||||
inputMeta: map[string]string{"etag": "900150983cd24fb0d6963f7d28e17f73"}, intputDataSize: int64(len("abcd") - 1),
|
||||
inputMeta: map[string]string{"etag": "900150983cd24fb0d6963f7d28e17f73"}, inputDataSize: int64(len("abcd") - 1),
|
||||
expectedError: ioutil.ErrOverread,
|
||||
},
|
||||
|
||||
// Validating for success cases.
|
||||
10: {bucketName: bucket, objName: object, inputData: []byte("abcd"), inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331f"}, intputDataSize: int64(len("abcd"))},
|
||||
11: {bucketName: bucket, objName: object, inputData: []byte("efgh"), inputMeta: map[string]string{"etag": "1f7690ebdd9b4caf8fab49ca1757bf27"}, intputDataSize: int64(len("efgh"))},
|
||||
12: {bucketName: bucket, objName: object, inputData: []byte("ijkl"), inputMeta: map[string]string{"etag": "09a0877d04abf8759f99adec02baf579"}, intputDataSize: int64(len("ijkl"))},
|
||||
13: {bucketName: bucket, objName: object, inputData: []byte("mnop"), inputMeta: map[string]string{"etag": "e132e96a5ddad6da8b07bba6f6131fef"}, intputDataSize: int64(len("mnop"))},
|
||||
10: {bucketName: bucket, objName: object, inputData: []byte("abcd"), inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331f"}, inputDataSize: int64(len("abcd"))},
|
||||
11: {bucketName: bucket, objName: object, inputData: []byte("efgh"), inputMeta: map[string]string{"etag": "1f7690ebdd9b4caf8fab49ca1757bf27"}, inputDataSize: int64(len("efgh"))},
|
||||
12: {bucketName: bucket, objName: object, inputData: []byte("ijkl"), inputMeta: map[string]string{"etag": "09a0877d04abf8759f99adec02baf579"}, inputDataSize: int64(len("ijkl"))},
|
||||
13: {bucketName: bucket, objName: object, inputData: []byte("mnop"), inputMeta: map[string]string{"etag": "e132e96a5ddad6da8b07bba6f6131fef"}, inputDataSize: int64(len("mnop"))},
|
||||
|
||||
// With no metadata
|
||||
14: {bucketName: bucket, objName: object, inputData: data, intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
15: {bucketName: bucket, objName: object, inputData: nilBytes, intputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
16: {bucketName: bucket, objName: object, inputData: fiveMBBytes, intputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
14: {bucketName: bucket, objName: object, inputData: data, inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
15: {bucketName: bucket, objName: object, inputData: nilBytes, inputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
16: {bucketName: bucket, objName: object, inputData: fiveMBBytes, inputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
|
||||
// With arbitrary metadata
|
||||
17: {bucketName: bucket, objName: object, inputData: data, inputMeta: map[string]string{"answer": "42"}, intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
18: {bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: map[string]string{"answer": "42"}, intputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
19: {bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: map[string]string{"answer": "42"}, intputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
17: {bucketName: bucket, objName: object, inputData: data, inputMeta: map[string]string{"answer": "42"}, inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
18: {bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: map[string]string{"answer": "42"}, inputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
19: {bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: map[string]string{"answer": "42"}, inputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
|
||||
// With valid md5sum and sha256.
|
||||
20: {bucketName: bucket, objName: object, inputData: data, inputMeta: md5Header(data), inputSHA256: getSHA256Hash(data), intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
21: {bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: md5Header(nilBytes), inputSHA256: getSHA256Hash(nilBytes), intputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
22: {bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: md5Header(fiveMBBytes), inputSHA256: getSHA256Hash(fiveMBBytes), intputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
20: {bucketName: bucket, objName: object, inputData: data, inputMeta: md5Header(data), inputSHA256: getSHA256Hash(data), inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
21: {bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: md5Header(nilBytes), inputSHA256: getSHA256Hash(nilBytes), inputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes)},
|
||||
22: {bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: md5Header(fiveMBBytes), inputSHA256: getSHA256Hash(fiveMBBytes), inputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes)},
|
||||
|
||||
// data with invalid md5sum in header
|
||||
23: {
|
||||
bucketName: bucket, objName: object, inputData: data, inputMeta: invalidMD5Header, intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data),
|
||||
bucketName: bucket, objName: object, inputData: data, inputMeta: invalidMD5Header, inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data),
|
||||
expectedError: hash.BadDigest{ExpectedMD5: invalidMD5, CalculatedMD5: getMD5Hash(data)},
|
||||
},
|
||||
24: {
|
||||
bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: invalidMD5Header, intputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes),
|
||||
bucketName: bucket, objName: object, inputData: nilBytes, inputMeta: invalidMD5Header, inputDataSize: int64(len(nilBytes)), expectedMd5: getMD5Hash(nilBytes),
|
||||
expectedError: hash.BadDigest{ExpectedMD5: invalidMD5, CalculatedMD5: getMD5Hash(nilBytes)},
|
||||
},
|
||||
25: {
|
||||
bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: invalidMD5Header, intputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes),
|
||||
bucketName: bucket, objName: object, inputData: fiveMBBytes, inputMeta: invalidMD5Header, inputDataSize: int64(len(fiveMBBytes)), expectedMd5: getMD5Hash(fiveMBBytes),
|
||||
expectedError: hash.BadDigest{ExpectedMD5: invalidMD5, CalculatedMD5: getMD5Hash(fiveMBBytes)},
|
||||
},
|
||||
|
||||
// data with size different from the actual number of bytes available in the reader
|
||||
26: {bucketName: bucket, objName: object, inputData: data, intputDataSize: int64(len(data) - 1), expectedMd5: getMD5Hash(data[:len(data)-1]), expectedError: ioutil.ErrOverread},
|
||||
27: {bucketName: bucket, objName: object, inputData: nilBytes, intputDataSize: int64(len(nilBytes) + 1), expectedMd5: getMD5Hash(nilBytes), expectedError: IncompleteBody{Bucket: bucket, Object: object}},
|
||||
26: {bucketName: bucket, objName: object, inputData: data, inputDataSize: int64(len(data) - 1), expectedMd5: getMD5Hash(data[:len(data)-1]), expectedError: ioutil.ErrOverread},
|
||||
27: {bucketName: bucket, objName: object, inputData: nilBytes, inputDataSize: int64(len(nilBytes) + 1), expectedMd5: getMD5Hash(nilBytes), expectedError: IncompleteBody{Bucket: bucket, Object: object}},
|
||||
28: {bucketName: bucket, objName: object, inputData: fiveMBBytes, expectedMd5: getMD5Hash(fiveMBBytes), expectedError: ioutil.ErrOverread},
|
||||
|
||||
// valid data with X-Amz-Meta- meta
|
||||
29: {bucketName: bucket, objName: object, inputData: data, inputMeta: map[string]string{"X-Amz-Meta-AppID": "a42"}, intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
29: {bucketName: bucket, objName: object, inputData: data, inputMeta: map[string]string{"X-Amz-Meta-AppID": "a42"}, inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
|
||||
// Put an empty object with a trailing slash
|
||||
30: {bucketName: bucket, objName: "emptydir/", inputData: []byte{}, expectedMd5: getMD5Hash([]byte{})},
|
||||
// Put an object inside the empty directory
|
||||
31: {bucketName: bucket, objName: "emptydir/" + object, inputData: data, intputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
31: {bucketName: bucket, objName: "emptydir/" + object, inputData: data, inputDataSize: int64(len(data)), expectedMd5: getMD5Hash(data)},
|
||||
// Put the empty object with a trailing slash again (refer to Test case 30), this needs to succeed
|
||||
32: {bucketName: bucket, objName: "emptydir/", inputData: []byte{}, expectedMd5: getMD5Hash([]byte{})},
|
||||
|
||||
// With invalid crc32.
|
||||
33: {
|
||||
bucketName: bucket, objName: object, inputData: []byte("abcd"),
|
||||
inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331f", "x-amz-checksum-crc32": "abcd"},
|
||||
intputDataSize: int64(len("abcd")),
|
||||
inputMeta: map[string]string{"etag": "e2fc714c4727ee9395f324cd2e7f331f", "x-amz-checksum-crc32": "abcd"},
|
||||
inputDataSize: int64(len("abcd")),
|
||||
},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
in := mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.intputDataSize, testCase.inputMeta["etag"], testCase.inputSHA256)
|
||||
in := mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.inputDataSize, testCase.inputMeta["etag"], testCase.inputSHA256)
|
||||
objInfo, actualErr := obj.PutObject(context.Background(), testCase.bucketName, testCase.objName, in, ObjectOptions{UserDefined: testCase.inputMeta})
|
||||
if actualErr != nil && testCase.expectedError == nil {
|
||||
t.Errorf("Test %d: %s: Expected to pass, but failed with: error %s.", i, instanceType, actualErr.Error())
|
||||
@@ -243,11 +243,11 @@ func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, di
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
intputDataSize int64
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
inputDataSize int64
|
||||
// flag indicating whether the test should pass.
|
||||
shouldPass bool
|
||||
// expected error output.
|
||||
@@ -263,7 +263,7 @@ func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, di
|
||||
|
||||
sha256sum := ""
|
||||
for i, testCase := range testCases {
|
||||
objInfo, actualErr := obj.PutObject(context.Background(), testCase.bucketName, testCase.objName, mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.intputDataSize, testCase.inputMeta["etag"], sha256sum), ObjectOptions{UserDefined: testCase.inputMeta})
|
||||
objInfo, actualErr := obj.PutObject(context.Background(), testCase.bucketName, testCase.objName, mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.inputDataSize, testCase.inputMeta["etag"], sha256sum), ObjectOptions{UserDefined: testCase.inputMeta})
|
||||
if actualErr != nil && testCase.shouldPass {
|
||||
t.Errorf("Test %d: %s: Expected to pass, but failed with: <ERROR> %s.", i+1, instanceType, actualErr.Error())
|
||||
}
|
||||
@@ -291,11 +291,11 @@ func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, di
|
||||
|
||||
// Validate the last test.
|
||||
testCase := struct {
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
intputDataSize int64
|
||||
bucketName string
|
||||
objName string
|
||||
inputData []byte
|
||||
inputMeta map[string]string
|
||||
inputDataSize int64
|
||||
// flag indicating whether the test should pass.
|
||||
shouldPass bool
|
||||
// expected error output.
|
||||
@@ -312,7 +312,7 @@ func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, di
|
||||
errErasureWriteQuorum,
|
||||
}
|
||||
|
||||
_, actualErr := obj.PutObject(context.Background(), testCase.bucketName, testCase.objName, mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.intputDataSize, testCase.inputMeta["etag"], sha256sum), ObjectOptions{UserDefined: testCase.inputMeta})
|
||||
_, actualErr := obj.PutObject(context.Background(), testCase.bucketName, testCase.objName, mustGetPutObjReader(t, bytes.NewReader(testCase.inputData), testCase.inputDataSize, testCase.inputMeta["etag"], sha256sum), ObjectOptions{UserDefined: testCase.inputMeta})
|
||||
if actualErr != nil && testCase.shouldPass {
|
||||
t.Errorf("Test %d: %s: Expected to pass, but failed with: <ERROR> %s.", len(testCases)+1, instanceType, actualErr.Error())
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ func TestIsValidBucketName(t *testing.T) {
|
||||
{"192.168.1.1", false},
|
||||
{"$this-is-not-valid-too", false},
|
||||
{"contains-$-dollar", false},
|
||||
{"contains-^-carret", false},
|
||||
{"contains-^-caret", false},
|
||||
{"contains-$-dollar", false},
|
||||
{"contains-$-dollar", false},
|
||||
{"......", false},
|
||||
@@ -195,7 +195,7 @@ func TestIsValidObjectName(t *testing.T) {
|
||||
{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", true},
|
||||
{"SHØRT", true},
|
||||
{"f*le", true},
|
||||
{"contains-^-carret", true},
|
||||
{"contains-^-caret", true},
|
||||
{"contains-|-pipe", true},
|
||||
{"contains-`-tick", true},
|
||||
{"..test", true},
|
||||
|
||||
+52
-43
@@ -1302,7 +1302,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
||||
|
||||
copySourceHeader := map[string]string{"X-Amz-Copy-Source": "somewhere"}
|
||||
invalidMD5Header := map[string]string{"Content-Md5": "42"}
|
||||
inalidStorageClassHeader := map[string]string{xhttp.AmzStorageClass: "INVALID"}
|
||||
invalidStorageClassHeader := map[string]string{xhttp.AmzStorageClass: "INVALID"}
|
||||
|
||||
addCustomHeaders := func(req *http.Request, customHeaders map[string]string) {
|
||||
for k, value := range customHeaders {
|
||||
@@ -1350,7 +1350,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
||||
objectName: objectName,
|
||||
data: bytesData,
|
||||
dataLen: len(bytesData),
|
||||
accessKey: "Wrong-AcessID",
|
||||
accessKey: "Wrong-AccessID",
|
||||
secretKey: credentials.SecretKey,
|
||||
|
||||
expectedRespStatus: http.StatusForbidden,
|
||||
@@ -1408,7 +1408,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
||||
6: {
|
||||
bucketName: bucketName,
|
||||
objectName: objectName,
|
||||
headers: inalidStorageClassHeader,
|
||||
headers: invalidStorageClassHeader,
|
||||
data: bytesData,
|
||||
dataLen: len(bytesData),
|
||||
accessKey: credentials.AccessKey,
|
||||
@@ -2225,10 +2225,19 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// Test case - 3.
|
||||
// Test case with new object name is same as object to be copied.
|
||||
// Test case with invalid source object.
|
||||
3: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "dir//newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
accessKey: credentials.AccessKey,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
// Test case - 4.
|
||||
// Test case with new object name is same as object to be copied.
|
||||
4: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2239,10 +2248,10 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// Test case - 4.
|
||||
// Test case - 5.
|
||||
// Test case with new object name is same as object to be copied.
|
||||
// But source copy is without leading slash
|
||||
4: {
|
||||
5: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceSame: true,
|
||||
@@ -2253,10 +2262,10 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// Test case - 5.
|
||||
// Test case - 6.
|
||||
// Test case with new object name is same as object to be copied
|
||||
// but metadata is updated.
|
||||
5: {
|
||||
6: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2270,9 +2279,9 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
|
||||
// Test case - 6.
|
||||
// Test case - 7.
|
||||
// Test case with invalid metadata-directive.
|
||||
6: {
|
||||
7: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2286,10 +2295,10 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// Test case - 7.
|
||||
// Test case - 8.
|
||||
// Test case with new object name is same as object to be copied
|
||||
// fail with BadRequest.
|
||||
7: {
|
||||
8: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2304,11 +2313,11 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusBadRequest,
|
||||
},
|
||||
|
||||
// Test case - 8.
|
||||
// Test case - 9.
|
||||
// Test case with non-existent source file.
|
||||
// Case for the purpose of failing `api.ObjectAPI.GetObjectInfo`.
|
||||
// Expecting the response status code to http.StatusNotFound (404).
|
||||
8: {
|
||||
9: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + "non-existent-object"),
|
||||
@@ -2318,11 +2327,11 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusNotFound,
|
||||
},
|
||||
|
||||
// Test case - 9.
|
||||
// Test case - 10.
|
||||
// Test case with non-existent source file.
|
||||
// Case for the purpose of failing `api.ObjectAPI.PutObject`.
|
||||
// Expecting the response status code to http.StatusNotFound (404).
|
||||
9: {
|
||||
10: {
|
||||
bucketName: "non-existent-destination-bucket",
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2332,9 +2341,9 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
expectedRespStatus: http.StatusNotFound,
|
||||
},
|
||||
|
||||
// Test case - 10.
|
||||
// Test case - 11.
|
||||
// Case with invalid AccessKey.
|
||||
10: {
|
||||
11: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: objectName,
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2343,8 +2352,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
|
||||
expectedRespStatus: http.StatusForbidden,
|
||||
},
|
||||
// Test case - 11, copy metadata from newObject1 with satisfying modified header.
|
||||
11: {
|
||||
// Test case - 12, copy metadata from newObject1 with satisfying modified header.
|
||||
12: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2353,8 +2362,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 12, copy metadata from newObject1 with unsatisfying modified header.
|
||||
12: {
|
||||
// Test case - 13, copy metadata from newObject1 with unsatisfying modified header.
|
||||
13: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2363,8 +2372,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusPreconditionFailed,
|
||||
},
|
||||
// Test case - 13, copy metadata from newObject1 with wrong modified header format
|
||||
13: {
|
||||
// Test case - 14, copy metadata from newObject1 with wrong modified header format
|
||||
14: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2373,8 +2382,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 14, copy metadata from newObject1 with satisfying unmodified header.
|
||||
14: {
|
||||
// Test case - 15, copy metadata from newObject1 with satisfying unmodified header.
|
||||
15: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2383,8 +2392,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 15, copy metadata from newObject1 with unsatisfying unmodified header.
|
||||
15: {
|
||||
// Test case - 16, copy metadata from newObject1 with unsatisfying unmodified header.
|
||||
16: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2393,8 +2402,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusPreconditionFailed,
|
||||
},
|
||||
// Test case - 16, copy metadata from newObject1 with incorrect unmodified header format.
|
||||
16: {
|
||||
// Test case - 17, copy metadata from newObject1 with incorrect unmodified header format.
|
||||
17: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName),
|
||||
@@ -2403,8 +2412,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 17, copy metadata from newObject1 with null versionId
|
||||
17: {
|
||||
// Test case - 18, copy metadata from newObject1 with null versionId
|
||||
18: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=null",
|
||||
@@ -2412,8 +2421,8 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
secretKey: credentials.SecretKey,
|
||||
expectedRespStatus: http.StatusOK,
|
||||
},
|
||||
// Test case - 18, copy metadata from newObject1 with non null versionId
|
||||
18: {
|
||||
// Test case - 19, copy metadata from newObject1 with non null versionId
|
||||
19: {
|
||||
bucketName: bucketName,
|
||||
newObjectName: "newObject1",
|
||||
copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=17",
|
||||
@@ -2574,7 +2583,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string,
|
||||
}
|
||||
|
||||
// Wrapper for calling NewMultipartUpload tests for both Erasure multiple disks and single node setup.
|
||||
// First register the HTTP handler for NewMutlipartUpload, then a HTTP request for NewMultipart upload is made.
|
||||
// First register the HTTP handler for NewMultipartUpload, then a HTTP request for NewMultipart upload is made.
|
||||
// The UploadID from the response body is parsed and its existence is asserted with an attempt to ListParts using it.
|
||||
func TestAPINewMultipartHandler(t *testing.T) {
|
||||
defer DetectTestLeak(t)()
|
||||
@@ -2614,7 +2623,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string
|
||||
t.Fatalf("Invalid UploadID: <ERROR> %s", err)
|
||||
}
|
||||
|
||||
// Testing the response for Invalid AcccessID.
|
||||
// Testing the response for Invalid AccessID.
|
||||
// Forcing the signature check to fail.
|
||||
rec = httptest.NewRecorder()
|
||||
// construct HTTP request for NewMultipart upload.
|
||||
@@ -2664,7 +2673,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string
|
||||
t.Fatalf("Invalid UploadID: <ERROR> %s", err)
|
||||
}
|
||||
|
||||
// Testing the response for invalid AcccessID.
|
||||
// Testing the response for invalid AccessID.
|
||||
// Forcing the V2 signature check to fail.
|
||||
recV2 = httptest.NewRecorder()
|
||||
// construct HTTP request for NewMultipartUpload endpoint.
|
||||
@@ -2819,7 +2828,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
}{
|
||||
// Case 1-4.
|
||||
// Creating sequence of parts for same uploadID.
|
||||
@@ -2839,7 +2848,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for _, part := range parts {
|
||||
_, err = obj.PutObjectPart(context.Background(), part.bucketName, part.objName, part.uploadID, part.PartID,
|
||||
mustGetPutObjReader(t, strings.NewReader(part.inputReaderData), part.intputDataSize, part.inputMd5, ""), opts)
|
||||
mustGetPutObjReader(t, strings.NewReader(part.inputReaderData), part.inputDataSize, part.inputMd5, ""), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
}
|
||||
@@ -3187,7 +3196,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri
|
||||
PartID int
|
||||
inputReaderData string
|
||||
inputMd5 string
|
||||
intputDataSize int64
|
||||
inputDataSize int64
|
||||
}{
|
||||
// Case 1-4.
|
||||
// Creating sequence of parts for same uploadID.
|
||||
@@ -3207,7 +3216,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri
|
||||
// Iterating over createPartCases to generate multipart chunks.
|
||||
for _, part := range parts {
|
||||
_, err = obj.PutObjectPart(context.Background(), part.bucketName, part.objName, part.uploadID, part.PartID,
|
||||
mustGetPutObjReader(t, strings.NewReader(part.inputReaderData), part.intputDataSize, part.inputMd5, ""), opts)
|
||||
mustGetPutObjReader(t, strings.NewReader(part.inputReaderData), part.inputDataSize, part.inputMd5, ""), opts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
}
|
||||
@@ -3233,7 +3242,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri
|
||||
expectedRespStatus: http.StatusNoContent,
|
||||
},
|
||||
// Test case - 2.
|
||||
// Abort non-existng upload ID.
|
||||
// Abort non-existing upload ID.
|
||||
{
|
||||
bucket: bucketName,
|
||||
object: objectName,
|
||||
|
||||
@@ -729,13 +729,20 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
||||
sha256hex = ""
|
||||
}
|
||||
|
||||
var forceMD5 []byte
|
||||
// Optimization: If SSE-KMS and SSE-C did not request Content-Md5. Use uuid as etag. Optionally enable this also
|
||||
// for server that is started with `--no-compat`.
|
||||
if !etag.ContentMD5Requested(r.Header) && (crypto.S3KMS.IsEncrypted(mi.UserDefined) || crypto.SSEC.IsRequested(r.Header) || !globalServerCtxt.StrictS3Compat) {
|
||||
forceMD5 = mustGetUUIDBytes()
|
||||
}
|
||||
|
||||
hashReader, err := hash.NewReaderWithOpts(ctx, reader, hash.Options{
|
||||
Size: size,
|
||||
MD5Hex: md5hex,
|
||||
SHA256Hex: sha256hex,
|
||||
ActualSize: actualSize,
|
||||
DisableMD5: false,
|
||||
ForceMD5: nil,
|
||||
ForceMD5: forceMD5,
|
||||
})
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||
|
||||
@@ -473,13 +473,13 @@ func testObjectOverwriteWorks(obj ObjectLayer, instanceType string, t TestErrHan
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling testNonExistantBucketOperations for both Erasure and FS.
|
||||
func TestNonExistantBucketOperations(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testNonExistantBucketOperations)
|
||||
// Wrapper for calling testNonExistentBucketOperations for both Erasure and FS.
|
||||
func TestNonExistentBucketOperations(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testNonExistentBucketOperations)
|
||||
}
|
||||
|
||||
// Tests validate that bucket operation on non-existent bucket fails.
|
||||
func testNonExistantBucketOperations(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
func testNonExistentBucketOperations(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
var opts ObjectOptions
|
||||
_, err := obj.PutObject(context.Background(), "bucket1", "object", mustGetPutObjReader(t, bytes.NewBufferString("one"), int64(len("one")), "", ""), opts)
|
||||
if err == nil {
|
||||
@@ -529,7 +529,7 @@ func enableCompression(t *testing.T, encrypt bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func enableEncrytion(t *testing.T) {
|
||||
func enableEncryption(t *testing.T) {
|
||||
// Exec with default settings...
|
||||
globalCompressConfigMu.Lock()
|
||||
globalCompressConfig.Enabled = false
|
||||
@@ -572,7 +572,7 @@ func execExtended(t *testing.T, fn func(t *testing.T)) {
|
||||
|
||||
t.Run("encrypted", func(t *testing.T) {
|
||||
resetCompressEncryption()
|
||||
enableEncrytion(t)
|
||||
enableEncryption(t)
|
||||
fn(t)
|
||||
})
|
||||
|
||||
@@ -760,13 +760,13 @@ func testListBucketsOrder(obj ObjectLayer, instanceType string, t TestErrHandler
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling testListObjectsTestsForNonExistantBucket for both Erasure and FS.
|
||||
func TestListObjectsTestsForNonExistantBucket(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testListObjectsTestsForNonExistantBucket)
|
||||
// Wrapper for calling testListObjectsTestsForNonExistentBucket for both Erasure and FS.
|
||||
func TestListObjectsTestsForNonExistentBucket(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testListObjectsTestsForNonExistentBucket)
|
||||
}
|
||||
|
||||
// Tests validate that ListObjects operation on a non-existent bucket fails as expected.
|
||||
func testListObjectsTestsForNonExistantBucket(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
func testListObjectsTestsForNonExistentBucket(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
result, err := obj.ListObjects(context.Background(), "bucket", "", "", "", 1000)
|
||||
if err == nil {
|
||||
t.Fatalf("%s: Expected error but found nil.", instanceType)
|
||||
@@ -782,13 +782,13 @@ func testListObjectsTestsForNonExistantBucket(obj ObjectLayer, instanceType stri
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling testNonExistantObjectInBucket for both Erasure and FS.
|
||||
func TestNonExistantObjectInBucket(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testNonExistantObjectInBucket)
|
||||
// Wrapper for calling testNonExistentObjectInBucket for both Erasure and FS.
|
||||
func TestNonExistentObjectInBucket(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testNonExistentObjectInBucket)
|
||||
}
|
||||
|
||||
// Tests validate that GetObject fails on a non-existent bucket as expected.
|
||||
func testNonExistantObjectInBucket(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
func testNonExistentObjectInBucket(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
err := obj.MakeBucket(context.Background(), "bucket", MakeBucketOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("%s: <ERROR> %s", instanceType, err)
|
||||
|
||||
+127
-333
@@ -18,7 +18,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"encoding/hex"
|
||||
@@ -28,7 +27,6 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -38,9 +36,7 @@ import (
|
||||
xhttp "github.com/minio/minio/internal/http"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
"github.com/minio/minio/internal/rest"
|
||||
"github.com/minio/pkg/v2/logger/message/log"
|
||||
xnet "github.com/minio/pkg/v2/net"
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// client to talk to peer Nodes.
|
||||
@@ -154,111 +150,65 @@ func (client *peerRESTClient) Close() error {
|
||||
|
||||
// GetLocks - fetch older locks for a remote node.
|
||||
func (client *peerRESTClient) GetLocks() (lockMap map[string][]lockRequesterInfo, err error) {
|
||||
respBody, err := client.call(peerRESTMethodGetLocks, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
resp, err := getLocksRPC.Call(context.Background(), client.gridConn(), grid.NewMSS())
|
||||
if err != nil || resp == nil {
|
||||
return nil, err
|
||||
}
|
||||
lockMap = map[string][]lockRequesterInfo{}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&lockMap)
|
||||
return lockMap, err
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
// LocalStorageInfo - fetch server information for a remote node.
|
||||
func (client *peerRESTClient) LocalStorageInfo(metrics bool) (info StorageInfo, err error) {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTMetrics, strconv.FormatBool(metrics))
|
||||
respBody, err := client.call(peerRESTMethodLocalStorageInfo, values, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := localStorageInfoRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTMetrics: strconv.FormatBool(metrics),
|
||||
}))
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// ServerInfo - fetch server information for a remote node.
|
||||
func (client *peerRESTClient) ServerInfo(metrics bool) (info madmin.ServerProperties, err error) {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTMetrics, strconv.FormatBool(metrics))
|
||||
|
||||
respBody, err := client.call(peerRESTMethodServerInfo, values, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := serverInfoRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{peerRESTMetrics: strconv.FormatBool(metrics)}))
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetCPUs - fetch CPU information for a remote node.
|
||||
func (client *peerRESTClient) GetCPUs(ctx context.Context) (info madmin.CPUs, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodCPUInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getCPUsHandler.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetNetInfo - fetch network information for a remote node.
|
||||
func (client *peerRESTClient) GetNetInfo(ctx context.Context) (info madmin.NetInfo, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodNetHwInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getNetInfoRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetPartitions - fetch disk partition information for a remote node.
|
||||
func (client *peerRESTClient) GetPartitions(ctx context.Context) (info madmin.Partitions, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodDiskHwInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getPartitionsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetOSInfo - fetch OS information for a remote node.
|
||||
func (client *peerRESTClient) GetOSInfo(ctx context.Context) (info madmin.OSInfo, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodOsInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getOSInfoRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetSELinuxInfo - fetch SELinux information for a remote node.
|
||||
func (client *peerRESTClient) GetSELinuxInfo(ctx context.Context) (info madmin.SysServices, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodSysServices, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getSysServicesRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetSysConfig - fetch sys config for a remote node.
|
||||
func (client *peerRESTClient) GetSysConfig(ctx context.Context) (info madmin.SysConfig, err error) {
|
||||
sent := time.Now()
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodSysConfig, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
roundtrip := int32(time.Since(sent).Milliseconds())
|
||||
defer xhttp.DrainBody(respBody)
|
||||
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
resp, err := getSysConfigRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
info = resp.ValueOrZero()
|
||||
if ti, ok := info.Config["time-info"].(madmin.TimeInfo); ok {
|
||||
ti.RoundtripDuration = roundtrip
|
||||
rt := int32(time.Since(sent).Milliseconds())
|
||||
ti.RoundtripDuration = rt
|
||||
info.Config["time-info"] = ti
|
||||
}
|
||||
return info, err
|
||||
@@ -266,24 +216,14 @@ func (client *peerRESTClient) GetSysConfig(ctx context.Context) (info madmin.Sys
|
||||
|
||||
// GetSysErrors - fetch sys errors for a remote node.
|
||||
func (client *peerRESTClient) GetSysErrors(ctx context.Context) (info madmin.SysErrors, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodSysErrors, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getSysErrorsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetMemInfo - fetch memory information for a remote node.
|
||||
func (client *peerRESTClient) GetMemInfo(ctx context.Context) (info madmin.MemInfo, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodMemInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getMemInfoRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetMetrics - fetch metrics from a remote node.
|
||||
@@ -298,52 +238,14 @@ func (client *peerRESTClient) GetMetrics(ctx context.Context, t madmin.MetricTyp
|
||||
}
|
||||
values.Set(peerRESTJobID, opts.jobID)
|
||||
values.Set(peerRESTDepID, opts.depID)
|
||||
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodMetrics, values, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) GetResourceMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodResourceMetrics, nil, nil, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec := gob.NewDecoder(respBody)
|
||||
ch := make(chan Metric)
|
||||
go func(ch chan<- Metric) {
|
||||
defer func() {
|
||||
xhttp.DrainBody(respBody)
|
||||
close(ch)
|
||||
}()
|
||||
for {
|
||||
var metric Metric
|
||||
if err := dec.Decode(&metric); err != nil {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ch <- metric:
|
||||
}
|
||||
}
|
||||
}(ch)
|
||||
return ch, nil
|
||||
v, err := getMetricsRPC.Call(ctx, client.gridConn(), grid.NewURLValuesWith(values))
|
||||
return v.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetProcInfo - fetch MinIO process information for a remote node.
|
||||
func (client *peerRESTClient) GetProcInfo(ctx context.Context) (info madmin.ProcInfo, err error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodProcInfo, nil, nil, -1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&info)
|
||||
return info, err
|
||||
resp, err := getProcInfoRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// StartProfiling - Issues profiling command on the peer node.
|
||||
@@ -371,51 +273,36 @@ func (client *peerRESTClient) DownloadProfileData() (data map[string][]byte, err
|
||||
|
||||
// GetBucketStats - load bucket statistics
|
||||
func (client *peerRESTClient) GetBucketStats(bucket string) (BucketStats, error) {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTBucket, bucket)
|
||||
respBody, err := client.call(peerRESTMethodGetBucketStats, values, nil, -1)
|
||||
if err != nil {
|
||||
resp, err := getBucketStatsRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTBucket: bucket,
|
||||
}))
|
||||
if err != nil || resp == nil {
|
||||
return BucketStats{}, err
|
||||
}
|
||||
|
||||
var bs BucketStats
|
||||
defer xhttp.DrainBody(respBody)
|
||||
return bs, msgp.Decode(respBody, &bs)
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
// GetSRMetrics- loads site replication metrics, optionally for a specific bucket
|
||||
// GetSRMetrics loads site replication metrics, optionally for a specific bucket
|
||||
func (client *peerRESTClient) GetSRMetrics() (SRMetricsSummary, error) {
|
||||
values := make(url.Values)
|
||||
respBody, err := client.call(peerRESTMethodGetSRMetrics, values, nil, -1)
|
||||
if err != nil {
|
||||
resp, err := getSRMetricsRPC.Call(context.Background(), client.gridConn(), grid.NewMSS())
|
||||
if err != nil || resp == nil {
|
||||
return SRMetricsSummary{}, err
|
||||
}
|
||||
|
||||
var sm SRMetricsSummary
|
||||
defer xhttp.DrainBody(respBody)
|
||||
return sm, msgp.Decode(respBody, &sm)
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
// GetAllBucketStats - load replication stats for all buckets
|
||||
func (client *peerRESTClient) GetAllBucketStats() (BucketStatsMap, error) {
|
||||
values := make(url.Values)
|
||||
respBody, err := client.call(peerRESTMethodGetAllBucketStats, values, nil, -1)
|
||||
if err != nil {
|
||||
resp, err := getAllBucketStatsRPC.Call(context.Background(), client.gridConn(), grid.NewMSS())
|
||||
if err != nil || resp == nil {
|
||||
return BucketStatsMap{}, err
|
||||
}
|
||||
|
||||
bsMap := BucketStatsMap{}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
return bsMap, msgp.Decode(respBody, &bsMap)
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
// LoadBucketMetadata - load bucket metadata
|
||||
func (client *peerRESTClient) LoadBucketMetadata(bucket string) error {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := loadBucketMetadataHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err := loadBucketMetadataRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTBucket: bucket,
|
||||
}))
|
||||
return err
|
||||
@@ -423,11 +310,7 @@ func (client *peerRESTClient) LoadBucketMetadata(bucket string) error {
|
||||
|
||||
// DeleteBucketMetadata - Delete bucket metadata
|
||||
func (client *peerRESTClient) DeleteBucketMetadata(bucket string) error {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := deleteBucketMetadataHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err := deleteBucketMetadataRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTBucket: bucket,
|
||||
}))
|
||||
return err
|
||||
@@ -435,12 +318,7 @@ func (client *peerRESTClient) DeleteBucketMetadata(bucket string) error {
|
||||
|
||||
// DeletePolicy - delete a specific canned policy.
|
||||
func (client *peerRESTClient) DeletePolicy(policyName string) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = deletePolicyHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = deletePolicyRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTPolicy: policyName,
|
||||
}))
|
||||
return err
|
||||
@@ -448,12 +326,7 @@ func (client *peerRESTClient) DeletePolicy(policyName string) (err error) {
|
||||
|
||||
// LoadPolicy - reload a specific canned policy.
|
||||
func (client *peerRESTClient) LoadPolicy(policyName string) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = loadPolicyHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = loadPolicyRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTPolicy: policyName,
|
||||
}))
|
||||
return err
|
||||
@@ -461,12 +334,7 @@ func (client *peerRESTClient) LoadPolicy(policyName string) (err error) {
|
||||
|
||||
// LoadPolicyMapping - reload a specific policy mapping
|
||||
func (client *peerRESTClient) LoadPolicyMapping(userOrGroup string, userType IAMUserType, isGroup bool) error {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := loadPolicyMappingHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err := loadPolicyMappingRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTUserOrGroup: userOrGroup,
|
||||
peerRESTUserType: strconv.Itoa(int(userType)),
|
||||
peerRESTIsGroup: strconv.FormatBool(isGroup),
|
||||
@@ -476,12 +344,7 @@ func (client *peerRESTClient) LoadPolicyMapping(userOrGroup string, userType IAM
|
||||
|
||||
// DeleteUser - delete a specific user.
|
||||
func (client *peerRESTClient) DeleteUser(accessKey string) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = deleteUserHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = deleteUserRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTUser: accessKey,
|
||||
}))
|
||||
return err
|
||||
@@ -489,12 +352,7 @@ func (client *peerRESTClient) DeleteUser(accessKey string) (err error) {
|
||||
|
||||
// DeleteServiceAccount - delete a specific service account.
|
||||
func (client *peerRESTClient) DeleteServiceAccount(accessKey string) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = deleteSvcActHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = deleteSvcActRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTUser: accessKey,
|
||||
}))
|
||||
return err
|
||||
@@ -502,12 +360,7 @@ func (client *peerRESTClient) DeleteServiceAccount(accessKey string) (err error)
|
||||
|
||||
// LoadUser - reload a specific user.
|
||||
func (client *peerRESTClient) LoadUser(accessKey string, temp bool) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = loadUserHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = loadUserRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTUser: accessKey,
|
||||
peerRESTUserTemp: strconv.FormatBool(temp),
|
||||
}))
|
||||
@@ -516,12 +369,7 @@ func (client *peerRESTClient) LoadUser(accessKey string, temp bool) (err error)
|
||||
|
||||
// LoadServiceAccount - reload a specific service account.
|
||||
func (client *peerRESTClient) LoadServiceAccount(accessKey string) (err error) {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = loadSvcActHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err = loadSvcActRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTUser: accessKey,
|
||||
}))
|
||||
return err
|
||||
@@ -529,12 +377,7 @@ func (client *peerRESTClient) LoadServiceAccount(accessKey string) (err error) {
|
||||
|
||||
// LoadGroup - send load group command to peers.
|
||||
func (client *peerRESTClient) LoadGroup(group string) error {
|
||||
conn := client.gridConn()
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := loadGroupHandler.Call(context.Background(), conn, grid.NewMSSWith(map[string]string{
|
||||
_, err := loadGroupRPC.Call(context.Background(), client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTGroup: group,
|
||||
}))
|
||||
return err
|
||||
@@ -546,7 +389,7 @@ func (client *peerRESTClient) ReloadSiteReplicationConfig(ctx context.Context) e
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := reloadSiteReplicationConfigHandler.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
_, err := reloadSiteReplicationConfigRPC.Call(ctx, conn, grid.NewMSS())
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -577,28 +420,17 @@ func (client *peerRESTClient) CommitBinary(ctx context.Context) error {
|
||||
|
||||
// SignalService - sends signal to peer nodes.
|
||||
func (client *peerRESTClient) SignalService(sig serviceSignal, subSys string, dryRun bool) error {
|
||||
values := make(url.Values)
|
||||
values := grid.NewMSS()
|
||||
values.Set(peerRESTSignal, strconv.Itoa(int(sig)))
|
||||
values.Set(peerRESTDryRun, strconv.FormatBool(dryRun))
|
||||
values.Set(peerRESTSubSys, subSys)
|
||||
respBody, err := client.call(peerRESTMethodSignalService, values, nil, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
return nil
|
||||
_, err := signalServiceRPC.Call(context.Background(), client.gridConn(), values)
|
||||
return err
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) BackgroundHealStatus() (madmin.BgHealState, error) {
|
||||
respBody, err := client.call(peerRESTMethodBackgroundHealStatus, nil, nil, -1)
|
||||
if err != nil {
|
||||
return madmin.BgHealState{}, err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
|
||||
state := madmin.BgHealState{}
|
||||
err = gob.NewDecoder(respBody).Decode(&state)
|
||||
return state, err
|
||||
resp, err := getBackgroundHealStatusRPC.Call(context.Background(), client.gridConn(), grid.NewMSS())
|
||||
return resp.ValueOrZero(), err
|
||||
}
|
||||
|
||||
// GetMetacacheListing - get a new or existing metacache.
|
||||
@@ -607,19 +439,7 @@ func (client *peerRESTClient) GetMetacacheListing(ctx context.Context, o listPat
|
||||
resp := localMetacacheMgr.getBucket(ctx, o.Bucket).findCache(o)
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
var reader bytes.Buffer
|
||||
err := gob.NewEncoder(&reader).Encode(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetMetacacheListing, nil, &reader, int64(reader.Len()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp metacache
|
||||
defer xhttp.DrainBody(respBody)
|
||||
return &resp, msgp.Decode(respBody, &resp)
|
||||
return getMetacacheListingRPC.Call(ctx, client.gridConn(), &o)
|
||||
}
|
||||
|
||||
// UpdateMetacacheListing - update an existing metacache it will unconditionally be updated to the new state.
|
||||
@@ -627,17 +447,11 @@ func (client *peerRESTClient) UpdateMetacacheListing(ctx context.Context, m meta
|
||||
if client == nil {
|
||||
return localMetacacheMgr.updateCacheEntry(m)
|
||||
}
|
||||
b, err := m.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
return m, err
|
||||
resp, err := updateMetacacheListingRPC.Call(ctx, client.gridConn(), &m)
|
||||
if err != nil || resp == nil {
|
||||
return metacache{}, err
|
||||
}
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodUpdateMetacacheListing, nil, bytes.NewBuffer(b), int64(len(b)))
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
var resp metacache
|
||||
return resp, msgp.Decode(respBody, &resp)
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) ReloadPoolMeta(ctx context.Context) error {
|
||||
@@ -645,7 +459,7 @@ func (client *peerRESTClient) ReloadPoolMeta(ctx context.Context) error {
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := reloadPoolMetaHandler.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
_, err := reloadPoolMetaRPC.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -654,7 +468,7 @@ func (client *peerRESTClient) StopRebalance(ctx context.Context) error {
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := stopRebalanceHandler.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
_, err := stopRebalanceRPC.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -663,7 +477,7 @@ func (client *peerRESTClient) LoadRebalanceMeta(ctx context.Context, startRebala
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := loadRebalanceMetaHandler.Call(ctx, conn, grid.NewMSSWith(map[string]string{
|
||||
_, err := loadRebalanceMetaRPC.Call(ctx, conn, grid.NewMSSWith(map[string]string{
|
||||
peerRESTStartRebalance: strconv.FormatBool(startRebalance),
|
||||
}))
|
||||
return err
|
||||
@@ -674,7 +488,7 @@ func (client *peerRESTClient) LoadTransitionTierConfig(ctx context.Context) erro
|
||||
if conn == nil {
|
||||
return nil
|
||||
}
|
||||
_, err := loadTransitionTierConfigHandler.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
_, err := loadTransitionTierConfigRPC.Call(ctx, conn, grid.NewMSSWith(map[string]string{}))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -711,7 +525,7 @@ func (client *peerRESTClient) doListen(ctx context.Context, listenCh chan<- []by
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
st, err := listenHandler.Call(ctx, conn, grid.NewURLValuesWith(v))
|
||||
st, err := listenRPC.Call(ctx, conn, grid.NewURLValuesWith(v))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -759,48 +573,31 @@ func (client *peerRESTClient) Trace(ctx context.Context, traceCh chan<- []byte,
|
||||
}()
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) doConsoleLog(logCh chan log.Info, doneCh <-chan struct{}) {
|
||||
// To cancel the REST request in case doneCh gets closed.
|
||||
ctx, cancel := context.WithCancel(GlobalContext)
|
||||
|
||||
cancelCh := make(chan struct{})
|
||||
defer close(cancelCh)
|
||||
go func() {
|
||||
select {
|
||||
case <-doneCh:
|
||||
case <-cancelCh:
|
||||
// There was an error in the REST request.
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodLog, nil, nil, -1)
|
||||
defer xhttp.DrainBody(respBody)
|
||||
func (client *peerRESTClient) doConsoleLog(ctx context.Context, kind madmin.LogMask, logCh chan<- []byte) {
|
||||
st, err := consoleLogRPC.Call(ctx, client.gridConn(), grid.NewMSSWith(map[string]string{
|
||||
peerRESTLogMask: strconv.Itoa(int(kind)),
|
||||
}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dec := gob.NewDecoder(respBody)
|
||||
for {
|
||||
var lg log.Info
|
||||
if err = dec.Decode(&lg); err != nil {
|
||||
break
|
||||
}
|
||||
st.Results(func(b *grid.Bytes) error {
|
||||
select {
|
||||
case logCh <- lg:
|
||||
case logCh <- *b:
|
||||
default:
|
||||
consoleLogRPC.PutResponse(b)
|
||||
// Do not block on slow receivers.
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ConsoleLog - sends request to peer nodes to get console logs
|
||||
func (client *peerRESTClient) ConsoleLog(logCh chan log.Info, doneCh <-chan struct{}) {
|
||||
func (client *peerRESTClient) ConsoleLog(ctx context.Context, kind madmin.LogMask, logCh chan<- []byte) {
|
||||
go func() {
|
||||
for {
|
||||
client.doConsoleLog(logCh, doneCh)
|
||||
client.doConsoleLog(ctx, kind, logCh)
|
||||
select {
|
||||
case <-doneCh:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
// There was error in the REST request, retry after sometime as probably the peer is down.
|
||||
@@ -838,71 +635,75 @@ func newPeerRestClients(endpoints EndpointServerPools) (remote, all []*peerRESTC
|
||||
|
||||
// MonitorBandwidth - send http trace request to peer nodes
|
||||
func (client *peerRESTClient) MonitorBandwidth(ctx context.Context, buckets []string) (*bandwidth.BucketBandwidthReport, error) {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTBuckets, strings.Join(buckets, ","))
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetBandwidth, values, nil, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
|
||||
dec := gob.NewDecoder(respBody)
|
||||
var bandwidthReport bandwidth.BucketBandwidthReport
|
||||
err = dec.Decode(&bandwidthReport)
|
||||
return &bandwidthReport, err
|
||||
values := grid.NewURLValuesWith(map[string][]string{
|
||||
peerRESTBuckets: buckets,
|
||||
})
|
||||
return getBandwidthRPC.Call(ctx, client.gridConn(), values)
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) GetPeerMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetPeerMetrics, nil, nil, -1)
|
||||
func (client *peerRESTClient) GetResourceMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
resp, err := getResourceMetricsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec := gob.NewDecoder(respBody)
|
||||
ch := make(chan Metric)
|
||||
go func(ch chan<- Metric) {
|
||||
defer func() {
|
||||
xhttp.DrainBody(respBody)
|
||||
close(ch)
|
||||
}()
|
||||
for {
|
||||
var metric Metric
|
||||
if err := dec.Decode(&metric); err != nil {
|
||||
return
|
||||
defer close(ch)
|
||||
for _, m := range resp.Value() {
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ch <- metric:
|
||||
case ch <- *m:
|
||||
}
|
||||
}
|
||||
}(ch)
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) GetPeerBucketMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
respBody, err := client.callWithContext(ctx, peerRESTMethodGetPeerBucketMetrics, nil, nil, -1)
|
||||
func (client *peerRESTClient) GetPeerMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
resp, err := getPeerMetricsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec := gob.NewDecoder(respBody)
|
||||
ch := make(chan Metric)
|
||||
go func(ch chan<- Metric) {
|
||||
defer func() {
|
||||
xhttp.DrainBody(respBody)
|
||||
close(ch)
|
||||
}()
|
||||
for {
|
||||
var metric Metric
|
||||
if err := dec.Decode(&metric); err != nil {
|
||||
return
|
||||
go func() {
|
||||
defer close(ch)
|
||||
for _, m := range resp.Value() {
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ch <- metric:
|
||||
case ch <- *m:
|
||||
}
|
||||
}
|
||||
}(ch)
|
||||
}()
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) GetPeerBucketMetrics(ctx context.Context) (<-chan Metric, error) {
|
||||
resp, err := getPeerBucketMetricsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ch := make(chan Metric)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
for _, m := range resp.Value() {
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ch <- *m:
|
||||
}
|
||||
}
|
||||
}()
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
@@ -966,18 +767,11 @@ func (client *peerRESTClient) DriveSpeedTest(ctx context.Context, opts madmin.Dr
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) GetLastDayTierStats(ctx context.Context) (DailyAllTierStats, error) {
|
||||
var result map[string]lastDayTierStats
|
||||
respBody, err := client.callWithContext(context.Background(), peerRESTMethodGetLastDayTierStats, nil, nil, -1)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
|
||||
err = gob.NewDecoder(respBody).Decode(&result)
|
||||
if err != nil {
|
||||
resp, err := getLastDayTierStatsRPC.Call(ctx, client.gridConn(), grid.NewMSS())
|
||||
if err != nil || resp == nil {
|
||||
return DailyAllTierStats{}, err
|
||||
}
|
||||
return DailyAllTierStats(result), nil
|
||||
return *resp, nil
|
||||
}
|
||||
|
||||
// DevNull - Used by netperf to pump data to peer
|
||||
|
||||
+18
-38
@@ -18,50 +18,29 @@
|
||||
package cmd
|
||||
|
||||
const (
|
||||
peerRESTVersion = "v37" // Add 'metrics' option for ServerInfo
|
||||
peerRESTVersion = "v38" // Convert RPC calls
|
||||
peerRESTVersionPrefix = SlashSeparator + peerRESTVersion
|
||||
peerRESTPrefix = minioReservedBucketPath + "/peer"
|
||||
peerRESTPath = peerRESTPrefix + peerRESTVersionPrefix
|
||||
)
|
||||
|
||||
const (
|
||||
peerRESTMethodHealth = "/health"
|
||||
peerRESTMethodServerInfo = "/serverinfo"
|
||||
peerRESTMethodLocalStorageInfo = "/localstorageinfo"
|
||||
peerRESTMethodCPUInfo = "/cpuinfo"
|
||||
peerRESTMethodDiskHwInfo = "/diskhwinfo"
|
||||
peerRESTMethodNetHwInfo = "/nethwinfo"
|
||||
peerRESTMethodOsInfo = "/osinfo"
|
||||
peerRESTMethodMemInfo = "/meminfo"
|
||||
peerRESTMethodProcInfo = "/procinfo"
|
||||
peerRESTMethodSysErrors = "/syserrors"
|
||||
peerRESTMethodSysServices = "/sysservices"
|
||||
peerRESTMethodSysConfig = "/sysconfig"
|
||||
peerRESTMethodGetBucketStats = "/getbucketstats"
|
||||
peerRESTMethodGetAllBucketStats = "/getallbucketstats"
|
||||
peerRESTMethodVerifyBinary = "/verifybinary"
|
||||
peerRESTMethodCommitBinary = "/commitbinary"
|
||||
peerRESTMethodSignalService = "/signalservice"
|
||||
peerRESTMethodBackgroundHealStatus = "/backgroundhealstatus"
|
||||
peerRESTMethodGetLocks = "/getlocks"
|
||||
peerRESTMethodStartProfiling = "/startprofiling"
|
||||
peerRESTMethodDownloadProfilingData = "/downloadprofilingdata"
|
||||
peerRESTMethodLog = "/log"
|
||||
peerRESTMethodGetBandwidth = "/bandwidth"
|
||||
peerRESTMethodGetMetacacheListing = "/getmetacache"
|
||||
peerRESTMethodUpdateMetacacheListing = "/updatemetacache"
|
||||
peerRESTMethodGetPeerMetrics = "/peermetrics"
|
||||
peerRESTMethodGetPeerBucketMetrics = "/peerbucketmetrics"
|
||||
peerRESTMethodSpeedTest = "/speedtest"
|
||||
peerRESTMethodDriveSpeedTest = "/drivespeedtest"
|
||||
peerRESTMethodStopRebalance = "/stoprebalance"
|
||||
peerRESTMethodGetLastDayTierStats = "/getlastdaytierstats"
|
||||
peerRESTMethodDevNull = "/devnull"
|
||||
peerRESTMethodNetperf = "/netperf"
|
||||
peerRESTMethodMetrics = "/metrics"
|
||||
peerRESTMethodResourceMetrics = "/resourcemetrics"
|
||||
peerRESTMethodGetReplicationMRF = "/getreplicationmrf"
|
||||
peerRESTMethodGetSRMetrics = "/getsrmetrics"
|
||||
peerRESTMethodHealth = "/health"
|
||||
peerRESTMethodVerifyBinary = "/verifybinary"
|
||||
peerRESTMethodCommitBinary = "/commitbinary"
|
||||
peerRESTMethodSignalService = "/signalservice"
|
||||
peerRESTMethodBackgroundHealStatus = "/backgroundhealstatus"
|
||||
peerRESTMethodGetLocks = "/getlocks"
|
||||
peerRESTMethodStartProfiling = "/startprofiling"
|
||||
peerRESTMethodDownloadProfilingData = "/downloadprofilingdata"
|
||||
peerRESTMethodGetBandwidth = "/bandwidth"
|
||||
peerRESTMethodSpeedTest = "/speedtest"
|
||||
peerRESTMethodDriveSpeedTest = "/drivespeedtest"
|
||||
peerRESTMethodReloadSiteReplicationConfig = "/reloadsitereplicationconfig"
|
||||
peerRESTMethodGetLastDayTierStats = "/getlastdaytierstats"
|
||||
peerRESTMethodDevNull = "/devnull"
|
||||
peerRESTMethodNetperf = "/netperf"
|
||||
peerRESTMethodGetReplicationMRF = "/getreplicationmrf"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -99,4 +78,5 @@ const (
|
||||
peerRESTListenPrefix = "prefix"
|
||||
peerRESTListenSuffix = "suffix"
|
||||
peerRESTListenEvents = "events"
|
||||
peerRESTLogMask = "log-mask"
|
||||
)
|
||||
|
||||
+262
-456
File diff suppressed because it is too large
Load Diff
@@ -376,7 +376,7 @@ func (client *remotePeerS3Client) HealBucket(ctx context.Context, bucket string,
|
||||
peerS3BucketDeleted: strconv.FormatBool(opts.Remove),
|
||||
})
|
||||
|
||||
_, err := healBucketHandler.Call(ctx, conn, mss)
|
||||
_, err := healBucketRPC.Call(ctx, conn, mss)
|
||||
|
||||
// Initialize heal result info
|
||||
return madmin.HealResultItem{
|
||||
@@ -398,7 +398,7 @@ func (client *remotePeerS3Client) GetBucketInfo(ctx context.Context, bucket stri
|
||||
peerS3BucketDeleted: strconv.FormatBool(opts.Deleted),
|
||||
})
|
||||
|
||||
volInfo, err := headBucketHandler.Call(ctx, conn, mss)
|
||||
volInfo, err := headBucketRPC.Call(ctx, conn, mss)
|
||||
if err != nil {
|
||||
return BucketInfo{}, toStorageErr(err)
|
||||
}
|
||||
@@ -449,7 +449,7 @@ func (client *remotePeerS3Client) MakeBucket(ctx context.Context, bucket string,
|
||||
peerS3BucketForceCreate: strconv.FormatBool(opts.ForceCreate),
|
||||
})
|
||||
|
||||
_, err := makeBucketHandler.Call(ctx, conn, mss)
|
||||
_, err := makeBucketRPC.Call(ctx, conn, mss)
|
||||
return toStorageErr(err)
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ func (client *remotePeerS3Client) DeleteBucket(ctx context.Context, bucket strin
|
||||
peerS3BucketForceDelete: strconv.FormatBool(opts.Force),
|
||||
})
|
||||
|
||||
_, err := deleteBucketHandler.Call(ctx, conn, mss)
|
||||
_, err := deleteBucketRPC.Call(ctx, conn, mss)
|
||||
return toStorageErr(err)
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -651,6 +651,15 @@ func serverMain(ctx *cli.Context) {
|
||||
|
||||
setDefaultProfilerRates()
|
||||
|
||||
// Initialize globalConsoleSys system
|
||||
bootstrapTrace("newConsoleLogger", func() {
|
||||
globalConsoleSys = NewConsoleLogger(GlobalContext)
|
||||
logger.AddSystemTarget(GlobalContext, globalConsoleSys)
|
||||
|
||||
// Set node name, only set for distributed setup.
|
||||
globalConsoleSys.SetNodeName(globalLocalNodeName)
|
||||
})
|
||||
|
||||
// Always load ENV variables from files first.
|
||||
loadEnvVarsFromFiles()
|
||||
|
||||
@@ -672,15 +681,6 @@ func serverMain(ctx *cli.Context) {
|
||||
// the config file if not defined, set the default one.
|
||||
loadRootCredentials()
|
||||
|
||||
// Initialize globalConsoleSys system
|
||||
bootstrapTrace("newConsoleLogger", func() {
|
||||
globalConsoleSys = NewConsoleLogger(GlobalContext)
|
||||
logger.AddSystemTarget(GlobalContext, globalConsoleSys)
|
||||
|
||||
// Set node name, only set for distributed setup.
|
||||
globalConsoleSys.SetNodeName(globalLocalNodeName)
|
||||
})
|
||||
|
||||
// Perform any self-tests
|
||||
bootstrapTrace("selftests", func() {
|
||||
bitrotSelfTest()
|
||||
|
||||
+2
-2
@@ -1974,8 +1974,8 @@ func (s *TestSuiteCommon) TestGetObjectLarge11MiB(c *check) {
|
||||
c.Assert(putMD5, getMD5)
|
||||
}
|
||||
|
||||
// TestGetPartialObjectMisAligned - tests get object partially mis-aligned.
|
||||
// create a large buffer of mis-aligned data and upload it.
|
||||
// TestGetPartialObjectMisAligned - tests get object partially miss-aligned.
|
||||
// create a large buffer of miss-aligned data and upload it.
|
||||
// then make partial range requests to while fetching it back and assert the response content.
|
||||
func (s *TestSuiteCommon) TestGetPartialObjectMisAligned(c *check) {
|
||||
// generate a random bucket name.
|
||||
|
||||
@@ -258,7 +258,7 @@ func TestParseSignature(t *testing.T) {
|
||||
expectedErrCode APIErrorCode
|
||||
}{
|
||||
// Test case - 1.
|
||||
// SignElemenet doesn't have 2 parts on an attempt to split at '='.
|
||||
// SignElement doesn't have 2 parts on an attempt to split at '='.
|
||||
// ErrMissingFields expected.
|
||||
{
|
||||
inputSignElement: "Signature",
|
||||
@@ -274,7 +274,7 @@ func TestParseSignature(t *testing.T) {
|
||||
expectedErrCode: ErrMissingFields,
|
||||
},
|
||||
// Test case - 3.
|
||||
// SignElemenet with missing "SignatureTag",ErrMissingSignTag expected.
|
||||
// SignElement with missing "SignatureTag",ErrMissingSignTag expected.
|
||||
{
|
||||
inputSignElement: "Sign=",
|
||||
expectedSignStr: "",
|
||||
@@ -310,7 +310,7 @@ func TestParseSignedHeaders(t *testing.T) {
|
||||
expectedErrCode APIErrorCode
|
||||
}{
|
||||
// Test case - 1.
|
||||
// SignElemenet doesn't have 2 parts on an attempt to split at '='.
|
||||
// SignElement doesn't have 2 parts on an attempt to split at '='.
|
||||
// ErrMissingFields expected.
|
||||
{
|
||||
inputSignElement: "SignedHeaders",
|
||||
@@ -318,7 +318,7 @@ func TestParseSignedHeaders(t *testing.T) {
|
||||
expectedErrCode: ErrMissingFields,
|
||||
},
|
||||
// Test case - 2.
|
||||
// SignElemenet with missing "SigHeaderTag",ErrMissingSignHeadersTag expected.
|
||||
// SignElement with missing "SigHeaderTag",ErrMissingSignHeadersTag expected.
|
||||
{
|
||||
inputSignElement: "Sign=",
|
||||
expectedSignedHeaders: nil,
|
||||
|
||||
@@ -3946,7 +3946,7 @@ func (c *SiteReplicationSys) EditPeerCluster(ctx context.Context, peer madmin.Pe
|
||||
return madmin.ReplicateEditStatus{}, errSRInvalidRequest(fmt.Errorf("Endpoint %s not reachable: %w", peer.Endpoint, err))
|
||||
}
|
||||
if info.DeploymentID != v.DeploymentID {
|
||||
return madmin.ReplicateEditStatus{}, errSRInvalidRequest(fmt.Errorf("Endpoint %s does not belong to deployment expected: %s (found %s) ", v.Endpoint, v.DeploymentID, info.DeploymentID))
|
||||
return madmin.ReplicateEditStatus{}, errSRInvalidRequest(fmt.Errorf("Endpoint %s does not belong to deployment expected: %s (found %s) ", peer.Endpoint, v.DeploymentID, info.DeploymentID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:generate msgp -file=$GOFILE
|
||||
|
||||
// DeleteOptions represents the disk level delete options available for the APIs
|
||||
type DeleteOptions struct {
|
||||
BaseOptions
|
||||
@@ -44,8 +46,6 @@ type DiskInfoOptions struct {
|
||||
NoOp bool `msg:"np"`
|
||||
}
|
||||
|
||||
//go:generate msgp -file=$GOFILE
|
||||
|
||||
// DiskInfo is an extended type which returns current
|
||||
// disk usage per path.
|
||||
// The above means that any added/deleted fields are incompatible.
|
||||
@@ -445,3 +445,8 @@ type RenameDataResp struct {
|
||||
type LocalDiskIDs struct {
|
||||
IDs []string
|
||||
}
|
||||
|
||||
// ListDirResult - ListDir()'s response.
|
||||
type ListDirResult struct {
|
||||
Entries []string `msg:"e"`
|
||||
}
|
||||
|
||||
@@ -2871,6 +2871,148 @@ func (z *FilesInfo) Msgsize() (s int) {
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *ListDirResult) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "e":
|
||||
var zb0002 uint32
|
||||
zb0002, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries")
|
||||
return
|
||||
}
|
||||
if cap(z.Entries) >= int(zb0002) {
|
||||
z.Entries = (z.Entries)[:zb0002]
|
||||
} else {
|
||||
z.Entries = make([]string, zb0002)
|
||||
}
|
||||
for za0001 := range z.Entries {
|
||||
z.Entries[za0001], err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *ListDirResult) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 1
|
||||
// write "e"
|
||||
err = en.Append(0x81, 0xa1, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.Entries)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries")
|
||||
return
|
||||
}
|
||||
for za0001 := range z.Entries {
|
||||
err = en.WriteString(z.Entries[za0001])
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *ListDirResult) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 1
|
||||
// string "e"
|
||||
o = append(o, 0x81, 0xa1, 0x65)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.Entries)))
|
||||
for za0001 := range z.Entries {
|
||||
o = msgp.AppendString(o, z.Entries[za0001])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *ListDirResult) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "e":
|
||||
var zb0002 uint32
|
||||
zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries")
|
||||
return
|
||||
}
|
||||
if cap(z.Entries) >= int(zb0002) {
|
||||
z.Entries = (z.Entries)[:zb0002]
|
||||
} else {
|
||||
z.Entries = make([]string, zb0002)
|
||||
}
|
||||
for za0001 := range z.Entries {
|
||||
z.Entries[za0001], bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Entries", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *ListDirResult) Msgsize() (s int) {
|
||||
s = 1 + 2 + msgp.ArrayHeaderSize
|
||||
for za0001 := range z.Entries {
|
||||
s += msgp.StringPrefixSize + len(z.Entries[za0001])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *LocalDiskIDs) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
|
||||
@@ -1252,6 +1252,119 @@ func BenchmarkDecodeFilesInfo(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalListDirResult(t *testing.T) {
|
||||
v := ListDirResult{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgListDirResult(b *testing.B) {
|
||||
v := ListDirResult{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgListDirResult(b *testing.B) {
|
||||
v := ListDirResult{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalListDirResult(b *testing.B) {
|
||||
v := ListDirResult{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeListDirResult(t *testing.T) {
|
||||
v := ListDirResult{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeListDirResult Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := ListDirResult{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeListDirResult(b *testing.B) {
|
||||
v := ListDirResult{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeListDirResult(b *testing.B) {
|
||||
v := ListDirResult{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalLocalDiskIDs(t *testing.T) {
|
||||
v := LocalDiskIDs{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
|
||||
+67
-33
@@ -35,6 +35,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
"github.com/minio/minio/internal/grid"
|
||||
xhttp "github.com/minio/minio/internal/http"
|
||||
xioutil "github.com/minio/minio/internal/ioutil"
|
||||
@@ -166,6 +167,8 @@ type storageRESTClient struct {
|
||||
formatData []byte
|
||||
formatMutex sync.RWMutex
|
||||
|
||||
diskInfoCache *cachevalue.Cache[DiskInfo]
|
||||
|
||||
// Indexes, will be -1 until assigned a set.
|
||||
poolIndex, setIndex, diskIndex int
|
||||
}
|
||||
@@ -237,7 +240,7 @@ func (client *storageRESTClient) NSScanner(ctx context.Context, cache dataUsageC
|
||||
defer atomic.AddInt32(&client.scanning, -1)
|
||||
defer xioutil.SafeClose(updates)
|
||||
|
||||
st, err := storageNSScannerHandler.Call(ctx, client.gridConn, &nsScannerOptions{
|
||||
st, err := storageNSScannerRPC.Call(ctx, client.gridConn, &nsScannerOptions{
|
||||
DiskID: client.diskID,
|
||||
ScanMode: int(scanMode),
|
||||
Cache: &cache,
|
||||
@@ -306,21 +309,48 @@ func (client *storageRESTClient) DiskInfo(ctx context.Context, opts DiskInfoOpti
|
||||
// transport is already down.
|
||||
return info, errDiskNotFound
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
opts.DiskID = client.diskID
|
||||
// if metrics was asked, or it was a NoOp we do not need to cache the value.
|
||||
if opts.Metrics || opts.NoOp {
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
infop, err := storageDiskInfoHandler.Call(ctx, client.gridConn, &opts)
|
||||
if err != nil {
|
||||
return info, toStorageErr(err)
|
||||
}
|
||||
info = *infop
|
||||
if info.Error != "" {
|
||||
return info, toStorageErr(errors.New(info.Error))
|
||||
}
|
||||
opts.DiskID = client.diskID
|
||||
|
||||
infop, err := storageDiskInfoRPC.Call(ctx, client.gridConn, &opts)
|
||||
if err != nil {
|
||||
return info, toStorageErr(err)
|
||||
}
|
||||
info = *infop
|
||||
if info.Error != "" {
|
||||
return info, toStorageErr(errors.New(info.Error))
|
||||
}
|
||||
info.Scanning = atomic.LoadInt32(&client.scanning) == 1
|
||||
return info, nil
|
||||
} // In all other cases cache the value upto 1sec.
|
||||
|
||||
client.diskInfoCache.Once.Do(func() {
|
||||
client.diskInfoCache.TTL = time.Second
|
||||
client.diskInfoCache.Update = func() (info DiskInfo, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
nopts := DiskInfoOptions{DiskID: client.diskID}
|
||||
infop, err := storageDiskInfoRPC.Call(ctx, client.gridConn, &nopts)
|
||||
if err != nil {
|
||||
return info, toStorageErr(err)
|
||||
}
|
||||
info = *infop
|
||||
if info.Error != "" {
|
||||
return info, toStorageErr(errors.New(info.Error))
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
})
|
||||
|
||||
info, err = client.diskInfoCache.Get()
|
||||
info.Scanning = atomic.LoadInt32(&client.scanning) == 1
|
||||
return info, nil
|
||||
return info, err
|
||||
}
|
||||
|
||||
// MakeVolBulk - create multiple volumes in a bulk operation.
|
||||
@@ -340,7 +370,7 @@ func (client *storageRESTClient) ListVols(ctx context.Context) (vols []VolInfo,
|
||||
|
||||
// StatVol - get volume info over the network.
|
||||
func (client *storageRESTClient) StatVol(ctx context.Context, volume string) (vol VolInfo, err error) {
|
||||
v, err := storageStatVolHandler.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
v, err := storageStatVolRPC.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
storageRESTDiskID: client.diskID,
|
||||
storageRESTVolume: volume,
|
||||
}))
|
||||
@@ -349,7 +379,7 @@ func (client *storageRESTClient) StatVol(ctx context.Context, volume string) (vo
|
||||
}
|
||||
vol = *v
|
||||
// Performs shallow copy, so we can reuse.
|
||||
storageStatVolHandler.PutResponse(v)
|
||||
storageStatVolRPC.PutResponse(v)
|
||||
return vol, nil
|
||||
}
|
||||
|
||||
@@ -386,7 +416,7 @@ func (client *storageRESTClient) CreateFile(ctx context.Context, origvolume, vol
|
||||
}
|
||||
|
||||
func (client *storageRESTClient) WriteMetadata(ctx context.Context, origvolume, volume, path string, fi FileInfo) error {
|
||||
_, err := storageWriteMetadataHandler.Call(ctx, client.gridConn, &MetadataHandlerParams{
|
||||
_, err := storageWriteMetadataRPC.Call(ctx, client.gridConn, &MetadataHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
OrigVolume: origvolume,
|
||||
Volume: volume,
|
||||
@@ -397,7 +427,7 @@ func (client *storageRESTClient) WriteMetadata(ctx context.Context, origvolume,
|
||||
}
|
||||
|
||||
func (client *storageRESTClient) UpdateMetadata(ctx context.Context, volume, path string, fi FileInfo, opts UpdateMetadataOpts) error {
|
||||
_, err := storageUpdateMetadataHandler.Call(ctx, client.gridConn, &MetadataHandlerParams{
|
||||
_, err := storageUpdateMetadataRPC.Call(ctx, client.gridConn, &MetadataHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
Volume: volume,
|
||||
FilePath: path,
|
||||
@@ -408,7 +438,7 @@ func (client *storageRESTClient) UpdateMetadata(ctx context.Context, volume, pat
|
||||
}
|
||||
|
||||
func (client *storageRESTClient) DeleteVersion(ctx context.Context, volume, path string, fi FileInfo, forceDelMarker bool, opts DeleteOptions) (err error) {
|
||||
_, err = storageDeleteVersionHandler.Call(ctx, client.gridConn, &DeleteVersionHandlerParams{
|
||||
_, err = storageDeleteVersionRPC.Call(ctx, client.gridConn, &DeleteVersionHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
Volume: volume,
|
||||
FilePath: path,
|
||||
@@ -431,7 +461,7 @@ func (client *storageRESTClient) WriteAll(ctx context.Context, volume string, pa
|
||||
|
||||
// CheckParts - stat all file parts.
|
||||
func (client *storageRESTClient) CheckParts(ctx context.Context, volume string, path string, fi FileInfo) error {
|
||||
_, err := storageCheckPartsHandler.Call(ctx, client.gridConn, &CheckPartsHandlerParams{
|
||||
_, err := storageCheckPartsRPC.Call(ctx, client.gridConn, &CheckPartsHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
Volume: volume,
|
||||
FilePath: path,
|
||||
@@ -442,7 +472,7 @@ func (client *storageRESTClient) CheckParts(ctx context.Context, volume string,
|
||||
|
||||
// RenameData - rename source path to destination path atomically, metadata and data file.
|
||||
func (client *storageRESTClient) RenameData(ctx context.Context, srcVolume, srcPath string, fi FileInfo, dstVolume, dstPath string, opts RenameOptions) (sign uint64, err error) {
|
||||
resp, err := storageRenameDataHandler.Call(ctx, client.gridConn, &RenameDataHandlerParams{
|
||||
resp, err := storageRenameDataRPC.Call(ctx, client.gridConn, &RenameDataHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
SrcVolume: srcVolume,
|
||||
SrcPath: srcPath,
|
||||
@@ -454,7 +484,7 @@ func (client *storageRESTClient) RenameData(ctx context.Context, srcVolume, srcP
|
||||
if err != nil {
|
||||
return 0, toStorageErr(err)
|
||||
}
|
||||
defer storageRenameDataHandler.PutResponse(resp)
|
||||
defer storageRenameDataRPC.PutResponse(resp)
|
||||
return resp.Signature, nil
|
||||
}
|
||||
|
||||
@@ -484,7 +514,7 @@ func readMsgpReaderPoolPut(r *msgp.Reader) {
|
||||
func (client *storageRESTClient) ReadVersion(ctx context.Context, origvolume, volume, path, versionID string, opts ReadOptions) (fi FileInfo, err error) {
|
||||
// Use websocket when not reading data.
|
||||
if !opts.ReadData {
|
||||
resp, err := storageReadVersionHandler.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
resp, err := storageReadVersionRPC.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
storageRESTDiskID: client.diskID,
|
||||
storageRESTOrigVolume: origvolume,
|
||||
storageRESTVolume: volume,
|
||||
@@ -524,7 +554,7 @@ func (client *storageRESTClient) ReadVersion(ctx context.Context, origvolume, vo
|
||||
func (client *storageRESTClient) ReadXL(ctx context.Context, volume string, path string, readData bool) (rf RawFileInfo, err error) {
|
||||
// Use websocket when not reading data.
|
||||
if !readData {
|
||||
resp, err := storageReadXLHandler.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
resp, err := storageReadXLRPC.Call(ctx, client.gridConn, grid.NewMSSWith(map[string]string{
|
||||
storageRESTDiskID: client.diskID,
|
||||
storageRESTVolume: volume,
|
||||
storageRESTFilePath: path,
|
||||
@@ -567,7 +597,7 @@ func (client *storageRESTClient) ReadAll(ctx context.Context, volume string, pat
|
||||
}
|
||||
}
|
||||
|
||||
gridBytes, err := storageReadAllHandler.Call(ctx, client.gridConn, &ReadAllHandlerParams{
|
||||
gridBytes, err := storageReadAllRPC.Call(ctx, client.gridConn, &ReadAllHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
Volume: volume,
|
||||
FilePath: path,
|
||||
@@ -618,24 +648,27 @@ func (client *storageRESTClient) ReadFile(ctx context.Context, volume string, pa
|
||||
|
||||
// ListDir - lists a directory.
|
||||
func (client *storageRESTClient) ListDir(ctx context.Context, origvolume, volume, dirPath string, count int) (entries []string, err error) {
|
||||
values := make(url.Values)
|
||||
values := grid.NewMSS()
|
||||
values.Set(storageRESTVolume, volume)
|
||||
values.Set(storageRESTDirPath, dirPath)
|
||||
values.Set(storageRESTCount, strconv.Itoa(count))
|
||||
values.Set(storageRESTOrigVolume, origvolume)
|
||||
values.Set(storageRESTDiskID, client.diskID)
|
||||
|
||||
respBody, err := client.call(ctx, storageRESTMethodListDir, values, nil, -1)
|
||||
st, err := storageListDirRPC.Call(ctx, client.gridConn, values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, toStorageErr(err)
|
||||
}
|
||||
defer xhttp.DrainBody(respBody)
|
||||
err = gob.NewDecoder(respBody).Decode(&entries)
|
||||
return entries, err
|
||||
err = st.Results(func(resp *ListDirResult) error {
|
||||
entries = resp.Entries
|
||||
return nil
|
||||
})
|
||||
return entries, toStorageErr(err)
|
||||
}
|
||||
|
||||
// DeleteFile - deletes a file.
|
||||
func (client *storageRESTClient) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) error {
|
||||
_, err := storageDeleteFileHandler.Call(ctx, client.gridConn, &DeleteFileHandlerParams{
|
||||
_, err := storageDeleteFileRPC.Call(ctx, client.gridConn, &DeleteFileHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
Volume: volume,
|
||||
FilePath: path,
|
||||
@@ -700,7 +733,7 @@ func (client *storageRESTClient) DeleteVersions(ctx context.Context, volume stri
|
||||
|
||||
// RenameFile - renames a file.
|
||||
func (client *storageRESTClient) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolume, dstPath string) (err error) {
|
||||
_, err = storageRenameFileHandler.Call(ctx, client.gridConn, &RenameFileHandlerParams{
|
||||
_, err = storageRenameFileRPC.Call(ctx, client.gridConn, &RenameFileHandlerParams{
|
||||
DiskID: client.diskID,
|
||||
SrcVolume: srcVolume,
|
||||
SrcFilePath: srcPath,
|
||||
@@ -860,6 +893,7 @@ func newStorageRESTClient(endpoint Endpoint, healthCheck bool, gm *grid.Manager)
|
||||
}
|
||||
return &storageRESTClient{
|
||||
endpoint: endpoint, restClient: restClient, poolIndex: -1, setIndex: -1, diskIndex: -1,
|
||||
gridConn: conn,
|
||||
gridConn: conn,
|
||||
diskInfoCache: cachevalue.New[DiskInfo](),
|
||||
}, nil
|
||||
}
|
||||
|
||||
+45
-98
@@ -57,6 +57,23 @@ type storageRESTServer struct {
|
||||
poolIndex, setIndex, diskIndex int
|
||||
}
|
||||
|
||||
var (
|
||||
storageCheckPartsRPC = grid.NewSingleHandler[*CheckPartsHandlerParams, grid.NoPayload](grid.HandlerCheckParts, func() *CheckPartsHandlerParams { return &CheckPartsHandlerParams{} }, grid.NewNoPayload)
|
||||
storageDeleteFileRPC = grid.NewSingleHandler[*DeleteFileHandlerParams, grid.NoPayload](grid.HandlerDeleteFile, func() *DeleteFileHandlerParams { return &DeleteFileHandlerParams{} }, grid.NewNoPayload).AllowCallRequestPool(true)
|
||||
storageDeleteVersionRPC = grid.NewSingleHandler[*DeleteVersionHandlerParams, grid.NoPayload](grid.HandlerDeleteVersion, func() *DeleteVersionHandlerParams { return &DeleteVersionHandlerParams{} }, grid.NewNoPayload)
|
||||
storageDiskInfoRPC = grid.NewSingleHandler[*DiskInfoOptions, *DiskInfo](grid.HandlerDiskInfo, func() *DiskInfoOptions { return &DiskInfoOptions{} }, func() *DiskInfo { return &DiskInfo{} }).WithSharedResponse().AllowCallRequestPool(true)
|
||||
storageNSScannerRPC = grid.NewStream[*nsScannerOptions, grid.NoPayload, *nsScannerResp](grid.HandlerNSScanner, func() *nsScannerOptions { return &nsScannerOptions{} }, nil, func() *nsScannerResp { return &nsScannerResp{} })
|
||||
storageReadAllRPC = grid.NewSingleHandler[*ReadAllHandlerParams, *grid.Bytes](grid.HandlerReadAll, func() *ReadAllHandlerParams { return &ReadAllHandlerParams{} }, grid.NewBytes).AllowCallRequestPool(true)
|
||||
storageReadVersionRPC = grid.NewSingleHandler[*grid.MSS, *FileInfo](grid.HandlerReadVersion, grid.NewMSS, func() *FileInfo { return &FileInfo{} })
|
||||
storageReadXLRPC = grid.NewSingleHandler[*grid.MSS, *RawFileInfo](grid.HandlerReadXL, grid.NewMSS, func() *RawFileInfo { return &RawFileInfo{} })
|
||||
storageRenameDataRPC = grid.NewSingleHandler[*RenameDataHandlerParams, *RenameDataResp](grid.HandlerRenameData, func() *RenameDataHandlerParams { return &RenameDataHandlerParams{} }, func() *RenameDataResp { return &RenameDataResp{} })
|
||||
storageRenameFileRPC = grid.NewSingleHandler[*RenameFileHandlerParams, grid.NoPayload](grid.HandlerRenameFile, func() *RenameFileHandlerParams { return &RenameFileHandlerParams{} }, grid.NewNoPayload).AllowCallRequestPool(true)
|
||||
storageStatVolRPC = grid.NewSingleHandler[*grid.MSS, *VolInfo](grid.HandlerStatVol, grid.NewMSS, func() *VolInfo { return &VolInfo{} })
|
||||
storageUpdateMetadataRPC = grid.NewSingleHandler[*MetadataHandlerParams, grid.NoPayload](grid.HandlerUpdateMetadata, func() *MetadataHandlerParams { return &MetadataHandlerParams{} }, grid.NewNoPayload)
|
||||
storageWriteMetadataRPC = grid.NewSingleHandler[*MetadataHandlerParams, grid.NoPayload](grid.HandlerWriteMetadata, func() *MetadataHandlerParams { return &MetadataHandlerParams{} }, grid.NewNoPayload)
|
||||
storageListDirRPC = grid.NewStream[*grid.MSS, grid.NoPayload, *ListDirResult](grid.HandlerListDir, grid.NewMSS, nil, func() *ListDirResult { return &ListDirResult{} }).WithOutCapacity(1)
|
||||
)
|
||||
|
||||
func (s *storageRESTServer) getStorage() StorageAPI {
|
||||
globalLocalDrivesMu.RLock()
|
||||
defer globalLocalDrivesMu.RUnlock()
|
||||
@@ -198,11 +215,6 @@ func (s *storageRESTServer) HealthHandler(w http.ResponseWriter, r *http.Request
|
||||
s.IsValid(w, r)
|
||||
}
|
||||
|
||||
// DiskInfo types.
|
||||
// DiskInfo.Metrics elements are shared, so we cannot reuse.
|
||||
var storageDiskInfoHandler = grid.NewSingleHandler[*DiskInfoOptions, *DiskInfo](grid.HandlerDiskInfo, func() *DiskInfoOptions { return &DiskInfoOptions{} },
|
||||
func() *DiskInfo { return &DiskInfo{} }).WithSharedResponse().AllowCallRequestPool(true)
|
||||
|
||||
// DiskInfoHandler - returns disk info.
|
||||
func (s *storageRESTServer) DiskInfoHandler(opts *DiskInfoOptions) (*DiskInfo, *grid.RemoteErr) {
|
||||
if !s.checkID(opts.DiskID) {
|
||||
@@ -215,12 +227,6 @@ func (s *storageRESTServer) DiskInfoHandler(opts *DiskInfoOptions) (*DiskInfo, *
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// scanner rpc handler.
|
||||
var storageNSScannerHandler = grid.NewStream[*nsScannerOptions, grid.NoPayload, *nsScannerResp](grid.HandlerNSScanner,
|
||||
func() *nsScannerOptions { return &nsScannerOptions{} },
|
||||
nil,
|
||||
func() *nsScannerResp { return &nsScannerResp{} })
|
||||
|
||||
func (s *storageRESTServer) NSScannerHandler(ctx context.Context, params *nsScannerOptions, out chan<- *nsScannerResp) *grid.RemoteErr {
|
||||
if !s.checkID(params.DiskID) {
|
||||
return grid.NewRemoteErr(errDiskNotFound)
|
||||
@@ -236,7 +242,7 @@ func (s *storageRESTServer) NSScannerHandler(ctx context.Context, params *nsScan
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for update := range updates {
|
||||
resp := storageNSScannerHandler.NewResponse()
|
||||
resp := storageNSScannerRPC.NewResponse()
|
||||
resp.Update = &update
|
||||
out <- resp
|
||||
}
|
||||
@@ -247,7 +253,7 @@ func (s *storageRESTServer) NSScannerHandler(ctx context.Context, params *nsScan
|
||||
return grid.NewRemoteErr(err)
|
||||
}
|
||||
// Send final response.
|
||||
resp := storageNSScannerHandler.NewResponse()
|
||||
resp := storageNSScannerRPC.NewResponse()
|
||||
resp.Final = &ui
|
||||
out <- resp
|
||||
return nil
|
||||
@@ -277,22 +283,6 @@ func (s *storageRESTServer) MakeVolBulkHandler(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
}
|
||||
|
||||
// ListVolsHandler - list volumes.
|
||||
func (s *storageRESTServer) ListVolsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.IsValid(w, r) {
|
||||
return
|
||||
}
|
||||
infos, err := s.getStorage().ListVols(r.Context())
|
||||
if err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
logger.LogIf(r.Context(), msgp.Encode(w, VolsInfo(infos)))
|
||||
}
|
||||
|
||||
// statvol types.
|
||||
var storageStatVolHandler = grid.NewSingleHandler[*grid.MSS, *VolInfo](grid.HandlerStatVol, grid.NewMSS, func() *VolInfo { return &VolInfo{} })
|
||||
|
||||
// StatVolHandler - stat a volume.
|
||||
func (s *storageRESTServer) StatVolHandler(params *grid.MSS) (*VolInfo, *grid.RemoteErr) {
|
||||
if !s.checkID(params.Get(storageRESTDiskID)) {
|
||||
@@ -346,10 +336,6 @@ func (s *storageRESTServer) CreateFileHandler(w http.ResponseWriter, r *http.Req
|
||||
done(s.getStorage().CreateFile(r.Context(), origvolume, volume, filePath, int64(fileSize), body))
|
||||
}
|
||||
|
||||
var storageDeleteVersionHandler = grid.NewSingleHandler[*DeleteVersionHandlerParams, grid.NoPayload](grid.HandlerDeleteVersion, func() *DeleteVersionHandlerParams {
|
||||
return &DeleteVersionHandlerParams{}
|
||||
}, grid.NewNoPayload)
|
||||
|
||||
// DeleteVersionHandler delete updated metadata.
|
||||
func (s *storageRESTServer) DeleteVersionHandler(p *DeleteVersionHandlerParams) (np grid.NoPayload, gerr *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -364,10 +350,6 @@ func (s *storageRESTServer) DeleteVersionHandler(p *DeleteVersionHandlerParams)
|
||||
return np, grid.NewRemoteErr(err)
|
||||
}
|
||||
|
||||
var storageReadVersionHandler = grid.NewSingleHandler[*grid.MSS, *FileInfo](grid.HandlerReadVersion, grid.NewMSS, func() *FileInfo {
|
||||
return &FileInfo{}
|
||||
})
|
||||
|
||||
// ReadVersionHandlerWS read metadata of versionID
|
||||
func (s *storageRESTServer) ReadVersionHandlerWS(params *grid.MSS) (*FileInfo, *grid.RemoteErr) {
|
||||
if !s.checkID(params.Get(storageRESTDiskID)) {
|
||||
@@ -422,10 +404,6 @@ func (s *storageRESTServer) ReadVersionHandler(w http.ResponseWriter, r *http.Re
|
||||
logger.LogIf(r.Context(), msgp.Encode(w, &fi))
|
||||
}
|
||||
|
||||
var storageWriteMetadataHandler = grid.NewSingleHandler[*MetadataHandlerParams, grid.NoPayload](grid.HandlerWriteMetadata, func() *MetadataHandlerParams {
|
||||
return &MetadataHandlerParams{}
|
||||
}, grid.NewNoPayload)
|
||||
|
||||
// WriteMetadataHandler rpc handler to write new updated metadata.
|
||||
func (s *storageRESTServer) WriteMetadataHandler(p *MetadataHandlerParams) (np grid.NoPayload, gerr *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -440,10 +418,6 @@ func (s *storageRESTServer) WriteMetadataHandler(p *MetadataHandlerParams) (np g
|
||||
return np, grid.NewRemoteErr(err)
|
||||
}
|
||||
|
||||
var storageUpdateMetadataHandler = grid.NewSingleHandler[*MetadataHandlerParams, grid.NoPayload](grid.HandlerUpdateMetadata, func() *MetadataHandlerParams {
|
||||
return &MetadataHandlerParams{}
|
||||
}, grid.NewNoPayload)
|
||||
|
||||
// UpdateMetadataHandler update new updated metadata.
|
||||
func (s *storageRESTServer) UpdateMetadataHandler(p *MetadataHandlerParams) (grid.NoPayload, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -479,10 +453,6 @@ func (s *storageRESTServer) WriteAllHandler(w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
}
|
||||
|
||||
var storageCheckPartsHandler = grid.NewSingleHandler[*CheckPartsHandlerParams, grid.NoPayload](grid.HandlerCheckParts, func() *CheckPartsHandlerParams {
|
||||
return &CheckPartsHandlerParams{}
|
||||
}, grid.NewNoPayload)
|
||||
|
||||
// CheckPartsHandler - check if a file metadata exists.
|
||||
func (s *storageRESTServer) CheckPartsHandler(p *CheckPartsHandlerParams) (grid.NoPayload, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -493,10 +463,6 @@ func (s *storageRESTServer) CheckPartsHandler(p *CheckPartsHandlerParams) (grid.
|
||||
return grid.NewNPErr(s.getStorage().CheckParts(context.Background(), volume, filePath, p.FI))
|
||||
}
|
||||
|
||||
var storageReadAllHandler = grid.NewSingleHandler[*ReadAllHandlerParams, *grid.Bytes](grid.HandlerReadAll, func() *ReadAllHandlerParams {
|
||||
return &ReadAllHandlerParams{}
|
||||
}, grid.NewBytes).AllowCallRequestPool(true)
|
||||
|
||||
// ReadAllHandler - read all the contents of a file.
|
||||
func (s *storageRESTServer) ReadAllHandler(p *ReadAllHandlerParams) (*grid.Bytes, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -532,10 +498,6 @@ func (s *storageRESTServer) ReadXLHandler(w http.ResponseWriter, r *http.Request
|
||||
logger.LogIf(r.Context(), msgp.Encode(w, &rf))
|
||||
}
|
||||
|
||||
var storageReadXLHandler = grid.NewSingleHandler[*grid.MSS, *RawFileInfo](grid.HandlerReadXL, grid.NewMSS, func() *RawFileInfo {
|
||||
return &RawFileInfo{}
|
||||
})
|
||||
|
||||
// ReadXLHandlerWS - read xl.meta for an object at path.
|
||||
func (s *storageRESTServer) ReadXLHandlerWS(params *grid.MSS) (*RawFileInfo, *grid.RemoteErr) {
|
||||
if !s.checkID(params.Get(storageRESTDiskID)) {
|
||||
@@ -650,31 +612,26 @@ func (s *storageRESTServer) ReadFileStreamHandler(w http.ResponseWriter, r *http
|
||||
}
|
||||
|
||||
// ListDirHandler - list a directory.
|
||||
func (s *storageRESTServer) ListDirHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.IsValid(w, r) {
|
||||
return
|
||||
func (s *storageRESTServer) ListDirHandler(ctx context.Context, params *grid.MSS, out chan<- *ListDirResult) *grid.RemoteErr {
|
||||
if !s.checkID(params.Get(storageRESTDiskID)) {
|
||||
return grid.NewRemoteErr(errDiskNotFound)
|
||||
}
|
||||
volume := r.Form.Get(storageRESTVolume)
|
||||
dirPath := r.Form.Get(storageRESTDirPath)
|
||||
origvolume := r.Form.Get(storageRESTOrigVolume)
|
||||
count, err := strconv.Atoi(r.Form.Get(storageRESTCount))
|
||||
volume := params.Get(storageRESTVolume)
|
||||
dirPath := params.Get(storageRESTDirPath)
|
||||
origvolume := params.Get(storageRESTOrigVolume)
|
||||
count, err := strconv.Atoi(params.Get(storageRESTCount))
|
||||
if err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
return grid.NewRemoteErr(err)
|
||||
}
|
||||
|
||||
entries, err := s.getStorage().ListDir(r.Context(), origvolume, volume, dirPath, count)
|
||||
entries, err := s.getStorage().ListDir(ctx, origvolume, volume, dirPath, count)
|
||||
if err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
return grid.NewRemoteErr(err)
|
||||
}
|
||||
gob.NewEncoder(w).Encode(&entries)
|
||||
out <- &ListDirResult{Entries: entries}
|
||||
return nil
|
||||
}
|
||||
|
||||
var storageDeleteFileHandler = grid.NewSingleHandler[*DeleteFileHandlerParams, grid.NoPayload](grid.HandlerDeleteFile, func() *DeleteFileHandlerParams {
|
||||
return &DeleteFileHandlerParams{}
|
||||
}, grid.NewNoPayload).AllowCallRequestPool(true)
|
||||
|
||||
// DeleteFileHandler - delete a file.
|
||||
func (s *storageRESTServer) DeleteFileHandler(p *DeleteFileHandlerParams) (grid.NoPayload, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -730,12 +687,6 @@ func (s *storageRESTServer) DeleteVersionsHandler(w http.ResponseWriter, r *http
|
||||
encoder.Encode(dErrsResp)
|
||||
}
|
||||
|
||||
var storageRenameDataHandler = grid.NewSingleHandler[*RenameDataHandlerParams, *RenameDataResp](grid.HandlerRenameData, func() *RenameDataHandlerParams {
|
||||
return &RenameDataHandlerParams{}
|
||||
}, func() *RenameDataResp {
|
||||
return &RenameDataResp{}
|
||||
})
|
||||
|
||||
// RenameDataHandler - renames a meta object and data dir to destination.
|
||||
func (s *storageRESTServer) RenameDataHandler(p *RenameDataHandlerParams) (*RenameDataResp, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -749,10 +700,6 @@ func (s *storageRESTServer) RenameDataHandler(p *RenameDataHandlerParams) (*Rena
|
||||
return resp, grid.NewRemoteErr(err)
|
||||
}
|
||||
|
||||
var storageRenameFileHandler = grid.NewSingleHandler[*RenameFileHandlerParams, grid.NoPayload](grid.HandlerRenameFile, func() *RenameFileHandlerParams {
|
||||
return &RenameFileHandlerParams{}
|
||||
}, grid.NewNoPayload).AllowCallRequestPool(true)
|
||||
|
||||
// RenameFileHandler - rename a file from source to destination
|
||||
func (s *storageRESTServer) RenameFileHandler(p *RenameFileHandlerParams) (grid.NoPayload, *grid.RemoteErr) {
|
||||
if !s.checkID(p.DiskID) {
|
||||
@@ -1356,26 +1303,26 @@ func registerStorageRESTHandlers(router *mux.Router, endpointServerPools Endpoin
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodCreateFile).HandlerFunc(h(server.CreateFileHandler))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadFile).HandlerFunc(h(server.ReadFileHandler))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadFileStream).HandlerFunc(h(server.ReadFileStreamHandler))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodListDir).HandlerFunc(h(server.ListDirHandler))
|
||||
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodDeleteVersions).HandlerFunc(h(server.DeleteVersionsHandler))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodVerifyFile).HandlerFunc(h(server.VerifyFileHandler))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodStatInfoFile).HandlerFunc(h(server.StatInfoFile))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadMultiple).HandlerFunc(h(server.ReadMultiple))
|
||||
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodCleanAbandoned).HandlerFunc(h(server.CleanAbandonedDataHandler))
|
||||
logger.FatalIf(storageReadAllHandler.Register(gm, server.ReadAllHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageRenameFileHandler.Register(gm, server.RenameFileHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageRenameDataHandler.Register(gm, server.RenameDataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDeleteFileHandler.Register(gm, server.DeleteFileHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageCheckPartsHandler.Register(gm, server.CheckPartsHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageReadVersionHandler.Register(gm, server.ReadVersionHandlerWS, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageWriteMetadataHandler.Register(gm, server.WriteMetadataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageUpdateMetadataHandler.Register(gm, server.UpdateMetadataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDeleteVersionHandler.Register(gm, server.DeleteVersionHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageReadXLHandler.Register(gm, server.ReadXLHandlerWS, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageNSScannerHandler.RegisterNoInput(gm, server.NSScannerHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDiskInfoHandler.Register(gm, server.DiskInfoHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageStatVolHandler.Register(gm, server.StatVolHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageListDirRPC.RegisterNoInput(gm, server.ListDirHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageReadAllRPC.Register(gm, server.ReadAllHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageRenameFileRPC.Register(gm, server.RenameFileHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageRenameDataRPC.Register(gm, server.RenameDataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDeleteFileRPC.Register(gm, server.DeleteFileHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageCheckPartsRPC.Register(gm, server.CheckPartsHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageReadVersionRPC.Register(gm, server.ReadVersionHandlerWS, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageWriteMetadataRPC.Register(gm, server.WriteMetadataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageUpdateMetadataRPC.Register(gm, server.UpdateMetadataHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDeleteVersionRPC.Register(gm, server.DeleteVersionHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageReadXLRPC.Register(gm, server.ReadXLHandlerWS, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageNSScannerRPC.RegisterNoInput(gm, server.NSScannerHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageDiskInfoRPC.Register(gm, server.DiskInfoHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(storageStatVolRPC.Register(gm, server.StatVolHandler, endpoint.Path), "unable to register handler")
|
||||
logger.FatalIf(gm.RegisterStreamingHandler(grid.HandlerWalkDir, grid.StreamHandler{
|
||||
Subroute: endpoint.Path,
|
||||
Handle: server.WalkDirHandler,
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
|
||||
// writeSTSErrorRespone writes error headers
|
||||
// writeSTSErrorResponse writes error headers
|
||||
func writeSTSErrorResponse(ctx context.Context, w http.ResponseWriter, errCode STSErrorCode, err error) {
|
||||
stsErr := stsErrCodes.ToSTSErr(errCode)
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import (
|
||||
"github.com/minio/madmin-go/v3"
|
||||
)
|
||||
|
||||
//go:generate msgp -file=$GOFILE -unexported
|
||||
|
||||
type lastDayTierStats struct {
|
||||
Bins [24]tierStats
|
||||
UpdatedAt time.Time
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *DailyAllTierStats) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var zb0004 uint32
|
||||
zb0004, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
if (*z) == nil {
|
||||
(*z) = make(DailyAllTierStats, zb0004)
|
||||
} else if len((*z)) > 0 {
|
||||
for key := range *z {
|
||||
delete((*z), key)
|
||||
}
|
||||
}
|
||||
for zb0004 > 0 {
|
||||
zb0004--
|
||||
var zb0001 string
|
||||
var zb0002 lastDayTierStats
|
||||
zb0001, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0005 uint32
|
||||
zb0005, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
for zb0005 > 0 {
|
||||
zb0005--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Bins":
|
||||
var zb0006 uint32
|
||||
zb0006, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "Bins")
|
||||
return
|
||||
}
|
||||
if zb0006 != uint32(24) {
|
||||
err = msgp.ArrayError{Wanted: uint32(24), Got: zb0006}
|
||||
return
|
||||
}
|
||||
for zb0003 := range zb0002.Bins {
|
||||
err = zb0002.Bins[zb0003].DecodeMsg(dc)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "Bins", zb0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
case "UpdatedAt":
|
||||
zb0002.UpdatedAt, err = dc.ReadTime()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
(*z)[zb0001] = zb0002
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z DailyAllTierStats) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteMapHeader(uint32(len(z)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0007, zb0008 := range z {
|
||||
err = en.WriteString(zb0007)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
// map header, size 2
|
||||
// write "Bins"
|
||||
err = en.Append(0x82, 0xa4, 0x42, 0x69, 0x6e, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(24))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0007, "Bins")
|
||||
return
|
||||
}
|
||||
for zb0009 := range zb0008.Bins {
|
||||
err = zb0008.Bins[zb0009].EncodeMsg(en)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0007, "Bins", zb0009)
|
||||
return
|
||||
}
|
||||
}
|
||||
// write "UpdatedAt"
|
||||
err = en.Append(0xa9, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteTime(zb0008.UpdatedAt)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0007, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z DailyAllTierStats) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z)))
|
||||
for zb0007, zb0008 := range z {
|
||||
o = msgp.AppendString(o, zb0007)
|
||||
// map header, size 2
|
||||
// string "Bins"
|
||||
o = append(o, 0x82, 0xa4, 0x42, 0x69, 0x6e, 0x73)
|
||||
o = msgp.AppendArrayHeader(o, uint32(24))
|
||||
for zb0009 := range zb0008.Bins {
|
||||
o, err = zb0008.Bins[zb0009].MarshalMsg(o)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0007, "Bins", zb0009)
|
||||
return
|
||||
}
|
||||
}
|
||||
// string "UpdatedAt"
|
||||
o = append(o, 0xa9, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||
o = msgp.AppendTime(o, zb0008.UpdatedAt)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *DailyAllTierStats) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var zb0004 uint32
|
||||
zb0004, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
if (*z) == nil {
|
||||
(*z) = make(DailyAllTierStats, zb0004)
|
||||
} else if len((*z)) > 0 {
|
||||
for key := range *z {
|
||||
delete((*z), key)
|
||||
}
|
||||
}
|
||||
for zb0004 > 0 {
|
||||
var zb0001 string
|
||||
var zb0002 lastDayTierStats
|
||||
zb0004--
|
||||
zb0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0005 uint32
|
||||
zb0005, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
for zb0005 > 0 {
|
||||
zb0005--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Bins":
|
||||
var zb0006 uint32
|
||||
zb0006, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "Bins")
|
||||
return
|
||||
}
|
||||
if zb0006 != uint32(24) {
|
||||
err = msgp.ArrayError{Wanted: uint32(24), Got: zb0006}
|
||||
return
|
||||
}
|
||||
for zb0003 := range zb0002.Bins {
|
||||
bts, err = zb0002.Bins[zb0003].UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "Bins", zb0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
case "UpdatedAt":
|
||||
zb0002.UpdatedAt, bts, err = msgp.ReadTimeBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, zb0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
(*z)[zb0001] = zb0002
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z DailyAllTierStats) Msgsize() (s int) {
|
||||
s = msgp.MapHeaderSize
|
||||
if z != nil {
|
||||
for zb0007, zb0008 := range z {
|
||||
_ = zb0008
|
||||
s += msgp.StringPrefixSize + len(zb0007) + 1 + 5 + msgp.ArrayHeaderSize
|
||||
for zb0009 := range zb0008.Bins {
|
||||
s += zb0008.Bins[zb0009].Msgsize()
|
||||
}
|
||||
s += 10 + msgp.TimeSize
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *lastDayTierStats) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Bins":
|
||||
var zb0002 uint32
|
||||
zb0002, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins")
|
||||
return
|
||||
}
|
||||
if zb0002 != uint32(24) {
|
||||
err = msgp.ArrayError{Wanted: uint32(24), Got: zb0002}
|
||||
return
|
||||
}
|
||||
for za0001 := range z.Bins {
|
||||
err = z.Bins[za0001].DecodeMsg(dc)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
case "UpdatedAt":
|
||||
z.UpdatedAt, err = dc.ReadTime()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *lastDayTierStats) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 2
|
||||
// write "Bins"
|
||||
err = en.Append(0x82, 0xa4, 0x42, 0x69, 0x6e, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(24))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins")
|
||||
return
|
||||
}
|
||||
for za0001 := range z.Bins {
|
||||
err = z.Bins[za0001].EncodeMsg(en)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
// write "UpdatedAt"
|
||||
err = en.Append(0xa9, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteTime(z.UpdatedAt)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *lastDayTierStats) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "Bins"
|
||||
o = append(o, 0x82, 0xa4, 0x42, 0x69, 0x6e, 0x73)
|
||||
o = msgp.AppendArrayHeader(o, uint32(24))
|
||||
for za0001 := range z.Bins {
|
||||
o, err = z.Bins[za0001].MarshalMsg(o)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
// string "UpdatedAt"
|
||||
o = append(o, 0xa9, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||
o = msgp.AppendTime(o, z.UpdatedAt)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *lastDayTierStats) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "Bins":
|
||||
var zb0002 uint32
|
||||
zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins")
|
||||
return
|
||||
}
|
||||
if zb0002 != uint32(24) {
|
||||
err = msgp.ArrayError{Wanted: uint32(24), Got: zb0002}
|
||||
return
|
||||
}
|
||||
for za0001 := range z.Bins {
|
||||
bts, err = z.Bins[za0001].UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Bins", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
case "UpdatedAt":
|
||||
z.UpdatedAt, bts, err = msgp.ReadTimeBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "UpdatedAt")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *lastDayTierStats) Msgsize() (s int) {
|
||||
s = 1 + 5 + msgp.ArrayHeaderSize
|
||||
for za0001 := range z.Bins {
|
||||
s += z.Bins[za0001].Msgsize()
|
||||
}
|
||||
s += 10 + msgp.TimeSize
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package cmd
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshalDailyAllTierStats(t *testing.T) {
|
||||
v := DailyAllTierStats{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgDailyAllTierStats(b *testing.B) {
|
||||
v := DailyAllTierStats{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgDailyAllTierStats(b *testing.B) {
|
||||
v := DailyAllTierStats{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalDailyAllTierStats(b *testing.B) {
|
||||
v := DailyAllTierStats{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeDailyAllTierStats(t *testing.T) {
|
||||
v := DailyAllTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeDailyAllTierStats Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := DailyAllTierStats{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeDailyAllTierStats(b *testing.B) {
|
||||
v := DailyAllTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeDailyAllTierStats(b *testing.B) {
|
||||
v := DailyAllTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshallastDayTierStats(t *testing.T) {
|
||||
v := lastDayTierStats{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsglastDayTierStats(b *testing.B) {
|
||||
v := lastDayTierStats{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsglastDayTierStats(b *testing.B) {
|
||||
v := lastDayTierStats{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshallastDayTierStats(b *testing.B) {
|
||||
v := lastDayTierStats{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodelastDayTierStats(t *testing.T) {
|
||||
v := lastDayTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodelastDayTierStats Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := lastDayTierStats{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodelastDayTierStats(b *testing.B) {
|
||||
v := lastDayTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodelastDayTierStats(b *testing.B) {
|
||||
v := lastDayTierStats{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -926,91 +926,6 @@ func iamPolicyClaimNameSA() string {
|
||||
return "sa-policy"
|
||||
}
|
||||
|
||||
// timedValue contains a synchronized value that is considered valid
|
||||
// for a specific amount of time.
|
||||
// An Update function must be set to provide an updated value when needed.
|
||||
type timedValue struct {
|
||||
// Update must return an updated value.
|
||||
// If an error is returned the cached value is not set.
|
||||
// Only one caller will call this function at any time, others will be blocking.
|
||||
// The returned value can no longer be modified once returned.
|
||||
// Should be set before calling Get().
|
||||
Update func() (interface{}, error)
|
||||
|
||||
// TTL for a cached value.
|
||||
// If not set 1 second TTL is assumed.
|
||||
// Should be set before calling Get().
|
||||
TTL time.Duration
|
||||
|
||||
// When set to true, return the last cached value
|
||||
// even if updating the value errors out
|
||||
Relax bool
|
||||
|
||||
// Once can be used to initialize values for lazy initialization.
|
||||
// Should be set before calling Get().
|
||||
Once sync.Once
|
||||
|
||||
// Managed values.
|
||||
value interface{}
|
||||
lastUpdate time.Time
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// Get will return a cached value or fetch a new one.
|
||||
// If the Update function returns an error the value is forwarded as is and not cached.
|
||||
func (t *timedValue) Get() (interface{}, error) {
|
||||
v := t.get(t.ttl())
|
||||
if v != nil {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
v, err := t.Update()
|
||||
if err != nil {
|
||||
if t.Relax {
|
||||
// if update fails, return current
|
||||
// cached value along with error.
|
||||
//
|
||||
// Let the caller decide if they want
|
||||
// to use the returned value based
|
||||
// on error.
|
||||
v = t.get(0)
|
||||
return v, err
|
||||
}
|
||||
return v, err
|
||||
}
|
||||
|
||||
t.update(v)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (t *timedValue) ttl() time.Duration {
|
||||
ttl := t.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = time.Second
|
||||
}
|
||||
return ttl
|
||||
}
|
||||
|
||||
func (t *timedValue) get(ttl time.Duration) (v interface{}) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
v = t.value
|
||||
if ttl <= 0 {
|
||||
return v
|
||||
}
|
||||
if time.Since(t.lastUpdate) < ttl {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *timedValue) update(v interface{}) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.value = v
|
||||
t.lastUpdate = time.Now()
|
||||
}
|
||||
|
||||
// On MinIO a directory object is stored as a regular object with "__XLDIR__" suffix.
|
||||
// For ex. "prefix/" is stored as "prefix__XLDIR__"
|
||||
func encodeDirObject(object string) string {
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Tests maximum object size.
|
||||
@@ -400,32 +399,3 @@ func TestGetMinioMode(t *testing.T) {
|
||||
globalIsDistErasure, globalIsErasure = false, false
|
||||
testMinioMode(globalMinioModeFS)
|
||||
}
|
||||
|
||||
func TestTimedValue(t *testing.T) {
|
||||
var cache timedValue
|
||||
t.Parallel()
|
||||
cache.Once.Do(func() {
|
||||
cache.TTL = 2 * time.Second
|
||||
cache.Update = func() (interface{}, error) {
|
||||
return time.Now(), nil
|
||||
}
|
||||
})
|
||||
|
||||
i, _ := cache.Get()
|
||||
t1 := i.(time.Time)
|
||||
|
||||
j, _ := cache.Get()
|
||||
t2 := j.(time.Time)
|
||||
|
||||
if !t1.Equal(t2) {
|
||||
t.Fatalf("expected time to be equal: %s != %s", t1, t2)
|
||||
}
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
k, _ := cache.Get()
|
||||
t3 := k.(time.Time)
|
||||
|
||||
if t1.Equal(t3) {
|
||||
t.Fatalf("expected time to be un-equal: %s == %s", t1, t3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
xioutil "github.com/minio/minio/internal/ioutil"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
@@ -89,7 +90,7 @@ type xlStorageDiskIDCheck struct {
|
||||
health *diskHealthTracker
|
||||
healthCheck bool
|
||||
|
||||
metricsCache timedValue
|
||||
metricsCache *cachevalue.Cache[DiskMetrics]
|
||||
diskCtx context.Context
|
||||
diskCancel context.CancelFunc
|
||||
}
|
||||
@@ -97,7 +98,7 @@ type xlStorageDiskIDCheck struct {
|
||||
func (p *xlStorageDiskIDCheck) getMetrics() DiskMetrics {
|
||||
p.metricsCache.Once.Do(func() {
|
||||
p.metricsCache.TTL = 5 * time.Second
|
||||
p.metricsCache.Update = func() (interface{}, error) {
|
||||
p.metricsCache.Update = func() (DiskMetrics, error) {
|
||||
diskMetric := DiskMetrics{
|
||||
LastMinute: make(map[string]AccElem, len(p.apiLatencies)),
|
||||
APICalls: make(map[string]uint64, len(p.apiCalls)),
|
||||
@@ -111,12 +112,8 @@ func (p *xlStorageDiskIDCheck) getMetrics() DiskMetrics {
|
||||
return diskMetric, nil
|
||||
}
|
||||
})
|
||||
m, _ := p.metricsCache.Get()
|
||||
diskMetric := DiskMetrics{}
|
||||
if m != nil {
|
||||
diskMetric = m.(DiskMetrics)
|
||||
}
|
||||
|
||||
diskMetric, _ := p.metricsCache.Get()
|
||||
// Do not need this value to be cached.
|
||||
diskMetric.TotalErrorsTimeout = p.totalErrsTimeout.Load()
|
||||
diskMetric.TotalErrorsAvailability = p.totalErrsAvailability.Load()
|
||||
@@ -180,9 +177,10 @@ func (e *lockedLastMinuteLatency) total() AccElem {
|
||||
|
||||
func newXLStorageDiskIDCheck(storage *xlStorage, healthCheck bool) *xlStorageDiskIDCheck {
|
||||
xl := xlStorageDiskIDCheck{
|
||||
storage: storage,
|
||||
health: newDiskHealthTracker(),
|
||||
healthCheck: healthCheck && globalDriveMonitoring,
|
||||
storage: storage,
|
||||
health: newDiskHealthTracker(),
|
||||
healthCheck: healthCheck && globalDriveMonitoring,
|
||||
metricsCache: cachevalue.New[DiskMetrics](),
|
||||
}
|
||||
|
||||
xl.totalWrites.Store(xl.storage.getWriteAttribute())
|
||||
|
||||
@@ -147,7 +147,7 @@ func getSampleXLMeta(totalParts int) xlMetaV1Object {
|
||||
|
||||
// Compare the unmarshaled XLMetaV1 with the one obtained from jsoniter parsing.
|
||||
func compareXLMetaV1(t *testing.T, unMarshalXLMeta, jsoniterXLMeta xlMetaV1Object) {
|
||||
// Start comparing the fields of xlMetaV1Object obtained from jsoniter parsing with one parsed using json unmarshaling.
|
||||
// Start comparing the fields of xlMetaV1Object obtained from jsoniter parsing with one parsed using json unmarshalling.
|
||||
if unMarshalXLMeta.Version != jsoniterXLMeta.Version {
|
||||
t.Errorf("Expected the Version to be \"%s\", but got \"%s\".", unMarshalXLMeta.Version, jsoniterXLMeta.Version)
|
||||
}
|
||||
|
||||
+54
-62
@@ -43,6 +43,7 @@ import (
|
||||
"github.com/klauspost/filepathx"
|
||||
"github.com/minio/madmin-go/v3"
|
||||
"github.com/minio/minio/internal/bucket/lifecycle"
|
||||
"github.com/minio/minio/internal/cachevalue"
|
||||
"github.com/minio/minio/internal/config/storageclass"
|
||||
"github.com/minio/minio/internal/disk"
|
||||
xioutil "github.com/minio/minio/internal/ioutil"
|
||||
@@ -112,7 +113,7 @@ type xlStorage struct {
|
||||
formatLegacy bool
|
||||
formatLastCheck time.Time
|
||||
|
||||
diskInfoCache timedValue
|
||||
diskInfoCache *cachevalue.Cache[DiskInfo]
|
||||
sync.RWMutex
|
||||
|
||||
formatData []byte
|
||||
@@ -230,12 +231,13 @@ func makeFormatErasureMetaVolumes(disk StorageAPI) error {
|
||||
// Initialize a new storage disk.
|
||||
func newXLStorage(ep Endpoint, cleanUp bool) (s *xlStorage, err error) {
|
||||
s = &xlStorage{
|
||||
drivePath: ep.Path,
|
||||
endpoint: ep,
|
||||
globalSync: globalFSOSync,
|
||||
poolIndex: -1,
|
||||
setIndex: -1,
|
||||
diskIndex: -1,
|
||||
drivePath: ep.Path,
|
||||
endpoint: ep,
|
||||
globalSync: globalFSOSync,
|
||||
diskInfoCache: cachevalue.New[DiskInfo](),
|
||||
poolIndex: -1,
|
||||
setIndex: -1,
|
||||
diskIndex: -1,
|
||||
}
|
||||
|
||||
s.drivePath, err = getValidPath(ep.Path)
|
||||
@@ -732,7 +734,7 @@ func (s *xlStorage) setWriteAttribute(writeCount uint64) error {
|
||||
func (s *xlStorage) DiskInfo(_ context.Context, _ DiskInfoOptions) (info DiskInfo, err error) {
|
||||
s.diskInfoCache.Once.Do(func() {
|
||||
s.diskInfoCache.TTL = time.Second
|
||||
s.diskInfoCache.Update = func() (interface{}, error) {
|
||||
s.diskInfoCache.Update = func() (DiskInfo, error) {
|
||||
dcinfo := DiskInfo{}
|
||||
di, err := getDiskInfo(s.drivePath)
|
||||
if err != nil {
|
||||
@@ -758,11 +760,7 @@ func (s *xlStorage) DiskInfo(_ context.Context, _ DiskInfoOptions) (info DiskInf
|
||||
}
|
||||
})
|
||||
|
||||
v, err := s.diskInfoCache.Get()
|
||||
if v != nil {
|
||||
info = v.(DiskInfo)
|
||||
}
|
||||
|
||||
info, err = s.diskInfoCache.Get()
|
||||
info.MountPath = s.drivePath
|
||||
info.Endpoint = s.endpoint.String()
|
||||
info.Scanning = atomic.LoadInt32(&s.scanning) == 1
|
||||
@@ -1186,7 +1184,7 @@ func (s *xlStorage) moveToTrash(filePath string, recursive, immediatePurge bool)
|
||||
}
|
||||
|
||||
// ENOSPC is a valid error from rename(); remove instead of rename in that case
|
||||
if err == errDiskFull {
|
||||
if errors.Is(err, errDiskFull) || isSysErrNoSpace(err) {
|
||||
if recursive {
|
||||
err = removeAll(filePath)
|
||||
} else {
|
||||
@@ -1702,7 +1700,7 @@ func (s *xlStorage) readAllData(ctx context.Context, volume, volumeDir string, f
|
||||
}
|
||||
|
||||
if discard {
|
||||
// This discard is mostly true for DELETEs
|
||||
// This discard is mostly true for DELETEEs
|
||||
// so we need to make sure we do not keep
|
||||
// page-cache references after.
|
||||
defer disk.Fdatasync(f)
|
||||
@@ -2617,67 +2615,53 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
|
||||
defer metaDataPoolPut(dstBuf)
|
||||
if err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
return 0, errFileCorrupt
|
||||
}
|
||||
|
||||
if srcDataPath != "" {
|
||||
if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
return 0, osErrToFileErr(err)
|
||||
if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil {
|
||||
if legacyPreserved {
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
diskHealthCheckOK(ctx, err)
|
||||
return 0, osErrToFileErr(err)
|
||||
}
|
||||
diskHealthCheckOK(ctx, err)
|
||||
|
||||
if srcDataPath != "" && len(fi.Data) == 0 && fi.Size > 0 {
|
||||
// renameAll only for objects that have xl.meta not saved inline.
|
||||
if len(fi.Data) == 0 && fi.Size > 0 {
|
||||
s.moveToTrash(dstDataPath, true, false)
|
||||
if healing {
|
||||
// If we are healing we should purge any legacyDataPath content,
|
||||
// that was previously preserved during PutObject() call
|
||||
// on a versioned bucket.
|
||||
s.moveToTrash(legacyDataPath, true, false)
|
||||
}
|
||||
if err = renameAll(srcDataPath, dstDataPath, dstVolumeDir); err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
s.deleteFile(dstVolumeDir, dstDataPath, false, false)
|
||||
return 0, osErrToFileErr(err)
|
||||
}
|
||||
s.moveToTrash(dstDataPath, true, false)
|
||||
if healing {
|
||||
// If we are healing we should purge any legacyDataPath content,
|
||||
// that was previously preserved during PutObject() call
|
||||
// on a versioned bucket.
|
||||
s.moveToTrash(legacyDataPath, true, false)
|
||||
}
|
||||
|
||||
// Commit meta-file
|
||||
if err = renameAll(srcFilePath, dstFilePath, dstVolumeDir); err != nil {
|
||||
if err = renameAll(srcDataPath, dstDataPath, dstVolumeDir); err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
s.deleteFile(dstVolumeDir, dstFilePath, false, false)
|
||||
s.deleteFile(dstVolumeDir, dstDataPath, false, false)
|
||||
return 0, osErrToFileErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
// additionally only purge older data at the end of the transaction of new data-dir
|
||||
// movement, this is to ensure that previous data references can co-exist for
|
||||
// any recoverability.
|
||||
if oldDstDataPath != "" {
|
||||
s.moveToTrash(oldDstDataPath, true, false)
|
||||
}
|
||||
} else {
|
||||
// Write meta-file directly, no data
|
||||
if err = s.WriteAll(ctx, dstVolume, pathJoin(dstPath, xlStorageFormatFile), dstBuf); err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
s.deleteFile(dstVolumeDir, dstFilePath, false, false)
|
||||
return 0, err
|
||||
// Commit meta-file
|
||||
if err = renameAll(srcFilePath, dstFilePath, dstVolumeDir); err != nil {
|
||||
if legacyPreserved {
|
||||
// Any failed rename calls un-roll previous transaction.
|
||||
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
|
||||
}
|
||||
s.deleteFile(dstVolumeDir, dstDataPath, false, false)
|
||||
return 0, osErrToFileErr(err)
|
||||
}
|
||||
|
||||
// additionally only purge older data at the end of the transaction of new data-dir
|
||||
// movement, this is to ensure that previous data references can co-exist for
|
||||
// any recoverability.
|
||||
if oldDstDataPath != "" {
|
||||
s.moveToTrash(oldDstDataPath, true, false)
|
||||
}
|
||||
|
||||
if srcVolume != minioMetaMultipartBucket {
|
||||
@@ -2883,14 +2867,22 @@ func (s *xlStorage) ReadMultiple(ctx context.Context, req ReadMultipleReq, resp
|
||||
if req.MaxSize > 0 && int64(len(data)) > req.MaxSize {
|
||||
r.Exists = true
|
||||
r.Error = fmt.Sprintf("max size (%d) exceeded: %d", req.MaxSize, len(data))
|
||||
resp <- r
|
||||
continue
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case resp <- r:
|
||||
continue
|
||||
}
|
||||
}
|
||||
found++
|
||||
r.Exists = true
|
||||
r.Data = data
|
||||
r.Modtime = mt
|
||||
resp <- r
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case resp <- r:
|
||||
}
|
||||
if req.MaxResults > 0 && found >= req.MaxResults {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -67,14 +67,13 @@ scrape_configs:
|
||||
|
||||
##### Bucket centric
|
||||
|
||||
```
|
||||
```yaml
|
||||
- job_name: minio-job-bucket
|
||||
bearer_token: <secret>
|
||||
metrics_path: /minio/v2/metrics/bucket
|
||||
scheme: http
|
||||
static_configs:
|
||||
- targets: ['localhost:9000']
|
||||
|
||||
```
|
||||
|
||||
#### 3.2 Public Prometheus config
|
||||
|
||||
@@ -2205,6 +2205,926 @@
|
||||
],
|
||||
"title": "Replication Latency (millis)",
|
||||
"type": "bargauge"
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 42
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 76,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "sum by (bucket) (minio_bucket_replication_proxied_head_requests_total{job=\"$scrape_jobs\"})",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{bucket}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Head Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 42
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 77,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_bucket_replication_proxied_head_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Head Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 42
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 78,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "sum by (bucket) (minio_bucket_replication_proxied_put_tagging_requests_total{job=\"$scrape_jobs\"})",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{bucket}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Put Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 42
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 79,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_bucket_replication_proxied_put_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Put Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 48
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 80,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "sum by (bucket) (minio_bucket_replication_proxied_get_tagging_requests_total{job=\"$scrape_jobs\"})",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{bucket}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Get Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 48
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 81,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_bucket_replication_proxied_get_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Get Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 48
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 82,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "sum by (bucket) (minio_bucket_replication_proxied_delete_tagging_requests_total{job=\"$scrape_jobs\"})",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{bucket}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Delete Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 48
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 83,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_bucket_replication_proxied_delete_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Delete Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 54
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 84,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "sum by (bucket) (minio_bucket_replication_proxied_get_requests_total{job=\"$scrape_jobs\"})",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{bucket}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Get Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 54
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 85,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_bucket_replication_proxied_get_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Get Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
|
||||
@@ -1812,6 +1812,926 @@
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 24
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 75,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_head_requests_total{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Head Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 30
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 76,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_head_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Head Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 30
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 77,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_put_tagging_requests_total{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Put Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 30
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 78,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_put_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Put Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 30
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 79,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_get_tagging_requests_total{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Get Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 36
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 80,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_get_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Get Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 36
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 81,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_delete_tagging_requests_total{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Delete Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 12,
|
||||
"y": 36
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 82,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_delete_tagging_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Delete Tag Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 18,
|
||||
"y": 36
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 83,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_get_requests_total{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Proxied Get Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"Replication Errors": "light-red",
|
||||
"Replication Requests": "light-green"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 6,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 42
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 84,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"alertThreshold": true
|
||||
},
|
||||
"percentage": false,
|
||||
"pluginVersion": "10.0.2",
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "prometheus",
|
||||
"uid": "${DS_PROMETHEUS}"
|
||||
},
|
||||
"exemplar": true,
|
||||
"expr": "minio_cluster_replication_proxied_get_requests_failures{job=\"$scrape_jobs\"}",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{instance}}",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeRegions": [],
|
||||
"title": "Total Failed Proxied Get Requests",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 2,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"mode": "time",
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"$$hashKey": "object:331",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"$$hashKey": "object:332",
|
||||
"format": "short",
|
||||
"logBase": 1,
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3.7'
|
||||
|
||||
# Settings and configurations that are common for all containers
|
||||
x-minio-common: &minio-common
|
||||
image: quay.io/minio/minio:RELEASE.2024-02-14T21-36-02Z
|
||||
image: quay.io/minio/minio:RELEASE.2024-02-24T17-11-14Z
|
||||
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
|
||||
expose:
|
||||
- "9000"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package bandwidth
|
||||
|
||||
//go:generate msgp -file=$GOFILE -unexported
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
@@ -25,6 +27,8 @@ import (
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
//msgp:ignore bucketThrottle Monitor
|
||||
|
||||
type bucketThrottle struct {
|
||||
*rate.Limiter
|
||||
NodeBandwidthPerSec int64
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
package bandwidth
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *BucketBandwidthReport) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z BucketBandwidthReport) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 0
|
||||
err = en.Append(0x80)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z BucketBandwidthReport) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 0
|
||||
o = append(o, 0x80)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *BucketBandwidthReport) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z BucketBandwidthReport) Msgsize() (s int) {
|
||||
s = 1
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *Details) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "LimitInBytesPerSecond":
|
||||
z.LimitInBytesPerSecond, err = dc.ReadInt64()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "LimitInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
case "CurrentBandwidthInBytesPerSecond":
|
||||
z.CurrentBandwidthInBytesPerSecond, err = dc.ReadFloat64()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "CurrentBandwidthInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z Details) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 2
|
||||
// write "LimitInBytesPerSecond"
|
||||
err = en.Append(0x82, 0xb5, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt64(z.LimitInBytesPerSecond)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "LimitInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
// write "CurrentBandwidthInBytesPerSecond"
|
||||
err = en.Append(0xd9, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteFloat64(z.CurrentBandwidthInBytesPerSecond)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "CurrentBandwidthInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z Details) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 2
|
||||
// string "LimitInBytesPerSecond"
|
||||
o = append(o, 0x82, 0xb5, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64)
|
||||
o = msgp.AppendInt64(o, z.LimitInBytesPerSecond)
|
||||
// string "CurrentBandwidthInBytesPerSecond"
|
||||
o = append(o, 0xd9, 0x20, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64)
|
||||
o = msgp.AppendFloat64(o, z.CurrentBandwidthInBytesPerSecond)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Details) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "LimitInBytesPerSecond":
|
||||
z.LimitInBytesPerSecond, bts, err = msgp.ReadInt64Bytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "LimitInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
case "CurrentBandwidthInBytesPerSecond":
|
||||
z.CurrentBandwidthInBytesPerSecond, bts, err = msgp.ReadFloat64Bytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "CurrentBandwidthInBytesPerSecond")
|
||||
return
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z Details) Msgsize() (s int) {
|
||||
s = 1 + 22 + msgp.Int64Size + 34 + msgp.Float64Size
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package bandwidth
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshalBucketBandwidthReport(t *testing.T) {
|
||||
v := BucketBandwidthReport{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgBucketBandwidthReport(b *testing.B) {
|
||||
v := BucketBandwidthReport{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgBucketBandwidthReport(b *testing.B) {
|
||||
v := BucketBandwidthReport{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalBucketBandwidthReport(b *testing.B) {
|
||||
v := BucketBandwidthReport{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeBucketBandwidthReport(t *testing.T) {
|
||||
v := BucketBandwidthReport{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeBucketBandwidthReport Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := BucketBandwidthReport{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeBucketBandwidthReport(b *testing.B) {
|
||||
v := BucketBandwidthReport{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeBucketBandwidthReport(b *testing.B) {
|
||||
v := BucketBandwidthReport{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalDetails(t *testing.T) {
|
||||
v := Details{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgDetails(b *testing.B) {
|
||||
v := Details{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgDetails(b *testing.B) {
|
||||
v := Details{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalDetails(b *testing.B) {
|
||||
v := Details{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeDetails(t *testing.T) {
|
||||
v := Details{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeDetails Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := Details{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeDetails(b *testing.B) {
|
||||
v := Details{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeDetails(b *testing.B) {
|
||||
v := Details{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ var (
|
||||
errLifecycleInvalidExpiration = Errorf("Exactly one of Days (positive integer) or Date (positive ISO 8601 format) should be present inside Expiration.")
|
||||
errLifecycleInvalidDeleteMarker = Errorf("Delete marker cannot be specified with Days or Date in a Lifecycle Expiration Policy")
|
||||
errLifecycleDateNotMidnight = Errorf("'Date' must be at midnight GMT")
|
||||
errLifecycleInvalidDeleteAll = Errorf("Days (positive integer) should be present inside Expiration with ExpiredObjectAllVersions.")
|
||||
)
|
||||
|
||||
// ExpirationDays is a type alias to unmarshal Days in Expiration
|
||||
@@ -186,6 +187,11 @@ func (e Expiration) Validate() error {
|
||||
return errLifecycleInvalidExpiration
|
||||
}
|
||||
|
||||
// DeleteAll set without expiration days
|
||||
if e.DeleteAll.set && e.IsDaysNull() {
|
||||
return errLifecycleInvalidDeleteAll
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ func TestInvalidExpiration(t *testing.T) {
|
||||
<Date>2019-04-20T00:00:00Z</Date>
|
||||
<ExpiredObjectAllVersions>true</ExpiredObjectAllVersions>
|
||||
</Expiration>`,
|
||||
expectedErr: nil,
|
||||
expectedErr: errLifecycleInvalidDeleteAll,
|
||||
},
|
||||
}
|
||||
for i, tc := range validationTestCases {
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestParseLegalHoldStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestUnmarshalDefaultRetention checks if default retention
|
||||
// marshaling and unmarshaling work as expected
|
||||
// marshaling and unmarshalling work as expected
|
||||
func TestUnmarshalDefaultRetention(t *testing.T) {
|
||||
days := uint64(4)
|
||||
years := uint64(1)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2015-2024 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cachevalue
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cache contains a synchronized value that is considered valid
|
||||
// for a specific amount of time.
|
||||
// An Update function must be set to provide an updated value when needed.
|
||||
type Cache[I any] struct {
|
||||
// Update must return an updated value.
|
||||
// If an error is returned the cached value is not set.
|
||||
// Only one caller will call this function at any time, others will be blocking.
|
||||
// The returned value can no longer be modified once returned.
|
||||
// Should be set before calling Get().
|
||||
Update func() (item I, err error)
|
||||
|
||||
// TTL for a cached value.
|
||||
// If not set 1 second TTL is assumed.
|
||||
// Should be set before calling Get().
|
||||
TTL time.Duration
|
||||
|
||||
// When set to true, return the last cached value
|
||||
// even if updating the value errors out
|
||||
Relax bool
|
||||
|
||||
// Once can be used to initialize values for lazy initialization.
|
||||
// Should be set before calling Get().
|
||||
Once sync.Once
|
||||
|
||||
// Managed values.
|
||||
value I // our cached value
|
||||
valueSet bool // 'true' if the value 'I' has a value
|
||||
lastUpdate time.Time // indicates when value 'I' was updated last, used for invalidation.
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// New initializes a new cached value instance.
|
||||
func New[I any]() *Cache[I] {
|
||||
return &Cache[I]{}
|
||||
}
|
||||
|
||||
// Get will return a cached value or fetch a new one.
|
||||
// If the Update function returns an error the value is forwarded as is and not cached.
|
||||
func (t *Cache[I]) Get() (item I, err error) {
|
||||
item, ok := t.get(t.ttl())
|
||||
if ok {
|
||||
return item, nil
|
||||
}
|
||||
|
||||
item, err = t.Update()
|
||||
if err != nil {
|
||||
if t.Relax {
|
||||
// if update fails, return current
|
||||
// cached value along with error.
|
||||
//
|
||||
// Let the caller decide if they want
|
||||
// to use the returned value based
|
||||
// on error.
|
||||
item, ok = t.get(0)
|
||||
if ok {
|
||||
return item, err
|
||||
}
|
||||
}
|
||||
return item, err
|
||||
}
|
||||
|
||||
t.update(item)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (t *Cache[_]) ttl() time.Duration {
|
||||
ttl := t.TTL
|
||||
if ttl <= 0 {
|
||||
ttl = time.Second
|
||||
}
|
||||
return ttl
|
||||
}
|
||||
|
||||
func (t *Cache[I]) get(ttl time.Duration) (item I, ok bool) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
if t.valueSet {
|
||||
item = t.value
|
||||
if ttl <= 0 {
|
||||
return item, true
|
||||
}
|
||||
if time.Since(t.lastUpdate) < ttl {
|
||||
return item, true
|
||||
}
|
||||
}
|
||||
return item, false
|
||||
}
|
||||
|
||||
func (t *Cache[I]) update(item I) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.value = item
|
||||
t.valueSet = true
|
||||
t.lastUpdate = time.Now()
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2015-2024 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cachevalue
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
cache := New[time.Time]()
|
||||
t.Parallel()
|
||||
cache.Once.Do(func() {
|
||||
cache.TTL = 2 * time.Second
|
||||
cache.Update = func() (time.Time, error) {
|
||||
return time.Now(), nil
|
||||
}
|
||||
})
|
||||
|
||||
t1, _ := cache.Get()
|
||||
|
||||
t2, _ := cache.Get()
|
||||
|
||||
if !t1.Equal(t2) {
|
||||
t.Fatalf("expected time to be equal: %s != %s", t1, t2)
|
||||
}
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
t3, _ := cache.Get()
|
||||
|
||||
if t1.Equal(t3) {
|
||||
t.Fatalf("expected time to be un-equal: %s == %s", t1, t3)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCache(b *testing.B) {
|
||||
cache := New[time.Time]()
|
||||
cache.Once.Do(func() {
|
||||
cache.TTL = 1 * time.Microsecond
|
||||
cache.Update = func() (time.Time, error) {
|
||||
return time.Now(), nil
|
||||
}
|
||||
})
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
cache.Get()
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -159,7 +159,7 @@ var NotifySubSystems = set.CreateStringSet(
|
||||
NotifyWebhookSubSys,
|
||||
)
|
||||
|
||||
// LambdaSubSystems - all lambda sub-systesm
|
||||
// LambdaSubSystems - all lambda sub-systems
|
||||
var LambdaSubSystems = set.CreateStringSet(
|
||||
LambdaWebhookSubSys,
|
||||
)
|
||||
|
||||
@@ -299,7 +299,7 @@ func checkValidNotificationKeysForSubSys(subSys string, tgt map[string]config.KV
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultKakfaKVS - default KV for kafka target
|
||||
// DefaultKafkaKVS - default KV for kafka target
|
||||
var (
|
||||
DefaultKafkaKVS = config.KVS{
|
||||
config.KV{
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
// RemoveSensitiveHeaders removes confidential encryption
|
||||
// information - e.g. the SSE-C key - from the HTTP headers.
|
||||
// It has the same semantics as RemoveSensitiveEntires.
|
||||
// It has the same semantics as RemoveSensitiveEntries.
|
||||
func RemoveSensitiveHeaders(h http.Header) {
|
||||
h.Del(xhttp.AmzServerSideEncryptionCustomerKey)
|
||||
h.Del(xhttp.AmzServerSideEncryptionCopyCustomerKey)
|
||||
|
||||
@@ -254,7 +254,7 @@ func (dm *DRWMutex) lockBlocking(ctx context.Context, lockLossCallback func(), i
|
||||
log("lockBlocking %s/%s for %#v: granted\n", id, source, dm.Names)
|
||||
|
||||
// Refresh lock continuously and cancel if there is no quorum in the lock anymore
|
||||
dm.startContinousLockRefresh(lockLossCallback, id, source, quorum)
|
||||
dm.startContinuousLockRefresh(lockLossCallback, id, source, quorum)
|
||||
|
||||
return locked
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (dm *DRWMutex) lockBlocking(ctx context.Context, lockLossCallback func(), i
|
||||
}
|
||||
}
|
||||
|
||||
func (dm *DRWMutex) startContinousLockRefresh(lockLossCallback func(), id, source string, quorum int) {
|
||||
func (dm *DRWMutex) startContinuousLockRefresh(lockLossCallback func(), id, source string, quorum int) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
dm.m.Lock()
|
||||
|
||||
@@ -24,12 +24,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/internal/event"
|
||||
@@ -154,15 +152,15 @@ func (k KafkaArgs) Validate() error {
|
||||
type KafkaTarget struct {
|
||||
initOnce once.Init
|
||||
|
||||
id event.TargetID
|
||||
args KafkaArgs
|
||||
producer sarama.SyncProducer
|
||||
config *sarama.Config
|
||||
store store.Store[event.Event]
|
||||
batch *store.Batch[string, *sarama.ProducerMessage]
|
||||
loggerOnce logger.LogOnce
|
||||
brokerConns map[string]net.Conn
|
||||
quitCh chan struct{}
|
||||
id event.TargetID
|
||||
args KafkaArgs
|
||||
client sarama.Client
|
||||
producer sarama.SyncProducer
|
||||
config *sarama.Config
|
||||
store store.Store[event.Event]
|
||||
batch *store.Batch[string, *sarama.ProducerMessage]
|
||||
loggerOnce logger.LogOnce
|
||||
quitCh chan struct{}
|
||||
}
|
||||
|
||||
// ID - returns target ID.
|
||||
@@ -189,7 +187,9 @@ func (target *KafkaTarget) IsActive() (bool, error) {
|
||||
}
|
||||
|
||||
func (target *KafkaTarget) isActive() (bool, error) {
|
||||
if err := target.pingBrokers(); err != nil {
|
||||
// Refer https://github.com/IBM/sarama/issues/1341
|
||||
brokers := target.client.Brokers()
|
||||
if len(brokers) == 0 {
|
||||
return false, store.ErrNotConnected
|
||||
}
|
||||
return true, nil
|
||||
@@ -317,56 +317,15 @@ func (target *KafkaTarget) toProducerMessage(eventData event.Event) (*sarama.Pro
|
||||
// Close - closes underneath kafka connection.
|
||||
func (target *KafkaTarget) Close() error {
|
||||
close(target.quitCh)
|
||||
|
||||
if target.producer != nil {
|
||||
return target.producer.Close()
|
||||
}
|
||||
for _, conn := range target.brokerConns {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
target.producer.Close()
|
||||
return target.client.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if at least one broker in cluster is active
|
||||
func (target *KafkaTarget) pingBrokers() (err error) {
|
||||
d := net.Dialer{Timeout: 1 * time.Second}
|
||||
|
||||
errs := make([]error, len(target.args.Brokers))
|
||||
var wg sync.WaitGroup
|
||||
for idx, broker := range target.args.Brokers {
|
||||
broker := broker
|
||||
idx := idx
|
||||
wg.Add(1)
|
||||
go func(broker xnet.Host, idx int) {
|
||||
defer wg.Done()
|
||||
conn, ok := target.brokerConns[broker.String()]
|
||||
if !ok || conn == nil {
|
||||
conn, errs[idx] = d.Dial("tcp", broker.String())
|
||||
if errs[idx] != nil {
|
||||
return
|
||||
}
|
||||
target.brokerConns[broker.String()] = conn
|
||||
}
|
||||
if _, errs[idx] = conn.Write([]byte("")); errs[idx] != nil {
|
||||
conn.Close()
|
||||
target.brokerConns[broker.String()] = nil
|
||||
}
|
||||
}(broker, idx)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
var retErr error
|
||||
for _, err := range errs {
|
||||
if err == nil {
|
||||
// if one of them is active we are good.
|
||||
return nil
|
||||
}
|
||||
retErr = err
|
||||
}
|
||||
return retErr
|
||||
}
|
||||
|
||||
func (target *KafkaTarget) init() error {
|
||||
return target.initOnce.Do(target.initKafka)
|
||||
}
|
||||
@@ -431,13 +390,22 @@ func (target *KafkaTarget) initKafka() error {
|
||||
brokers = append(brokers, broker.String())
|
||||
}
|
||||
|
||||
producer, err := sarama.NewSyncProducer(brokers, config)
|
||||
client, err := sarama.NewClient(brokers, config)
|
||||
if err != nil {
|
||||
if err != sarama.ErrOutOfBrokers {
|
||||
if !errors.Is(err, sarama.ErrOutOfBrokers) {
|
||||
target.loggerOnce(context.Background(), err, target.ID().String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
producer, err := sarama.NewSyncProducerFromClient(client)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sarama.ErrOutOfBrokers) {
|
||||
target.loggerOnce(context.Background(), err, target.ID().String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
target.client = client
|
||||
target.producer = producer
|
||||
|
||||
yes, err := target.isActive()
|
||||
@@ -463,12 +431,11 @@ func NewKafkaTarget(id string, args KafkaArgs, loggerOnce logger.LogOnce) (*Kafk
|
||||
}
|
||||
|
||||
target := &KafkaTarget{
|
||||
id: event.TargetID{ID: id, Name: "kafka"},
|
||||
args: args,
|
||||
store: queueStore,
|
||||
loggerOnce: loggerOnce,
|
||||
quitCh: make(chan struct{}),
|
||||
brokerConns: make(map[string]net.Conn, len(args.Brokers)),
|
||||
id: event.TargetID{ID: id, Name: "kafka"},
|
||||
args: args,
|
||||
store: queueStore,
|
||||
loggerOnce: loggerOnce,
|
||||
quitCh: make(chan struct{}),
|
||||
}
|
||||
|
||||
if target.store != nil {
|
||||
|
||||
@@ -531,10 +531,11 @@ func (c *Connection) shouldConnect() bool {
|
||||
return h0 < h1
|
||||
}
|
||||
|
||||
func (c *Connection) send(msg []byte) error {
|
||||
func (c *Connection) send(ctx context.Context, msg []byte) error {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return context.Cause(c.ctx)
|
||||
case <-ctx.Done():
|
||||
// Returning error here is too noisy.
|
||||
return nil
|
||||
case c.outQueue <- msg:
|
||||
return nil
|
||||
}
|
||||
@@ -570,7 +571,7 @@ func (c *Connection) queueMsg(msg message, payload sender) error {
|
||||
h := xxh3.Hash(dst)
|
||||
dst = binary.LittleEndian.AppendUint32(dst, uint32(h))
|
||||
}
|
||||
return c.send(dst)
|
||||
return c.send(c.ctx, dst)
|
||||
}
|
||||
|
||||
// sendMsg will send
|
||||
|
||||
@@ -184,12 +184,12 @@ func (m *lockedClientMap) Delete(id uint64) {
|
||||
|
||||
func (m *lockedClientMap) Range(fn func(key uint64, value *muxClient) bool) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for k, v := range m.m {
|
||||
if !fn(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
func (m *lockedClientMap) Clear() {
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
// HandlerID is a handler identifier.
|
||||
// It is used to determine request routing on the server.
|
||||
// Handlers can be registered with a static subroute.
|
||||
// Do NOT remove or change the order of existing handlers.
|
||||
const (
|
||||
// handlerInvalid is reserved to check for uninitialized values.
|
||||
handlerInvalid HandlerID = iota
|
||||
@@ -69,7 +70,6 @@ const (
|
||||
HandlerStopRebalance
|
||||
HandlerLoadRebalanceMeta
|
||||
HandlerLoadTransitionTierConfig
|
||||
|
||||
HandlerDeletePolicy
|
||||
HandlerLoadPolicy
|
||||
HandlerLoadPolicyMapping
|
||||
@@ -78,11 +78,37 @@ const (
|
||||
HandlerDeleteUser
|
||||
HandlerLoadUser
|
||||
HandlerLoadGroup
|
||||
|
||||
HandlerHealBucket
|
||||
HandlerMakeBucket
|
||||
HandlerHeadBucket
|
||||
HandlerDeleteBucket
|
||||
HandlerGetMetrics
|
||||
HandlerGetResourceMetrics
|
||||
HandlerGetMemInfo
|
||||
HandlerGetProcInfo
|
||||
HandlerGetOSInfo
|
||||
HandlerGetPartitions
|
||||
HandlerGetNetInfo
|
||||
HandlerGetCPUs
|
||||
HandlerServerInfo
|
||||
HandlerGetSysConfig
|
||||
HandlerGetSysServices
|
||||
HandlerGetSysErrors
|
||||
HandlerGetAllBucketStats
|
||||
HandlerGetBucketStats
|
||||
HandlerGetSRMetrics
|
||||
HandlerGetPeerMetrics
|
||||
HandlerGetMetacacheListing
|
||||
HandlerUpdateMetacacheListing
|
||||
HandlerGetPeerBucketMetrics
|
||||
HandlerStorageInfo
|
||||
HandlerConsoleLog
|
||||
HandlerListDir
|
||||
HandlerGetLocks
|
||||
HandlerBackgroundHealStatus
|
||||
HandlerGetLastDayTierStats
|
||||
HandlerSignalService
|
||||
HandlerGetBandwidth
|
||||
|
||||
// Add more above here ^^^
|
||||
// If all handlers are used, the type of Handler can be changed.
|
||||
@@ -137,6 +163,28 @@ var handlerPrefixes = [handlerLast]string{
|
||||
HandlerHeadBucket: peerPrefixS3,
|
||||
HandlerDeleteBucket: peerPrefixS3,
|
||||
HandlerHealBucket: healPrefix,
|
||||
HandlerGetMetrics: peerPrefix,
|
||||
HandlerGetResourceMetrics: peerPrefix,
|
||||
HandlerGetMemInfo: peerPrefix,
|
||||
HandlerGetProcInfo: peerPrefix,
|
||||
HandlerGetOSInfo: peerPrefix,
|
||||
HandlerGetPartitions: peerPrefix,
|
||||
HandlerGetNetInfo: peerPrefix,
|
||||
HandlerGetCPUs: peerPrefix,
|
||||
HandlerServerInfo: peerPrefix,
|
||||
HandlerGetSysConfig: peerPrefix,
|
||||
HandlerGetSysServices: peerPrefix,
|
||||
HandlerGetSysErrors: peerPrefix,
|
||||
HandlerGetAllBucketStats: peerPrefix,
|
||||
HandlerGetBucketStats: peerPrefix,
|
||||
HandlerGetSRMetrics: peerPrefix,
|
||||
HandlerGetPeerMetrics: peerPrefix,
|
||||
HandlerGetMetacacheListing: peerPrefix,
|
||||
HandlerUpdateMetacacheListing: peerPrefix,
|
||||
HandlerGetPeerBucketMetrics: peerPrefix,
|
||||
HandlerStorageInfo: peerPrefix,
|
||||
HandlerConsoleLog: peerPrefix,
|
||||
HandlerListDir: storagePrefix,
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -344,9 +392,10 @@ type RoundTripper interface {
|
||||
|
||||
// SingleHandler is a type safe handler for single roundtrip requests.
|
||||
type SingleHandler[Req, Resp RoundTripper] struct {
|
||||
id HandlerID
|
||||
sharedResp bool
|
||||
callReuseReq bool
|
||||
id HandlerID
|
||||
sharedResp bool
|
||||
callReuseReq bool
|
||||
ignoreNilConn bool
|
||||
|
||||
newReq func() Req
|
||||
newResp func() Resp
|
||||
@@ -407,6 +456,17 @@ func (h *SingleHandler[Req, Resp]) AllowCallRequestPool(b bool) *SingleHandler[R
|
||||
return h
|
||||
}
|
||||
|
||||
// IgnoreNilConn will ignore nil connections when calling.
|
||||
// This will make Call return nil instead of ErrDisconnected when the connection is nil.
|
||||
// This may only be set ONCE before use.
|
||||
func (h *SingleHandler[Req, Resp]) IgnoreNilConn() *SingleHandler[Req, Resp] {
|
||||
if h.ignoreNilConn {
|
||||
logger.LogOnceIf(context.Background(), fmt.Errorf("%s: IgnoreNilConn called twice", h.id.String()), h.id.String()+"IgnoreNilConn")
|
||||
}
|
||||
h.ignoreNilConn = true
|
||||
return h
|
||||
}
|
||||
|
||||
// WithSharedResponse indicates it is unsafe to reuse the response
|
||||
// when it has been returned on a handler.
|
||||
// This will disable automatic response recycling/pooling.
|
||||
@@ -476,6 +536,12 @@ type Requester interface {
|
||||
// The response should be returned with PutResponse when no error.
|
||||
// If no deadline is set, a 1-minute deadline is added.
|
||||
func (h *SingleHandler[Req, Resp]) Call(ctx context.Context, c Requester, req Req) (resp Resp, err error) {
|
||||
if c == nil {
|
||||
if h.ignoreNilConn {
|
||||
return resp, nil
|
||||
}
|
||||
return resp, ErrDisconnected
|
||||
}
|
||||
payload, err := req.MarshalMsg(GetByteBuffer()[:0])
|
||||
if err != nil {
|
||||
return resp, err
|
||||
@@ -777,6 +843,9 @@ type Streamer interface {
|
||||
|
||||
// Call the remove with the request and
|
||||
func (h *StreamTypeHandler[Payload, Req, Resp]) Call(ctx context.Context, c Streamer, payload Payload) (st *TypedStream[Req, Resp], err error) {
|
||||
if c == nil {
|
||||
return nil, ErrDisconnected
|
||||
}
|
||||
var payloadB []byte
|
||||
if h.WithPayload {
|
||||
var err error
|
||||
|
||||
@@ -51,14 +51,41 @@ func _() {
|
||||
_ = x[HandlerMakeBucket-40]
|
||||
_ = x[HandlerHeadBucket-41]
|
||||
_ = x[HandlerDeleteBucket-42]
|
||||
_ = x[handlerTest-43]
|
||||
_ = x[handlerTest2-44]
|
||||
_ = x[handlerLast-45]
|
||||
_ = x[HandlerGetMetrics-43]
|
||||
_ = x[HandlerGetResourceMetrics-44]
|
||||
_ = x[HandlerGetMemInfo-45]
|
||||
_ = x[HandlerGetProcInfo-46]
|
||||
_ = x[HandlerGetOSInfo-47]
|
||||
_ = x[HandlerGetPartitions-48]
|
||||
_ = x[HandlerGetNetInfo-49]
|
||||
_ = x[HandlerGetCPUs-50]
|
||||
_ = x[HandlerServerInfo-51]
|
||||
_ = x[HandlerGetSysConfig-52]
|
||||
_ = x[HandlerGetSysServices-53]
|
||||
_ = x[HandlerGetSysErrors-54]
|
||||
_ = x[HandlerGetAllBucketStats-55]
|
||||
_ = x[HandlerGetBucketStats-56]
|
||||
_ = x[HandlerGetSRMetrics-57]
|
||||
_ = x[HandlerGetPeerMetrics-58]
|
||||
_ = x[HandlerGetMetacacheListing-59]
|
||||
_ = x[HandlerUpdateMetacacheListing-60]
|
||||
_ = x[HandlerGetPeerBucketMetrics-61]
|
||||
_ = x[HandlerStorageInfo-62]
|
||||
_ = x[HandlerConsoleLog-63]
|
||||
_ = x[HandlerListDir-64]
|
||||
_ = x[HandlerGetLocks-65]
|
||||
_ = x[HandlerBackgroundHealStatus-66]
|
||||
_ = x[HandlerGetLastDayTierStats-67]
|
||||
_ = x[HandlerSignalService-68]
|
||||
_ = x[HandlerGetBandwidth-69]
|
||||
_ = x[handlerTest-70]
|
||||
_ = x[handlerTest2-71]
|
||||
_ = x[handlerLast-72]
|
||||
}
|
||||
|
||||
const _HandlerID_name = "handlerInvalidLockLockLockRLockLockUnlockLockRUnlockLockRefreshLockForceUnlockWalkDirStatVolDiskInfoNSScannerReadXLReadVersionDeleteFileDeleteVersionUpdateMetadataWriteMetadataCheckPartsRenameDataRenameFileReadAllServerVerifyTraceListenDeleteBucketMetadataLoadBucketMetadataReloadSiteReplicationConfigReloadPoolMetaStopRebalanceLoadRebalanceMetaLoadTransitionTierConfigDeletePolicyLoadPolicyLoadPolicyMappingDeleteServiceAccountLoadServiceAccountDeleteUserLoadUserLoadGroupHealBucketMakeBucketHeadBucketDeleteBuckethandlerTesthandlerTest2handlerLast"
|
||||
const _HandlerID_name = "handlerInvalidLockLockLockRLockLockUnlockLockRUnlockLockRefreshLockForceUnlockWalkDirStatVolDiskInfoNSScannerReadXLReadVersionDeleteFileDeleteVersionUpdateMetadataWriteMetadataCheckPartsRenameDataRenameFileReadAllServerVerifyTraceListenDeleteBucketMetadataLoadBucketMetadataReloadSiteReplicationConfigReloadPoolMetaStopRebalanceLoadRebalanceMetaLoadTransitionTierConfigDeletePolicyLoadPolicyLoadPolicyMappingDeleteServiceAccountLoadServiceAccountDeleteUserLoadUserLoadGroupHealBucketMakeBucketHeadBucketDeleteBucketGetMetricsGetResourceMetricsGetMemInfoGetProcInfoGetOSInfoGetPartitionsGetNetInfoGetCPUsServerInfoGetSysConfigGetSysServicesGetSysErrorsGetAllBucketStatsGetBucketStatsGetSRMetricsGetPeerMetricsGetMetacacheListingUpdateMetacacheListingGetPeerBucketMetricsStorageInfoConsoleLogListDirGetLocksBackgroundHealStatusGetLastDayTierStatsSignalServiceGetBandwidthhandlerTesthandlerTest2handlerLast"
|
||||
|
||||
var _HandlerID_index = [...]uint16{0, 14, 22, 31, 41, 52, 63, 78, 85, 92, 100, 109, 115, 126, 136, 149, 163, 176, 186, 196, 206, 213, 225, 230, 236, 256, 274, 301, 315, 328, 345, 369, 381, 391, 408, 428, 446, 456, 464, 473, 483, 493, 503, 515, 526, 538, 549}
|
||||
var _HandlerID_index = [...]uint16{0, 14, 22, 31, 41, 52, 63, 78, 85, 92, 100, 109, 115, 126, 136, 149, 163, 176, 186, 196, 206, 213, 225, 230, 236, 256, 274, 301, 315, 328, 345, 369, 381, 391, 408, 428, 446, 456, 464, 473, 483, 493, 503, 515, 525, 543, 553, 564, 573, 586, 596, 603, 613, 625, 639, 651, 668, 682, 694, 708, 727, 749, 769, 780, 790, 797, 805, 825, 844, 857, 869, 880, 892, 903}
|
||||
|
||||
func (i HandlerID) String() string {
|
||||
if i >= HandlerID(len(_HandlerID_index)-1) {
|
||||
|
||||
@@ -250,7 +250,7 @@ func (m *Manager) RegisterSingleHandler(id HandlerID, h SingleHandlerFn, subrout
|
||||
|
||||
if len(subroute) == 0 {
|
||||
if m.handlers.hasAny(id) && !id.isTestHandler() {
|
||||
return ErrHandlerAlreadyExists
|
||||
return fmt.Errorf("handler %v: %w", id.String(), ErrHandlerAlreadyExists)
|
||||
}
|
||||
|
||||
m.handlers.single[id] = h
|
||||
@@ -258,7 +258,7 @@ func (m *Manager) RegisterSingleHandler(id HandlerID, h SingleHandlerFn, subrout
|
||||
}
|
||||
subID := makeSubHandlerID(id, s)
|
||||
if m.handlers.hasSubhandler(subID) && !id.isTestHandler() {
|
||||
return ErrHandlerAlreadyExists
|
||||
return fmt.Errorf("handler %v, subroute:%v: %w", id.String(), s, ErrHandlerAlreadyExists)
|
||||
}
|
||||
m.handlers.subSingle[subID] = h
|
||||
// Copy so clients can also pick it up for other subpaths.
|
||||
|
||||
@@ -173,7 +173,7 @@ func (m *muxClient) sendLocked(msg message) error {
|
||||
h := xxh3.Hash(dst)
|
||||
dst = binary.LittleEndian.AppendUint32(dst, uint32(h))
|
||||
}
|
||||
return m.parent.send(dst)
|
||||
return m.parent.send(m.ctx, dst)
|
||||
}
|
||||
|
||||
// RequestStateless will send a single payload request and stream back results.
|
||||
@@ -552,7 +552,15 @@ func (m *muxClient) close() {
|
||||
if debugPrint {
|
||||
fmt.Println("closing outgoing mux", m.MuxID)
|
||||
}
|
||||
m.respMu.Lock()
|
||||
if !m.respMu.TryLock() {
|
||||
// Cancel before locking - will unblock any pending sends.
|
||||
if m.cancelFn != nil {
|
||||
m.cancelFn(context.Canceled)
|
||||
}
|
||||
// Wait for senders to release.
|
||||
m.respMu.Lock()
|
||||
}
|
||||
|
||||
defer m.respMu.Unlock()
|
||||
m.closeLocked()
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
package grid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -394,6 +397,137 @@ func (u URLValues) Msgsize() (s int) {
|
||||
return
|
||||
}
|
||||
|
||||
// JSONPool is a pool for JSON objects that unmarshal into T.
|
||||
type JSONPool[T any] struct {
|
||||
pool sync.Pool
|
||||
emptySz int
|
||||
}
|
||||
|
||||
// NewJSONPool returns a new JSONPool.
|
||||
func NewJSONPool[T any]() *JSONPool[T] {
|
||||
var t T
|
||||
sz := 128
|
||||
if b, err := json.Marshal(t); err != nil {
|
||||
sz = len(b)
|
||||
}
|
||||
return &JSONPool[T]{
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
var t T
|
||||
return &t
|
||||
},
|
||||
},
|
||||
emptySz: sz,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *JSONPool[T]) new() *T {
|
||||
var zero T
|
||||
t := p.pool.Get().(*T)
|
||||
*t = zero
|
||||
return t
|
||||
}
|
||||
|
||||
// JSON is a wrapper around a T object that can be serialized.
|
||||
// There is an internal value
|
||||
type JSON[T any] struct {
|
||||
p *JSONPool[T]
|
||||
val *T
|
||||
}
|
||||
|
||||
// NewJSON returns a new JSONPool.
|
||||
// No initial value is set.
|
||||
func (p *JSONPool[T]) NewJSON() *JSON[T] {
|
||||
var j JSON[T]
|
||||
j.p = p
|
||||
return &j
|
||||
}
|
||||
|
||||
// NewJSONWith returns a new JSON with the provided value.
|
||||
func (p *JSONPool[T]) NewJSONWith(val *T) *JSON[T] {
|
||||
var j JSON[T]
|
||||
j.p = p
|
||||
j.val = val
|
||||
return &j
|
||||
}
|
||||
|
||||
// Value returns the underlying value.
|
||||
// If not set yet, a new value is created.
|
||||
func (j *JSON[T]) Value() *T {
|
||||
if j.val == nil {
|
||||
j.val = j.p.new()
|
||||
}
|
||||
return j.val
|
||||
}
|
||||
|
||||
// ValueOrZero returns the underlying value.
|
||||
// If the underlying value is nil, a zero value is returned.
|
||||
func (j *JSON[T]) ValueOrZero() T {
|
||||
if j == nil || j.val == nil {
|
||||
var t T
|
||||
return t
|
||||
}
|
||||
return *j.val
|
||||
}
|
||||
|
||||
// Set the underlying value.
|
||||
func (j *JSON[T]) Set(v *T) {
|
||||
j.val = v
|
||||
}
|
||||
|
||||
// Recycle the underlying value.
|
||||
func (j *JSON[T]) Recycle() {
|
||||
if j.val != nil {
|
||||
j.p.pool.Put(j.val)
|
||||
j.val = nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (j *JSON[T]) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
if j.val == nil {
|
||||
return msgp.AppendNil(b), nil
|
||||
}
|
||||
buf := bytes.NewBuffer(GetByteBuffer()[:0])
|
||||
defer func() {
|
||||
PutByteBuffer(buf.Bytes())
|
||||
}()
|
||||
enc := json.NewEncoder(buf)
|
||||
err = enc.Encode(j.val)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
return msgp.AppendBytes(b, buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array.
|
||||
// Nil values are supported.
|
||||
func (j *JSON[T]) UnmarshalMsg(bytes []byte) ([]byte, error) {
|
||||
if bytes, err := msgp.ReadNilBytes(bytes); err == nil {
|
||||
if j.val != nil {
|
||||
j.p.pool.Put(j.val)
|
||||
}
|
||||
j.val = nil
|
||||
return bytes, nil
|
||||
}
|
||||
val, bytes, err := msgp.ReadBytesZC(bytes)
|
||||
if err != nil {
|
||||
return bytes, err
|
||||
}
|
||||
if j.val == nil {
|
||||
j.val = j.p.new()
|
||||
} else {
|
||||
var t T
|
||||
*j.val = t
|
||||
}
|
||||
return bytes, json.Unmarshal(val, j.val)
|
||||
}
|
||||
|
||||
// Msgsize returns the size of an empty JSON object.
|
||||
func (j *JSON[T]) Msgsize() int {
|
||||
return j.p.emptySz
|
||||
}
|
||||
|
||||
// NoPayload is a type that can be used for handlers that do not use a payload.
|
||||
type NoPayload struct{}
|
||||
|
||||
@@ -419,3 +553,158 @@ func NewNoPayload() NoPayload {
|
||||
|
||||
// Recycle is a no-op.
|
||||
func (NoPayload) Recycle() {}
|
||||
|
||||
// ArrayOf wraps an array of Messagepack compatible objects.
|
||||
type ArrayOf[T RoundTripper] struct {
|
||||
aPool sync.Pool // Arrays
|
||||
ePool sync.Pool // Elements
|
||||
}
|
||||
|
||||
// NewArrayOf returns a new ArrayOf.
|
||||
// You must provide a function that returns a new instance of T.
|
||||
func NewArrayOf[T RoundTripper](newFn func() T) *ArrayOf[T] {
|
||||
return &ArrayOf[T]{
|
||||
ePool: sync.Pool{New: func() any {
|
||||
return newFn()
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a new empty Array.
|
||||
func (p *ArrayOf[T]) New() *Array[T] {
|
||||
return &Array[T]{
|
||||
p: p,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWith returns a new Array with the provided value (not copied).
|
||||
func (p *ArrayOf[T]) NewWith(val []T) *Array[T] {
|
||||
return &Array[T]{
|
||||
p: p,
|
||||
val: val,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ArrayOf[T]) newA(sz uint32) []T {
|
||||
t, ok := p.aPool.Get().(*[]T)
|
||||
if !ok || t == nil {
|
||||
return make([]T, 0, sz)
|
||||
}
|
||||
t2 := *t
|
||||
return t2[:0]
|
||||
}
|
||||
|
||||
func (p *ArrayOf[T]) putA(v []T) {
|
||||
var zero T // nil
|
||||
for i, t := range v {
|
||||
p.ePool.Put(t)
|
||||
v[i] = zero
|
||||
}
|
||||
if v != nil {
|
||||
v = v[:0]
|
||||
p.aPool.Put(&v)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ArrayOf[T]) newE() T {
|
||||
return p.ePool.Get().(T)
|
||||
}
|
||||
|
||||
// Array provides a wrapper for an underlying array of serializable objects.
|
||||
type Array[T RoundTripper] struct {
|
||||
p *ArrayOf[T]
|
||||
val []T
|
||||
}
|
||||
|
||||
// Msgsize returns the size of the array in bytes.
|
||||
func (j *Array[T]) Msgsize() int {
|
||||
if j.val == nil {
|
||||
return msgp.NilSize
|
||||
}
|
||||
sz := msgp.ArrayHeaderSize
|
||||
for _, v := range j.val {
|
||||
sz += v.Msgsize()
|
||||
}
|
||||
return sz
|
||||
}
|
||||
|
||||
// Value returns the underlying value.
|
||||
// Regular append mechanics should be observed.
|
||||
// If no value has been set yet, a new array is created.
|
||||
func (j *Array[T]) Value() []T {
|
||||
if j.val == nil {
|
||||
j.val = j.p.newA(10)
|
||||
}
|
||||
return j.val
|
||||
}
|
||||
|
||||
// Append a value to the underlying array.
|
||||
// The returned Array is always the same as the one called.
|
||||
func (j *Array[T]) Append(v ...T) *Array[T] {
|
||||
if j.val == nil {
|
||||
j.val = j.p.newA(uint32(len(v)))
|
||||
}
|
||||
j.val = append(j.val, v...)
|
||||
return j
|
||||
}
|
||||
|
||||
// Set the underlying value.
|
||||
func (j *Array[T]) Set(val []T) {
|
||||
j.val = val
|
||||
}
|
||||
|
||||
// Recycle the underlying value.
|
||||
func (j *Array[T]) Recycle() {
|
||||
if j.val != nil {
|
||||
j.p.putA(j.val)
|
||||
j.val = nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (j *Array[T]) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
if j.val == nil {
|
||||
return msgp.AppendNil(b), nil
|
||||
}
|
||||
if uint64(len(j.val)) > math.MaxUint32 {
|
||||
return b, errors.New("array: length of array exceeds math.MaxUint32")
|
||||
}
|
||||
b = msgp.AppendArrayHeader(b, uint32(len(j.val)))
|
||||
for _, v := range j.val {
|
||||
b, err = v.MarshalMsg(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
// UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array.
|
||||
// Nil values are supported.
|
||||
func (j *Array[T]) UnmarshalMsg(bytes []byte) ([]byte, error) {
|
||||
if bytes, err := msgp.ReadNilBytes(bytes); err == nil {
|
||||
if j.val != nil {
|
||||
j.p.putA(j.val)
|
||||
}
|
||||
j.val = nil
|
||||
return bytes, nil
|
||||
}
|
||||
l, bytes, err := msgp.ReadArrayHeaderBytes(bytes)
|
||||
if err != nil {
|
||||
return bytes, err
|
||||
}
|
||||
if j.val == nil {
|
||||
j.val = j.p.newA(l)
|
||||
} else {
|
||||
j.val = j.val[:0]
|
||||
}
|
||||
for i := uint32(0); i < l; i++ {
|
||||
v := j.p.newE()
|
||||
bytes, err = v.UnmarshalMsg(bytes)
|
||||
if err != nil {
|
||||
return bytes, err
|
||||
}
|
||||
j.val = append(j.val, v)
|
||||
}
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
@@ -124,17 +124,17 @@ func Init(goPath string, goRoot string) {
|
||||
var goRootList []string
|
||||
var defaultgoPathList []string
|
||||
var defaultgoRootList []string
|
||||
pathSeperator := ":"
|
||||
pathSeparator := ":"
|
||||
// Add all possible GOPATH paths into trimStrings
|
||||
// Split GOPATH depending on the OS type
|
||||
if runtime.GOOS == "windows" {
|
||||
pathSeperator = ";"
|
||||
pathSeparator = ";"
|
||||
}
|
||||
|
||||
goPathList = strings.Split(goPath, pathSeperator)
|
||||
goRootList = strings.Split(goRoot, pathSeperator)
|
||||
defaultgoPathList = strings.Split(build.Default.GOPATH, pathSeperator)
|
||||
defaultgoRootList = strings.Split(build.Default.GOROOT, pathSeperator)
|
||||
goPathList = strings.Split(goPath, pathSeparator)
|
||||
goRootList = strings.Split(goRoot, pathSeparator)
|
||||
defaultgoPathList = strings.Split(build.Default.GOPATH, pathSeparator)
|
||||
defaultgoRootList = strings.Split(build.Default.GOROOT, pathSeparator)
|
||||
|
||||
// Add trim string "{GOROOT}/src/" into trimStrings
|
||||
trimStrings = []string{filepath.Join(runtime.GOROOT(), "src") + string(filepath.Separator)}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
@@ -78,44 +77,6 @@ type Config struct {
|
||||
LogOnce func(ctx context.Context, err error, id string, errKind ...interface{}) `json:"-"`
|
||||
}
|
||||
|
||||
func (h *Target) pingBrokers() (err error) {
|
||||
d := net.Dialer{Timeout: 1 * time.Second}
|
||||
|
||||
errs := make([]error, len(h.kconfig.Brokers))
|
||||
var wg sync.WaitGroup
|
||||
for idx, broker := range h.kconfig.Brokers {
|
||||
broker := broker
|
||||
idx := idx
|
||||
wg.Add(1)
|
||||
go func(broker xnet.Host, idx int) {
|
||||
defer wg.Done()
|
||||
conn, ok := h.brokerConns[broker.String()]
|
||||
if !ok || conn == nil {
|
||||
conn, errs[idx] = d.Dial("tcp", broker.String())
|
||||
if errs[idx] != nil {
|
||||
return
|
||||
}
|
||||
h.brokerConns[broker.String()] = conn
|
||||
}
|
||||
if _, errs[idx] = conn.Write([]byte("")); errs[idx] != nil {
|
||||
conn.Close()
|
||||
h.brokerConns[broker.String()] = nil
|
||||
}
|
||||
}(broker, idx)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
var retErr error
|
||||
for _, err := range errs {
|
||||
if err == nil {
|
||||
// if one of them is active we are good.
|
||||
return nil
|
||||
}
|
||||
retErr = err
|
||||
}
|
||||
return retErr
|
||||
}
|
||||
|
||||
// Target - Kafka target.
|
||||
type Target struct {
|
||||
status int32
|
||||
@@ -139,10 +100,10 @@ type Target struct {
|
||||
initKafkaOnce once.Init
|
||||
initQueueStoreOnce once.Init
|
||||
|
||||
producer sarama.SyncProducer
|
||||
kconfig Config
|
||||
config *sarama.Config
|
||||
brokerConns map[string]net.Conn
|
||||
client sarama.Client
|
||||
producer sarama.SyncProducer
|
||||
kconfig Config
|
||||
config *sarama.Config
|
||||
}
|
||||
|
||||
func (h *Target) validate() error {
|
||||
@@ -202,7 +163,7 @@ func (h *Target) Init(ctx context.Context) error {
|
||||
if err := h.init(); err != nil {
|
||||
return err
|
||||
}
|
||||
go h.startKakfaLogger()
|
||||
go h.startKafkaLogger()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -220,7 +181,7 @@ func (h *Target) initQueueStore(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (h *Target) startKakfaLogger() {
|
||||
func (h *Target) startKafkaLogger() {
|
||||
h.logChMu.RLock()
|
||||
logCh := h.logCh
|
||||
if logCh != nil {
|
||||
@@ -273,10 +234,6 @@ func (h *Target) send(entry interface{}) error {
|
||||
|
||||
// Init initialize kafka target
|
||||
func (h *Target) init() error {
|
||||
if err := h.pingBrokers(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sconfig := sarama.NewConfig()
|
||||
if h.kconfig.Version != "" {
|
||||
kafkaVersion, err := sarama.ParseKafkaVersion(h.kconfig.Version)
|
||||
@@ -325,13 +282,23 @@ func (h *Target) init() error {
|
||||
brokers = append(brokers, broker.String())
|
||||
}
|
||||
|
||||
producer, err := sarama.NewSyncProducer(brokers, sconfig)
|
||||
client, err := sarama.NewClient(brokers, sconfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
producer, err := sarama.NewSyncProducerFromClient(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.client = client
|
||||
h.producer = producer
|
||||
atomic.StoreInt32(&h.status, statusOnline)
|
||||
|
||||
if len(h.client.Brokers()) > 0 {
|
||||
// Refer https://github.com/IBM/sarama/issues/1341
|
||||
atomic.StoreInt32(&h.status, statusOnline)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -409,12 +376,7 @@ func (h *Target) Cancel() {
|
||||
|
||||
if h.producer != nil {
|
||||
h.producer.Close()
|
||||
}
|
||||
|
||||
for _, conn := range h.brokerConns {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
h.client.Close()
|
||||
}
|
||||
|
||||
// Wait for messages to be sent...
|
||||
@@ -425,10 +387,9 @@ func (h *Target) Cancel() {
|
||||
// sends log over http to the specified endpoint
|
||||
func New(config Config) *Target {
|
||||
target := &Target{
|
||||
logCh: make(chan interface{}, config.QueueSize),
|
||||
kconfig: config,
|
||||
status: statusOffline,
|
||||
brokerConns: make(map[string]net.Conn, len(config.Brokers)),
|
||||
logCh: make(chan interface{}, config.QueueSize),
|
||||
kconfig: config,
|
||||
status: statusOffline,
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ func NewReader(readCloser io.ReadCloser, args *ReaderArgs) (*Reader, error) {
|
||||
ret.Comment = []rune(args.CommentCharacter)[0]
|
||||
ret.Quote = []rune{}
|
||||
if len([]rune(args.QuoteCharacter)) > 0 {
|
||||
// Add the first rune of args.QuoteChracter
|
||||
// Add the first rune of args.QuoteCharacter
|
||||
ret.Quote = append(ret.Quote, []rune(args.QuoteCharacter)[0])
|
||||
}
|
||||
ret.QuoteEscape = []rune(args.QuoteEscapeCharacter)[0]
|
||||
|
||||
@@ -25,11 +25,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
errKeyLookup = errors.New("Cannot look up key in non-object value")
|
||||
errIndexLookup = errors.New("Cannot look up array index in non-array value")
|
||||
errWildcardObjectLookup = errors.New("Object wildcard used on non-object value")
|
||||
errWildcardArrayLookup = errors.New("Array wildcard used on non-array value")
|
||||
errWilcardObjectUsageInvalid = errors.New("Invalid usage of object wildcard")
|
||||
errKeyLookup = errors.New("Cannot look up key in non-object value")
|
||||
errIndexLookup = errors.New("Cannot look up array index in non-array value")
|
||||
errWildcardObjectLookup = errors.New("Object wildcard used on non-object value")
|
||||
errWildcardArrayLookup = errors.New("Array wildcard used on non-array value")
|
||||
errWildcardObjectUsageInvalid = errors.New("Invalid usage of object wildcard")
|
||||
)
|
||||
|
||||
// jsonpathEval evaluates a JSON path and returns the value at the path.
|
||||
@@ -85,13 +85,13 @@ func jsonpathEval(p []*JSONPathElement, v interface{}) (r interface{}, flat bool
|
||||
switch kvs := v.(type) {
|
||||
case jstream.KVS:
|
||||
if len(p[1:]) > 0 {
|
||||
return nil, false, errWilcardObjectUsageInvalid
|
||||
return nil, false, errWildcardObjectUsageInvalid
|
||||
}
|
||||
|
||||
return kvs, false, nil
|
||||
case simdjson.Object:
|
||||
if len(p[1:]) > 0 {
|
||||
return nil, false, errWilcardObjectUsageInvalid
|
||||
return nil, false, errWildcardObjectUsageInvalid
|
||||
}
|
||||
|
||||
return kvs, false, nil
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
package s3select
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Validation errors.
|
||||
// Validation errors.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
func errExpressionTooLong(err error) *s3Error {
|
||||
return &s3Error{
|
||||
code: "ExpressionTooLong",
|
||||
@@ -151,11 +151,11 @@ func errUnrecognizedFormatException(err error) *s3Error {
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SQL parsing errors.
|
||||
// SQL parsing errors.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
func errLexerInvalidChar(err error) *s3Error {
|
||||
return &s3Error{
|
||||
code: "LexerInvalidChar",
|
||||
@@ -498,11 +498,11 @@ func errParseCannotMixSqbAndWildcardInSelectList(err error) *s3Error {
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CAST() related errors.
|
||||
// CAST() related errors.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
func errCastFailed(err error) *s3Error {
|
||||
return &s3Error{
|
||||
code: "CastFailed",
|
||||
@@ -593,11 +593,11 @@ func errEvaluatorInvalidTimestampFormatPatternSymbol(err error) *s3Error {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generic S3 HTTP handler errors.
|
||||
// Generic S3 HTTP handler errors.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
func errBusy(err error) *s3Error {
|
||||
return &s3Error{
|
||||
code: "Busy",
|
||||
|
||||
Reference in New Issue
Block a user