github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/grid/types.go (about) 1 // Copyright (c) 2015-2023 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package grid 19 20 import ( 21 "bytes" 22 "encoding/json" 23 "errors" 24 "math" 25 "net/url" 26 "sort" 27 "strings" 28 "sync" 29 30 "github.com/tinylib/msgp/msgp" 31 ) 32 33 // Recycler will override the internal reuse in typed handlers. 34 // When this is supported, the handler will not do internal pooling of objects, 35 // call Recycle() when the object is no longer needed. 36 // The recycler should handle nil pointers. 37 type Recycler interface { 38 Recycle() 39 } 40 41 // MSS is a map[string]string that can be serialized. 42 // It is not very efficient, but it is only used for easy parameter passing. 43 type MSS map[string]string 44 45 // Get returns the value for the given key. 46 func (m *MSS) Get(key string) string { 47 if m == nil { 48 return "" 49 } 50 return (*m)[key] 51 } 52 53 // Set a key, value pair. 54 func (m *MSS) Set(key, value string) { 55 if m == nil { 56 *m = mssPool.Get().(map[string]string) 57 } 58 (*m)[key] = value 59 } 60 61 // UnmarshalMsg deserializes m from the provided byte slice and returns the 62 // remainder of bytes. 63 func (m *MSS) UnmarshalMsg(bts []byte) (o []byte, err error) { 64 if m == nil { 65 return bts, errors.New("MSS: UnmarshalMsg on nil pointer") 66 } 67 if msgp.IsNil(bts) { 68 bts = bts[1:] 69 *m = nil 70 return bts, nil 71 } 72 var zb0002 uint32 73 zb0002, bts, err = msgp.ReadMapHeaderBytes(bts) 74 if err != nil { 75 err = msgp.WrapError(err, "Values") 76 return 77 } 78 dst := *m 79 if dst == nil { 80 dst = make(map[string]string, zb0002) 81 } else if len(dst) > 0 { 82 for key := range dst { 83 delete(dst, key) 84 } 85 } 86 for zb0002 > 0 { 87 var za0001 string 88 var za0002 string 89 zb0002-- 90 za0001, bts, err = msgp.ReadStringBytes(bts) 91 if err != nil { 92 err = msgp.WrapError(err, "Values") 93 return 94 } 95 za0002, bts, err = msgp.ReadStringBytes(bts) 96 if err != nil { 97 err = msgp.WrapError(err, "Values", za0001) 98 return 99 } 100 dst[za0001] = za0002 101 } 102 *m = dst 103 return bts, nil 104 } 105 106 // MarshalMsg appends the bytes representation of b to the provided byte slice. 107 func (m *MSS) MarshalMsg(bytes []byte) (o []byte, err error) { 108 if m == nil || *m == nil { 109 return msgp.AppendNil(bytes), nil 110 } 111 o = msgp.AppendMapHeader(bytes, uint32(len(*m))) 112 for za0001, za0002 := range *m { 113 o = msgp.AppendString(o, za0001) 114 o = msgp.AppendString(o, za0002) 115 } 116 return o, nil 117 } 118 119 // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message. 120 func (m *MSS) Msgsize() int { 121 if m == nil || *m == nil { 122 return msgp.NilSize 123 } 124 s := msgp.MapHeaderSize 125 for za0001, za0002 := range *m { 126 s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002) 127 } 128 return s 129 } 130 131 // NewMSS returns a new MSS. 132 func NewMSS() *MSS { 133 m := MSS(mssPool.Get().(map[string]string)) 134 for k := range m { 135 delete(m, k) 136 } 137 return &m 138 } 139 140 // NewMSSWith returns a new MSS with the given map. 141 func NewMSSWith(m map[string]string) *MSS { 142 m2 := MSS(m) 143 return &m2 144 } 145 146 var mssPool = sync.Pool{ 147 New: func() interface{} { 148 return make(map[string]string, 5) 149 }, 150 } 151 152 // Recycle the underlying map. 153 func (m *MSS) Recycle() { 154 if m != nil && *m != nil { 155 mssPool.Put(map[string]string(*m)) 156 *m = nil 157 } 158 } 159 160 // ToQuery constructs a URL query string from the MSS, including "?" if there are any keys. 161 func (m MSS) ToQuery() string { 162 if len(m) == 0 { 163 return "" 164 } 165 var buf strings.Builder 166 buf.WriteByte('?') 167 keys := make([]string, 0, len(m)) 168 for k := range m { 169 keys = append(keys, k) 170 } 171 sort.Strings(keys) 172 for _, k := range keys { 173 v := m[k] 174 keyEscaped := url.QueryEscape(k) 175 if buf.Len() > 1 { 176 buf.WriteByte('&') 177 } 178 buf.WriteString(keyEscaped) 179 buf.WriteByte('=') 180 buf.WriteString(url.QueryEscape(v)) 181 } 182 return buf.String() 183 } 184 185 // NewBytes returns a new Bytes. 186 // A slice is preallocated. 187 func NewBytes() *Bytes { 188 b := Bytes(GetByteBuffer()[:0]) 189 return &b 190 } 191 192 // NewBytesWith returns a new Bytes with the provided content. 193 // When sent as a parameter, the caller gives up ownership of the byte slice. 194 // When returned as response, the handler also gives up ownership of the byte slice. 195 func NewBytesWith(b []byte) *Bytes { 196 bb := Bytes(b) 197 return &bb 198 } 199 200 // NewBytesWithCopyOf returns a new byte slice with a copy of the provided content. 201 func NewBytesWithCopyOf(b []byte) *Bytes { 202 if b == nil { 203 bb := Bytes(nil) 204 return &bb 205 } 206 if len(b) < maxBufferSize { 207 bb := NewBytes() 208 *bb = append(*bb, b...) 209 return bb 210 } 211 bb := Bytes(make([]byte, len(b))) 212 copy(bb, b) 213 return &bb 214 } 215 216 // Bytes provides a byte slice that can be serialized. 217 type Bytes []byte 218 219 // UnmarshalMsg deserializes b from the provided byte slice and returns the 220 // remainder of bytes. 221 func (b *Bytes) UnmarshalMsg(bytes []byte) ([]byte, error) { 222 if b == nil { 223 return bytes, errors.New("Bytes: UnmarshalMsg on nil pointer") 224 } 225 if bytes, err := msgp.ReadNilBytes(bytes); err == nil { 226 if *b != nil { 227 PutByteBuffer(*b) 228 } 229 *b = nil 230 return bytes, nil 231 } 232 val, bytes, err := msgp.ReadBytesZC(bytes) 233 if err != nil { 234 return bytes, err 235 } 236 if cap(*b) >= len(val) { 237 *b = (*b)[:len(val)] 238 copy(*b, val) 239 } else { 240 if cap(*b) == 0 && len(val) <= maxBufferSize { 241 *b = GetByteBuffer()[:0] 242 } else { 243 PutByteBuffer(*b) 244 *b = make([]byte, 0, len(val)) 245 } 246 in := *b 247 in = append(in[:0], val...) 248 *b = in 249 } 250 return bytes, nil 251 } 252 253 // MarshalMsg appends the bytes representation of b to the provided byte slice. 254 func (b *Bytes) MarshalMsg(bytes []byte) ([]byte, error) { 255 if b == nil || *b == nil { 256 return msgp.AppendNil(bytes), nil 257 } 258 return msgp.AppendBytes(bytes, *b), nil 259 } 260 261 // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message. 262 func (b *Bytes) Msgsize() int { 263 if b == nil || *b == nil { 264 return msgp.NilSize 265 } 266 return msgp.ArrayHeaderSize + len(*b) 267 } 268 269 // Recycle puts the Bytes back into the pool. 270 func (b *Bytes) Recycle() { 271 if b != nil && *b != nil { 272 *b = (*b)[:0] 273 PutByteBuffer(*b) 274 *b = nil 275 } 276 } 277 278 // URLValues can be used for url.Values. 279 type URLValues map[string][]string 280 281 var urlValuesPool = sync.Pool{ 282 New: func() interface{} { 283 return make(map[string][]string, 10) 284 }, 285 } 286 287 // NewURLValues returns a new URLValues. 288 func NewURLValues() *URLValues { 289 u := URLValues(urlValuesPool.Get().(map[string][]string)) 290 return &u 291 } 292 293 // NewURLValuesWith returns a new URLValues with the provided content. 294 func NewURLValuesWith(values map[string][]string) *URLValues { 295 u := URLValues(values) 296 return &u 297 } 298 299 // Values returns the url.Values. 300 // If u is nil, an empty url.Values is returned. 301 // The values are a shallow copy of the underlying map. 302 func (u *URLValues) Values() url.Values { 303 if u == nil { 304 return url.Values{} 305 } 306 return url.Values(*u) 307 } 308 309 // Recycle the underlying map. 310 func (u *URLValues) Recycle() { 311 if *u != nil { 312 for key := range *u { 313 delete(*u, key) 314 } 315 val := map[string][]string(*u) 316 urlValuesPool.Put(val) 317 *u = nil 318 } 319 } 320 321 // MarshalMsg implements msgp.Marshaler 322 func (u URLValues) MarshalMsg(b []byte) (o []byte, err error) { 323 o = msgp.Require(b, u.Msgsize()) 324 o = msgp.AppendMapHeader(o, uint32(len(u))) 325 for zb0006, zb0007 := range u { 326 o = msgp.AppendString(o, zb0006) 327 o = msgp.AppendArrayHeader(o, uint32(len(zb0007))) 328 for zb0008 := range zb0007 { 329 o = msgp.AppendString(o, zb0007[zb0008]) 330 } 331 } 332 return 333 } 334 335 // UnmarshalMsg implements msgp.Unmarshaler 336 func (u *URLValues) UnmarshalMsg(bts []byte) (o []byte, err error) { 337 var zb0004 uint32 338 zb0004, bts, err = msgp.ReadMapHeaderBytes(bts) 339 if err != nil { 340 err = msgp.WrapError(err) 341 return 342 } 343 if *u == nil { 344 *u = urlValuesPool.Get().(map[string][]string) 345 } 346 if len(*u) > 0 { 347 for key := range *u { 348 delete(*u, key) 349 } 350 } 351 352 for zb0004 > 0 { 353 var zb0001 string 354 var zb0002 []string 355 zb0004-- 356 zb0001, bts, err = msgp.ReadStringBytes(bts) 357 if err != nil { 358 err = msgp.WrapError(err) 359 return 360 } 361 var zb0005 uint32 362 zb0005, bts, err = msgp.ReadArrayHeaderBytes(bts) 363 if err != nil { 364 err = msgp.WrapError(err, zb0001) 365 return 366 } 367 if cap(zb0002) >= int(zb0005) { 368 zb0002 = zb0002[:zb0005] 369 } else { 370 zb0002 = make([]string, zb0005) 371 } 372 for zb0003 := range zb0002 { 373 zb0002[zb0003], bts, err = msgp.ReadStringBytes(bts) 374 if err != nil { 375 err = msgp.WrapError(err, zb0001, zb0003) 376 return 377 } 378 } 379 (*u)[zb0001] = zb0002 380 } 381 o = bts 382 return 383 } 384 385 // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message 386 func (u URLValues) Msgsize() (s int) { 387 s = msgp.MapHeaderSize 388 if u != nil { 389 for zb0006, zb0007 := range u { 390 _ = zb0007 391 s += msgp.StringPrefixSize + len(zb0006) + msgp.ArrayHeaderSize 392 for zb0008 := range zb0007 { 393 s += msgp.StringPrefixSize + len(zb0007[zb0008]) 394 } 395 } 396 } 397 return 398 } 399 400 // JSONPool is a pool for JSON objects that unmarshal into T. 401 type JSONPool[T any] struct { 402 pool sync.Pool 403 emptySz int 404 } 405 406 // NewJSONPool returns a new JSONPool. 407 func NewJSONPool[T any]() *JSONPool[T] { 408 var t T 409 sz := 128 410 if b, err := json.Marshal(t); err != nil { 411 sz = len(b) 412 } 413 return &JSONPool[T]{ 414 pool: sync.Pool{ 415 New: func() interface{} { 416 var t T 417 return &t 418 }, 419 }, 420 emptySz: sz, 421 } 422 } 423 424 func (p *JSONPool[T]) new() *T { 425 var zero T 426 t := p.pool.Get().(*T) 427 *t = zero 428 return t 429 } 430 431 // JSON is a wrapper around a T object that can be serialized. 432 // There is an internal value 433 type JSON[T any] struct { 434 p *JSONPool[T] 435 val *T 436 } 437 438 // NewJSON returns a new JSONPool. 439 // No initial value is set. 440 func (p *JSONPool[T]) NewJSON() *JSON[T] { 441 var j JSON[T] 442 j.p = p 443 return &j 444 } 445 446 // NewJSONWith returns a new JSON with the provided value. 447 func (p *JSONPool[T]) NewJSONWith(val *T) *JSON[T] { 448 var j JSON[T] 449 j.p = p 450 j.val = val 451 return &j 452 } 453 454 // Value returns the underlying value. 455 // If not set yet, a new value is created. 456 func (j *JSON[T]) Value() *T { 457 if j.val == nil { 458 j.val = j.p.new() 459 } 460 return j.val 461 } 462 463 // ValueOrZero returns the underlying value. 464 // If the underlying value is nil, a zero value is returned. 465 func (j *JSON[T]) ValueOrZero() T { 466 if j == nil || j.val == nil { 467 var t T 468 return t 469 } 470 return *j.val 471 } 472 473 // Set the underlying value. 474 func (j *JSON[T]) Set(v *T) { 475 j.val = v 476 } 477 478 // Recycle the underlying value. 479 func (j *JSON[T]) Recycle() { 480 if j.val != nil { 481 j.p.pool.Put(j.val) 482 j.val = nil 483 } 484 } 485 486 // MarshalMsg implements msgp.Marshaler 487 func (j *JSON[T]) MarshalMsg(b []byte) (o []byte, err error) { 488 if j.val == nil { 489 return msgp.AppendNil(b), nil 490 } 491 buf := bytes.NewBuffer(GetByteBuffer()[:0]) 492 defer func() { 493 PutByteBuffer(buf.Bytes()) 494 }() 495 enc := json.NewEncoder(buf) 496 err = enc.Encode(j.val) 497 if err != nil { 498 return b, err 499 } 500 return msgp.AppendBytes(b, buf.Bytes()), nil 501 } 502 503 // UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array. 504 // Nil values are supported. 505 func (j *JSON[T]) UnmarshalMsg(bytes []byte) ([]byte, error) { 506 if bytes, err := msgp.ReadNilBytes(bytes); err == nil { 507 if j.val != nil { 508 j.p.pool.Put(j.val) 509 } 510 j.val = nil 511 return bytes, nil 512 } 513 val, bytes, err := msgp.ReadBytesZC(bytes) 514 if err != nil { 515 return bytes, err 516 } 517 if j.val == nil { 518 j.val = j.p.new() 519 } else { 520 var t T 521 *j.val = t 522 } 523 return bytes, json.Unmarshal(val, j.val) 524 } 525 526 // Msgsize returns the size of an empty JSON object. 527 func (j *JSON[T]) Msgsize() int { 528 return j.p.emptySz 529 } 530 531 // NoPayload is a type that can be used for handlers that do not use a payload. 532 type NoPayload struct{} 533 534 // Msgsize returns 0. 535 func (p NoPayload) Msgsize() int { 536 return 0 537 } 538 539 // UnmarshalMsg satisfies the interface, but is a no-op. 540 func (NoPayload) UnmarshalMsg(bytes []byte) ([]byte, error) { 541 return bytes, nil 542 } 543 544 // MarshalMsg satisfies the interface, but is a no-op. 545 func (NoPayload) MarshalMsg(bytes []byte) ([]byte, error) { 546 return bytes, nil 547 } 548 549 // NewNoPayload returns an empty NoPayload struct. 550 func NewNoPayload() NoPayload { 551 return NoPayload{} 552 } 553 554 // Recycle is a no-op. 555 func (NoPayload) Recycle() {} 556 557 // ArrayOf wraps an array of Messagepack compatible objects. 558 type ArrayOf[T RoundTripper] struct { 559 aPool sync.Pool // Arrays 560 ePool sync.Pool // Elements 561 } 562 563 // NewArrayOf returns a new ArrayOf. 564 // You must provide a function that returns a new instance of T. 565 func NewArrayOf[T RoundTripper](newFn func() T) *ArrayOf[T] { 566 return &ArrayOf[T]{ 567 ePool: sync.Pool{New: func() any { 568 return newFn() 569 }}, 570 } 571 } 572 573 // New returns a new empty Array. 574 func (p *ArrayOf[T]) New() *Array[T] { 575 return &Array[T]{ 576 p: p, 577 } 578 } 579 580 // NewWith returns a new Array with the provided value (not copied). 581 func (p *ArrayOf[T]) NewWith(val []T) *Array[T] { 582 return &Array[T]{ 583 p: p, 584 val: val, 585 } 586 } 587 588 func (p *ArrayOf[T]) newA(sz uint32) []T { 589 t, ok := p.aPool.Get().(*[]T) 590 if !ok || t == nil { 591 return make([]T, 0, sz) 592 } 593 t2 := *t 594 return t2[:0] 595 } 596 597 func (p *ArrayOf[T]) putA(v []T) { 598 var zero T // nil 599 for i, t := range v { 600 p.ePool.Put(t) 601 v[i] = zero 602 } 603 if v != nil { 604 v = v[:0] 605 p.aPool.Put(&v) 606 } 607 } 608 609 func (p *ArrayOf[T]) newE() T { 610 return p.ePool.Get().(T) 611 } 612 613 // Array provides a wrapper for an underlying array of serializable objects. 614 type Array[T RoundTripper] struct { 615 p *ArrayOf[T] 616 val []T 617 } 618 619 // Msgsize returns the size of the array in bytes. 620 func (j *Array[T]) Msgsize() int { 621 if j.val == nil { 622 return msgp.NilSize 623 } 624 sz := msgp.ArrayHeaderSize 625 for _, v := range j.val { 626 sz += v.Msgsize() 627 } 628 return sz 629 } 630 631 // Value returns the underlying value. 632 // Regular append mechanics should be observed. 633 // If no value has been set yet, a new array is created. 634 func (j *Array[T]) Value() []T { 635 if j.val == nil { 636 j.val = j.p.newA(10) 637 } 638 return j.val 639 } 640 641 // Append a value to the underlying array. 642 // The returned Array is always the same as the one called. 643 func (j *Array[T]) Append(v ...T) *Array[T] { 644 if j.val == nil { 645 j.val = j.p.newA(uint32(len(v))) 646 } 647 j.val = append(j.val, v...) 648 return j 649 } 650 651 // Set the underlying value. 652 func (j *Array[T]) Set(val []T) { 653 j.val = val 654 } 655 656 // Recycle the underlying value. 657 func (j *Array[T]) Recycle() { 658 if j.val != nil { 659 j.p.putA(j.val) 660 j.val = nil 661 } 662 } 663 664 // MarshalMsg implements msgp.Marshaler 665 func (j *Array[T]) MarshalMsg(b []byte) (o []byte, err error) { 666 if j.val == nil { 667 return msgp.AppendNil(b), nil 668 } 669 if uint64(len(j.val)) > math.MaxUint32 { 670 return b, errors.New("array: length of array exceeds math.MaxUint32") 671 } 672 b = msgp.AppendArrayHeader(b, uint32(len(j.val))) 673 for _, v := range j.val { 674 b, err = v.MarshalMsg(b) 675 if err != nil { 676 return b, err 677 } 678 } 679 return b, err 680 } 681 682 // UnmarshalMsg will JSON marshal the value and wrap as a msgp byte array. 683 // Nil values are supported. 684 func (j *Array[T]) UnmarshalMsg(bytes []byte) ([]byte, error) { 685 if bytes, err := msgp.ReadNilBytes(bytes); err == nil { 686 if j.val != nil { 687 j.p.putA(j.val) 688 } 689 j.val = nil 690 return bytes, nil 691 } 692 l, bytes, err := msgp.ReadArrayHeaderBytes(bytes) 693 if err != nil { 694 return bytes, err 695 } 696 if j.val == nil { 697 j.val = j.p.newA(l) 698 } else { 699 j.val = j.val[:0] 700 } 701 for i := uint32(0); i < l; i++ { 702 v := j.p.newE() 703 bytes, err = v.UnmarshalMsg(bytes) 704 if err != nil { 705 return bytes, err 706 } 707 j.val = append(j.val, v) 708 } 709 return bytes, nil 710 }