github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/cmd/services/m3dbnode/config/pooling.go (about) 1 // Copyright (c) 2017 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package config 22 23 import ( 24 "fmt" 25 26 "github.com/m3db/m3/src/x/pool" 27 ) 28 29 // PoolingType is a type of pooling, using runtime or mmap'd bytes pooling. 30 type PoolingType string 31 32 const ( 33 // SimplePooling uses the basic Go runtime to allocate bytes for bytes pools. 34 SimplePooling PoolingType = "simple" 35 36 defaultPoolingType = SimplePooling 37 38 defaultBlockAllocSize = 16 39 ) 40 41 var defaultThriftBytesPoolAllocSizes = []int{16, 64, 256, 512, 1024, 2048} 42 43 type poolPolicyDefault struct { 44 size pool.Size 45 refillLowWaterMark float64 46 refillHighWaterMark float64 47 48 // Only used for capacity and max capacity pools. 49 capacity int 50 // Only used for max capacity pools. 51 maxCapacity int 52 } 53 54 type bucketPoolPolicyDefault struct { 55 buckets []CapacityPoolPolicy 56 } 57 58 var ( 59 defaultRefillLowWaterMark = 0.3 60 defaultRefillHighWaterMark = 0.6 61 62 defaultPoolPolicy = poolPolicyDefault{ 63 size: 4096, 64 refillLowWaterMark: 0, 65 refillHighWaterMark: 0, 66 } 67 68 defaultPoolPolicies = map[string]poolPolicyDefault{ 69 "checkedBytesWrapper": poolPolicyDefault{ 70 size: 65536, 71 refillLowWaterMark: 0, 72 refillHighWaterMark: 0, 73 }, 74 "tagsIterator": defaultPoolPolicy, 75 "indexResults": poolPolicyDefault{ 76 // NB(r): There only needs to be one index results map per 77 // concurrent query, so as long as there is no more than 78 // the number of concurrent index queries than the size 79 // specified here the maps should be recycled. 80 size: 256, 81 refillLowWaterMark: 0, 82 refillHighWaterMark: 0, 83 }, 84 "tagEncoder": poolPolicyDefault{ 85 // NB(r): Tag encoder is used for every individual time series 86 // returned from an index query since it needs to encode the tags 87 // back for RPC and has a bytes buffer internally for each time 88 // series being returned. 89 size: 8192, 90 refillLowWaterMark: 0, 91 refillHighWaterMark: 0, 92 }, 93 "tagDecoder": defaultPoolPolicy, 94 "context": poolPolicyDefault{ 95 size: 32768, 96 refillLowWaterMark: 0, 97 refillHighWaterMark: 0, 98 }, 99 "series": poolPolicyDefault{ 100 size: 65536, 101 refillLowWaterMark: defaultRefillLowWaterMark, 102 refillHighWaterMark: defaultRefillHighWaterMark, 103 }, 104 "block": poolPolicyDefault{ 105 size: 65536, 106 refillLowWaterMark: defaultRefillLowWaterMark, 107 refillHighWaterMark: defaultRefillHighWaterMark, 108 }, 109 "encoder": poolPolicyDefault{ 110 size: 65536, 111 refillLowWaterMark: defaultRefillLowWaterMark, 112 refillHighWaterMark: defaultRefillHighWaterMark, 113 }, 114 "closers": poolPolicyDefault{ 115 // NB(r): Note this has to be bigger than context pool by 116 // big fraction (by factor of say 4) since each context 117 // usually uses a fair few closers. 118 size: 262144, 119 refillLowWaterMark: 0, 120 refillHighWaterMark: 0, 121 }, 122 "segmentReader": poolPolicyDefault{ 123 size: 65536, 124 refillLowWaterMark: defaultRefillLowWaterMark, 125 refillHighWaterMark: defaultRefillHighWaterMark, 126 }, 127 "iterator": poolPolicyDefault{ 128 size: 2048, 129 refillLowWaterMark: defaultRefillLowWaterMark, 130 refillHighWaterMark: defaultRefillHighWaterMark, 131 }, 132 "blockMetadata": poolPolicyDefault{ 133 size: 65536, 134 refillLowWaterMark: defaultRefillLowWaterMark, 135 refillHighWaterMark: defaultRefillHighWaterMark, 136 }, 137 "blocksMetadata": poolPolicyDefault{ 138 size: 65536, 139 refillLowWaterMark: defaultRefillLowWaterMark, 140 refillHighWaterMark: defaultRefillHighWaterMark, 141 }, 142 "identifier": poolPolicyDefault{ 143 size: 65536, 144 refillLowWaterMark: defaultRefillLowWaterMark, 145 refillHighWaterMark: defaultRefillHighWaterMark, 146 }, 147 "postingsList": poolPolicyDefault{ 148 // defaultPostingsListPoolSize has a small default pool size since postings 149 // lists can frequently reach the size of 4mb each in practice even when 150 // reset. 151 size: 16, 152 refillLowWaterMark: defaultRefillLowWaterMark, 153 refillHighWaterMark: defaultRefillHighWaterMark, 154 }, 155 "bufferBucket": poolPolicyDefault{ 156 size: 65536, 157 refillLowWaterMark: defaultRefillLowWaterMark, 158 refillHighWaterMark: defaultRefillHighWaterMark, 159 }, 160 "bufferBucketVersions": poolPolicyDefault{ 161 size: 65536, 162 refillLowWaterMark: defaultRefillLowWaterMark, 163 refillHighWaterMark: defaultRefillHighWaterMark, 164 }, 165 "retrieveRequestPool": poolPolicyDefault{ 166 size: 65536, 167 refillLowWaterMark: 0, 168 refillHighWaterMark: 0, 169 }, 170 171 // Capacity pools. 172 "fetchBlockMetadataResults": poolPolicyDefault{ 173 size: 65536, 174 refillLowWaterMark: defaultRefillLowWaterMark, 175 refillHighWaterMark: defaultRefillHighWaterMark, 176 capacity: 32, 177 }, 178 "fetchBlocksMetadataResults": poolPolicyDefault{ 179 size: 32, 180 refillLowWaterMark: defaultRefillLowWaterMark, 181 refillHighWaterMark: defaultRefillHighWaterMark, 182 capacity: 4096, 183 }, 184 "replicaMetadataSlice": poolPolicyDefault{ 185 size: 131072, 186 refillLowWaterMark: defaultRefillLowWaterMark, 187 refillHighWaterMark: defaultRefillHighWaterMark, 188 capacity: 3, 189 }, 190 "blockMetadataSlice": poolPolicyDefault{ 191 size: 65536, 192 refillLowWaterMark: defaultRefillLowWaterMark, 193 refillHighWaterMark: defaultRefillHighWaterMark, 194 capacity: 32, 195 }, 196 "blocksMetadataSlice": poolPolicyDefault{ 197 size: 32, 198 refillLowWaterMark: defaultRefillLowWaterMark, 199 refillHighWaterMark: defaultRefillHighWaterMark, 200 capacity: 4096, 201 }, 202 203 // Max capacity pools. 204 "tags": poolPolicyDefault{ 205 size: 4096, 206 refillLowWaterMark: defaultRefillLowWaterMark, 207 refillHighWaterMark: defaultRefillHighWaterMark, 208 capacity: 0, 209 maxCapacity: 16, 210 }, 211 } 212 213 defaultBucketPoolPolicies = map[string]bucketPoolPolicyDefault{ 214 "bytes": bucketPoolPolicyDefault{ 215 buckets: []CapacityPoolPolicy{ 216 { 217 Capacity: intPtr(16), 218 PoolPolicy: PoolPolicy{ 219 Size: poolSizePtr(524288), 220 RefillLowWaterMark: &defaultRefillLowWaterMark, 221 RefillHighWaterMark: &defaultRefillHighWaterMark, 222 }, 223 }, 224 { 225 Capacity: intPtr(32), 226 PoolPolicy: PoolPolicy{ 227 Size: poolSizePtr(262144), 228 RefillLowWaterMark: &defaultRefillLowWaterMark, 229 RefillHighWaterMark: &defaultRefillHighWaterMark, 230 }, 231 }, 232 { 233 Capacity: intPtr(64), 234 PoolPolicy: PoolPolicy{ 235 Size: poolSizePtr(131072), 236 RefillLowWaterMark: &defaultRefillLowWaterMark, 237 RefillHighWaterMark: &defaultRefillHighWaterMark, 238 }, 239 }, 240 { 241 Capacity: intPtr(128), 242 PoolPolicy: PoolPolicy{ 243 Size: poolSizePtr(65536), 244 RefillLowWaterMark: &defaultRefillLowWaterMark, 245 RefillHighWaterMark: &defaultRefillHighWaterMark, 246 }, 247 }, 248 { 249 Capacity: intPtr(256), 250 PoolPolicy: PoolPolicy{ 251 Size: poolSizePtr(65536), 252 RefillLowWaterMark: &defaultRefillLowWaterMark, 253 RefillHighWaterMark: &defaultRefillHighWaterMark, 254 }, 255 }, 256 { 257 Capacity: intPtr(1440), 258 PoolPolicy: PoolPolicy{ 259 Size: poolSizePtr(16384), 260 RefillLowWaterMark: &defaultRefillLowWaterMark, 261 RefillHighWaterMark: &defaultRefillHighWaterMark, 262 }, 263 }, 264 { 265 Capacity: intPtr(4096), 266 PoolPolicy: PoolPolicy{ 267 Size: poolSizePtr(8192), 268 RefillLowWaterMark: &defaultRefillLowWaterMark, 269 RefillHighWaterMark: &defaultRefillHighWaterMark, 270 }, 271 }, 272 }, 273 }, 274 } 275 ) 276 277 // PoolingPolicy specifies the pooling policy. To add a new pool, follow these steps: 278 // 279 // 1. Add the pool to the struct below. 280 // 2. Add the default values to the defaultPoolPolicies or defaultBucketPoolPolicies map. 281 // 3. Add a call to initDefaultsAndValidate() for the new pool in the 282 // PoolingPolicy.InitDefaultsAndValidate() method. 283 type PoolingPolicy struct { 284 // The initial alloc size for a block. 285 BlockAllocSize *int `yaml:"blockAllocSize"` 286 287 // The thrift bytes pool max bytes slice allocation for a single binary field. 288 ThriftBytesPoolAllocSize *int `yaml:"thriftBytesPoolAllocSize"` 289 290 // The general pool type (currently only supported: simple). 291 Type *PoolingType `yaml:"type"` 292 293 // The Bytes pool buckets to use. 294 BytesPool BucketPoolPolicy `yaml:"bytesPool"` 295 296 // The policy for the checked bytes wrapper pool. 297 CheckedBytesWrapperPool PoolPolicy `yaml:"checkedBytesWrapperPool"` 298 299 // The policy for the Closers pool. 300 ClosersPool PoolPolicy `yaml:"closersPool"` 301 302 // The policy for the Context pool. 303 ContextPool PoolPolicy `yaml:"contextPool"` 304 305 // The policy for the DatabaseSeries pool. 306 SeriesPool PoolPolicy `yaml:"seriesPool"` 307 308 // The policy for the DatabaseBlock pool. 309 BlockPool PoolPolicy `yaml:"blockPool"` 310 311 // The policy for the Encoder pool. 312 EncoderPool PoolPolicy `yaml:"encoderPool"` 313 314 // The policy for the Iterator pool. 315 IteratorPool PoolPolicy `yaml:"iteratorPool"` 316 317 // The policy for the Segment Reader pool. 318 SegmentReaderPool PoolPolicy `yaml:"segmentReaderPool"` 319 320 // The policy for the Identifier pool. 321 IdentifierPool PoolPolicy `yaml:"identifierPool"` 322 323 // The policy for the FetchBlockMetadataResult pool. 324 FetchBlockMetadataResultsPool CapacityPoolPolicy `yaml:"fetchBlockMetadataResultsPool"` 325 326 // The policy for the FetchBlocksMetadataResults pool. 327 FetchBlocksMetadataResultsPool CapacityPoolPolicy `yaml:"fetchBlocksMetadataResultsPool"` 328 329 // The policy for the ReplicaMetadataSlicePool pool. 330 ReplicaMetadataSlicePool CapacityPoolPolicy `yaml:"replicaMetadataSlicePool"` 331 332 // The policy for the BlockMetadat pool. 333 BlockMetadataPool PoolPolicy `yaml:"blockMetadataPool"` 334 335 // The policy for the BlockMetadataSlice pool. 336 BlockMetadataSlicePool CapacityPoolPolicy `yaml:"blockMetadataSlicePool"` 337 338 // The policy for the BlocksMetadata pool. 339 BlocksMetadataPool PoolPolicy `yaml:"blocksMetadataPool"` 340 341 // The policy for the BlocksMetadataSlice pool. 342 BlocksMetadataSlicePool CapacityPoolPolicy `yaml:"blocksMetadataSlicePool"` 343 344 // The policy for the tags pool. 345 TagsPool MaxCapacityPoolPolicy `yaml:"tagsPool"` 346 347 // The policy for the tags iterator pool. 348 TagsIteratorPool PoolPolicy `yaml:"tagIteratorPool"` 349 350 // The policy for the index.ResultsPool. 351 IndexResultsPool PoolPolicy `yaml:"indexResultsPool"` 352 353 // The policy for the TagEncoderPool. 354 TagEncoderPool PoolPolicy `yaml:"tagEncoderPool"` 355 356 // The policy for the TagDecoderPool. 357 TagDecoderPool PoolPolicy `yaml:"tagDecoderPool"` 358 359 // The policy for the WriteBatchPool. 360 WriteBatchPool WriteBatchPoolPolicy `yaml:"writeBatchPool"` 361 362 // The policy for the BufferBucket pool. 363 BufferBucketPool PoolPolicy `yaml:"bufferBucketPool"` 364 365 // The policy for the BufferBucketVersions pool. 366 BufferBucketVersionsPool PoolPolicy `yaml:"bufferBucketVersionsPool"` 367 368 // The policy for the RetrieveRequestPool pool. 369 RetrieveRequestPool PoolPolicy `yaml:"retrieveRequestPool"` 370 371 // The policy for the PostingsListPool. 372 PostingsListPool PoolPolicy `yaml:"postingsListPool"` 373 } 374 375 // InitDefaultsAndValidate initializes all default values and validates the configuration 376 func (p *PoolingPolicy) InitDefaultsAndValidate() error { 377 if err := p.CheckedBytesWrapperPool.initDefaultsAndValidate("checkedBytesWrapper"); err != nil { 378 return err 379 } 380 if err := p.ClosersPool.initDefaultsAndValidate("closers"); err != nil { 381 return err 382 } 383 if err := p.ContextPool.initDefaultsAndValidate("context"); err != nil { 384 return err 385 } 386 if err := p.SeriesPool.initDefaultsAndValidate("series"); err != nil { 387 return err 388 } 389 if err := p.BlockPool.initDefaultsAndValidate("block"); err != nil { 390 return err 391 } 392 if err := p.EncoderPool.initDefaultsAndValidate("encoder"); err != nil { 393 return err 394 } 395 if err := p.IteratorPool.initDefaultsAndValidate("iterator"); err != nil { 396 return err 397 } 398 if err := p.SegmentReaderPool.initDefaultsAndValidate("segmentReader"); err != nil { 399 return err 400 } 401 if err := p.IdentifierPool.initDefaultsAndValidate("identifier"); err != nil { 402 return err 403 } 404 if err := p.FetchBlockMetadataResultsPool.initDefaultsAndValidate("fetchBlockMetadataResults"); err != nil { 405 return err 406 } 407 if err := p.FetchBlocksMetadataResultsPool.initDefaultsAndValidate("fetchBlocksMetadataResults"); err != nil { 408 return err 409 } 410 if err := p.ReplicaMetadataSlicePool.initDefaultsAndValidate("replicaMetadataSlice"); err != nil { 411 return err 412 } 413 if err := p.BlockMetadataPool.initDefaultsAndValidate("blockMetadata"); err != nil { 414 return err 415 } 416 if err := p.BlockMetadataSlicePool.initDefaultsAndValidate("blockMetadataSlice"); err != nil { 417 return err 418 } 419 if err := p.BlocksMetadataPool.initDefaultsAndValidate("blocksMetadata"); err != nil { 420 return err 421 } 422 if err := p.BlocksMetadataSlicePool.initDefaultsAndValidate("blocksMetadataSlice"); err != nil { 423 return err 424 } 425 if err := p.TagsPool.initDefaultsAndValidate("tags"); err != nil { 426 return err 427 } 428 if err := p.TagsIteratorPool.initDefaultsAndValidate("tagsIterator"); err != nil { 429 return err 430 } 431 if err := p.IndexResultsPool.initDefaultsAndValidate("indexResults"); err != nil { 432 return err 433 } 434 if err := p.TagEncoderPool.initDefaultsAndValidate("tagEncoder"); err != nil { 435 return err 436 } 437 if err := p.TagDecoderPool.initDefaultsAndValidate("tagDecoder"); err != nil { 438 return err 439 } 440 if err := p.PostingsListPool.initDefaultsAndValidate("postingsList"); err != nil { 441 return err 442 } 443 if err := p.BytesPool.initDefaultsAndValidate("bytes"); err != nil { 444 return err 445 } 446 if err := p.BufferBucketPool.initDefaultsAndValidate("bufferBucket"); err != nil { 447 return err 448 } 449 if err := p.BufferBucketVersionsPool.initDefaultsAndValidate("bufferBucketVersions"); err != nil { 450 return err 451 } 452 if err := p.RetrieveRequestPool.initDefaultsAndValidate("retrieveRequestPool"); err != nil { 453 return err 454 } 455 return nil 456 } 457 458 // BlockAllocSizeOrDefault returns the configured block alloc size if provided, 459 // or a default value otherwise. 460 func (p *PoolingPolicy) BlockAllocSizeOrDefault() int { 461 if p.BlockAllocSize != nil { 462 return *p.BlockAllocSize 463 } 464 465 return defaultBlockAllocSize 466 } 467 468 // ThriftBytesPoolAllocSizesOrDefault returns the configured thrift bytes pool 469 // max alloc size if provided, or a default value otherwise. 470 func (p *PoolingPolicy) ThriftBytesPoolAllocSizesOrDefault() []int { 471 if p.ThriftBytesPoolAllocSize != nil { 472 return []int{*p.ThriftBytesPoolAllocSize} 473 } 474 475 return defaultThriftBytesPoolAllocSizes 476 } 477 478 // TypeOrDefault returns the configured pooling type if provided, or a default 479 // value otherwise. 480 func (p *PoolingPolicy) TypeOrDefault() PoolingType { 481 if p.Type != nil { 482 return *p.Type 483 } 484 485 return defaultPoolingType 486 } 487 488 // PoolPolicy specifies a single pool policy. 489 type PoolPolicy struct { 490 // The size of the pool. 491 Size *pool.Size `yaml:"size"` 492 493 // The low watermark to start refilling the pool, if zero none. 494 RefillLowWaterMark *float64 `yaml:"lowWatermark"` 495 496 // The high watermark to stop refilling the pool, if zero none. 497 RefillHighWaterMark *float64 `yaml:"highWatermark"` 498 } 499 500 func (p *PoolPolicy) initDefaultsAndValidate(poolName string) error { 501 defaults, ok := defaultPoolPolicies[poolName] 502 if !ok { 503 return fmt.Errorf("no default values for pool: %s", poolName) 504 } 505 506 if p.Size == nil { 507 p.Size = &defaults.size 508 } 509 if p.RefillLowWaterMark == nil { 510 p.RefillLowWaterMark = &defaults.refillLowWaterMark 511 } 512 if p.RefillHighWaterMark == nil { 513 p.RefillHighWaterMark = &defaults.refillHighWaterMark 514 } 515 516 if *p.RefillLowWaterMark < 0 || *p.RefillLowWaterMark > 1 { 517 return fmt.Errorf( 518 "invalid lowWatermark value for %s pool, should be >= 0 and <= 1", poolName) 519 } 520 521 if *p.RefillHighWaterMark < 0 || *p.RefillHighWaterMark > 1 { 522 return fmt.Errorf( 523 "invalid lowWatermark value for %s pool, should be >= 0 and <= 1", poolName) 524 } 525 526 return nil 527 } 528 529 // SizeOrDefault returns the configured size if present, or a default value otherwise. 530 func (p *PoolPolicy) SizeOrDefault() pool.Size { 531 return *p.Size 532 } 533 534 // RefillLowWaterMarkOrDefault returns the configured refill low water mark if present, 535 // or a default value otherwise. 536 func (p *PoolPolicy) RefillLowWaterMarkOrDefault() float64 { 537 return *p.RefillLowWaterMark 538 } 539 540 // RefillHighWaterMarkOrDefault returns the configured refill high water mark if present, 541 // or a default value otherwise. 542 func (p *PoolPolicy) RefillHighWaterMarkOrDefault() float64 { 543 return *p.RefillHighWaterMark 544 } 545 546 // CapacityPoolPolicy specifies a single pool policy that has a 547 // per element capacity. 548 type CapacityPoolPolicy struct { 549 PoolPolicy `yaml:",inline"` 550 551 // The capacity of items in the pool. 552 Capacity *int `yaml:"capacity"` 553 } 554 555 // Validate validates the capacity pool policy config. 556 func (p *CapacityPoolPolicy) initDefaultsAndValidate(poolName string) error { 557 if err := p.PoolPolicy.initDefaultsAndValidate(poolName); err != nil { 558 return err 559 } 560 561 defaults, ok := defaultPoolPolicies[poolName] 562 if !ok { 563 return fmt.Errorf("no default values for pool: %s", poolName) 564 } 565 566 if p.Capacity == nil { 567 p.Capacity = &defaults.capacity 568 } 569 570 if *p.Capacity < 0 { 571 return fmt.Errorf("capacity of %s pool must be >= 0", poolName) 572 } 573 574 return nil 575 } 576 577 // CapacityOrDefault returns the configured capacity if present, or a default value otherwise. 578 func (p *CapacityPoolPolicy) CapacityOrDefault() int { 579 return *p.Capacity 580 } 581 582 // MaxCapacityPoolPolicy specifies a single pool policy that has a 583 // per element capacity, and a maximum allowed capacity as well. 584 type MaxCapacityPoolPolicy struct { 585 CapacityPoolPolicy `yaml:",inline"` 586 587 // The max capacity of items in the pool. 588 MaxCapacity *int `yaml:"maxCapacity"` 589 } 590 591 func (p *MaxCapacityPoolPolicy) initDefaultsAndValidate(poolName string) error { 592 if err := p.CapacityPoolPolicy.initDefaultsAndValidate(poolName); err != nil { 593 return err 594 } 595 596 defaults, ok := defaultPoolPolicies[poolName] 597 if !ok { 598 return fmt.Errorf("no default values for pool: %s", poolName) 599 } 600 601 if p.MaxCapacity == nil { 602 p.MaxCapacity = &defaults.maxCapacity 603 } 604 605 if *p.MaxCapacity < 0 { 606 return fmt.Errorf("maxCapacity of %s pool must be >= 0", poolName) 607 } 608 609 return nil 610 } 611 612 // MaxCapacityOrDefault returns the configured maximum capacity if present, or a 613 // default value otherwise. 614 func (p *MaxCapacityPoolPolicy) MaxCapacityOrDefault() int { 615 return *p.MaxCapacity 616 } 617 618 // BucketPoolPolicy specifies a bucket pool policy. 619 type BucketPoolPolicy struct { 620 // The pool buckets sizes to use 621 Buckets []CapacityPoolPolicy `yaml:"buckets"` 622 } 623 624 func (p *BucketPoolPolicy) initDefaultsAndValidate(poolName string) error { 625 defaults, ok := defaultBucketPoolPolicies[poolName] 626 if !ok { 627 return fmt.Errorf("no default values for pool: %s", poolName) 628 } 629 630 if p.Buckets == nil { 631 p.Buckets = defaults.buckets 632 } 633 634 for i, bucket := range p.Buckets { 635 // If the user provided buckets, but no values for refill low/high watermarks 636 // then set them to default values. 637 if bucket.RefillLowWaterMark == nil { 638 p.Buckets[i].RefillLowWaterMark = &defaultRefillLowWaterMark 639 } 640 if bucket.RefillHighWaterMark == nil { 641 p.Buckets[i].RefillHighWaterMark = &defaultRefillHighWaterMark 642 } 643 } 644 645 for _, bucket := range p.Buckets { 646 if bucket.Size == nil { 647 return fmt.Errorf("bucket size for pool %s cannot be nil", poolName) 648 } 649 if bucket.Capacity == nil { 650 return fmt.Errorf("bucket capacity for pool %s cannot be nil", poolName) 651 } 652 } 653 return nil 654 } 655 656 // WriteBatchPoolPolicy specifies the pooling policy for the WriteBatch pool. 657 type WriteBatchPoolPolicy struct { 658 // The size of the pool. 659 Size *int `yaml:"size"` 660 661 // InitialBatchSize controls the initial batch size for each WriteBatch when 662 // the pool is being constructed / refilled. 663 InitialBatchSize *int `yaml:"initialBatchSize"` 664 665 // MaxBatchSize controls the maximum size that a pooled WriteBatch can grow to 666 // and still remain in the pool. 667 MaxBatchSize *int `yaml:"maxBatchSize"` 668 } 669 670 func intPtr(x int) *int { 671 return &x 672 } 673 674 func poolSizePtr(x int) *pool.Size { 675 sz := pool.Size(x) 676 return &sz 677 }