github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/ais/prxbsumm.go (about) 1 // Package ais provides core functionality for the AIStore object storage. 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package ais 6 7 import ( 8 "net/http" 9 "net/url" 10 "strconv" 11 12 "github.com/NVIDIA/aistore/api/apc" 13 "github.com/NVIDIA/aistore/cmn" 14 "github.com/NVIDIA/aistore/cmn/cos" 15 "github.com/NVIDIA/aistore/cmn/debug" 16 "github.com/NVIDIA/aistore/core/meta" 17 ) 18 19 // in this source: 20 // - bsummact <= api.GetBucketSummary(query-bcks, ActMsg) 21 // - bsummhead <= api.GetBucketInfo(bck, QparamBinfoWithOrWithoutRemote) 22 23 func (p *proxy) bsummact(w http.ResponseWriter, r *http.Request, qbck *cmn.QueryBcks, msg *apc.BsummCtrlMsg) { 24 news := msg.UUID == "" 25 debug.Assert(msg.UUID == "" || cos.IsValidUUID(msg.UUID), msg.UUID) 26 27 // start new 28 if news { 29 err := p.bsummNew(qbck, msg) 30 if err != nil { 31 p.writeErr(w, r, err) 32 } else { 33 w.WriteHeader(http.StatusAccepted) 34 w.Header().Set(cos.HdrContentLength, strconv.Itoa(len(msg.UUID))) 35 w.Write([]byte(msg.UUID)) 36 } 37 return 38 } 39 40 // or, query partial or final results 41 summaries, status, err := p.bsummCollect(qbck, msg) 42 if err != nil { 43 p.writeErr(w, r, err) 44 return 45 } 46 w.WriteHeader(status) 47 p.writeJSON(w, r, summaries, "bucket-summary") 48 } 49 50 func (p *proxy) bsummNew(qbck *cmn.QueryBcks, msg *apc.BsummCtrlMsg) (err error) { 51 q := qbck.NewQuery() 52 53 msg.UUID = cos.GenUUID() 54 aisMsg := p.newAmsgActVal(apc.ActSummaryBck, msg) 55 56 args := allocBcArgs() 57 args.req = cmn.HreqArgs{ 58 Method: http.MethodGet, 59 Path: apc.URLPathBuckets.Join(qbck.Name, apc.ActBegin), // compare w/ txn 60 Query: q, 61 Body: cos.MustMarshal(aisMsg), 62 } 63 args.smap = p.owner.smap.get() 64 if cnt := args.smap.CountActiveTs(); cnt < 1 { 65 return cmn.NewErrNoNodes(apc.Target, args.smap.CountTargets()) 66 } 67 results := p.bcastGroup(args) 68 for _, res := range results { 69 if res.err != nil { 70 err = res.toErr() 71 break 72 } 73 } 74 freeBcastRes(results) 75 return 76 } 77 78 func (p *proxy) bsummCollect(qbck *cmn.QueryBcks, msg *apc.BsummCtrlMsg) (_ cmn.AllBsummResults, status int, _ error) { 79 var ( 80 q = make(url.Values, 4) 81 aisMsg = p.newAmsgActVal(apc.ActSummaryBck, msg) 82 args = allocBcArgs() 83 ) 84 args.req = cmn.HreqArgs{ 85 Method: http.MethodGet, 86 Path: apc.URLPathBuckets.Join(qbck.Name, apc.ActQuery), 87 Body: cos.MustMarshal(aisMsg), 88 } 89 args.smap = p.owner.smap.get() 90 if cnt := args.smap.CountActiveTs(); cnt < 1 { 91 return nil, 0, cmn.NewErrNoNodes(apc.Target, args.smap.CountTargets()) 92 } 93 qbck.AddToQuery(q) 94 q.Set(apc.QparamSilent, "true") 95 args.req.Query = q 96 args.cresv = cresBsumm{} // -> cmn.AllBsummResults 97 98 results := p.bcastGroup(args) 99 freeBcArgs(args) 100 for _, res := range results { 101 if res.err != nil { 102 freeBcastRes(results) 103 return nil, 0, res.toErr() 104 } 105 } 106 107 var ( 108 summaries = make(cmn.AllBsummResults, 0, 8) 109 dsize = make(map[string]uint64, len(results)) 110 numAccepted int 111 numPartial int 112 ) 113 for _, res := range results { 114 if res.status == http.StatusAccepted { 115 numAccepted++ 116 continue 117 } 118 if res.status == http.StatusPartialContent { 119 numPartial++ 120 } 121 tbsumm, tid := res.v.(*cmn.AllBsummResults), res.si.ID() 122 for _, summ := range *tbsumm { 123 dsize[tid] = summ.TotalSize.Disks 124 summaries = summaries.Aggregate(summ) 125 } 126 } 127 summaries.Finalize(dsize, cmn.Rom.TestingEnv()) 128 freeBcastRes(results) 129 130 switch { 131 case numPartial == 0 && numAccepted == 0: 132 status = http.StatusOK 133 case numPartial == 0: 134 status = http.StatusAccepted 135 default: 136 status = http.StatusPartialContent 137 } 138 return summaries, status, nil 139 } 140 141 // fully reuse bsummact impl. 142 func (p *proxy) bsummhead(bck *meta.Bck, msg *apc.BsummCtrlMsg) (info *cmn.BsummResult, status int, err error) { 143 var ( 144 summaries cmn.AllBsummResults 145 qbck = (*cmn.QueryBcks)(bck) // adapt 146 ) 147 if msg.UUID == "" { 148 if err = p.bsummNew(qbck, msg); err == nil { 149 status = http.StatusAccepted 150 } 151 return 152 } 153 summaries, status, err = p.bsummCollect(qbck, msg) 154 if err == nil && (status == http.StatusOK || status == http.StatusPartialContent) { 155 info = summaries[0] 156 } 157 return 158 }