get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/jetstream.go (about) 1 // Copyright 2019-2024 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "crypto/hmac" 18 "crypto/sha256" 19 "encoding/binary" 20 "encoding/hex" 21 "encoding/json" 22 "fmt" 23 "math" 24 "os" 25 "path/filepath" 26 "runtime/debug" 27 "strconv" 28 "strings" 29 "sync" 30 "sync/atomic" 31 "time" 32 33 "get.pme.sh/pnats/server/sysmem" 34 "github.com/minio/highwayhash" 35 "github.com/nats-io/nkeys" 36 "github.com/nats-io/nuid" 37 ) 38 39 // JetStreamConfig determines this server's configuration. 40 // MaxMemory and MaxStore are in bytes. 41 type JetStreamConfig struct { 42 MaxMemory int64 `json:"max_memory"` 43 MaxStore int64 `json:"max_storage"` 44 StoreDir string `json:"store_dir,omitempty"` 45 SyncInterval time.Duration `json:"sync_interval,omitempty"` 46 SyncAlways bool `json:"sync_always,omitempty"` 47 Domain string `json:"domain,omitempty"` 48 CompressOK bool `json:"compress_ok,omitempty"` 49 UniqueTag string `json:"unique_tag,omitempty"` 50 } 51 52 // Statistics about JetStream for this server. 53 type JetStreamStats struct { 54 Memory uint64 `json:"memory"` 55 Store uint64 `json:"storage"` 56 ReservedMemory uint64 `json:"reserved_memory"` 57 ReservedStore uint64 `json:"reserved_storage"` 58 Accounts int `json:"accounts"` 59 HAAssets int `json:"ha_assets"` 60 API JetStreamAPIStats `json:"api"` 61 } 62 63 type JetStreamAccountLimits struct { 64 MaxMemory int64 `json:"max_memory"` 65 MaxStore int64 `json:"max_storage"` 66 MaxStreams int `json:"max_streams"` 67 MaxConsumers int `json:"max_consumers"` 68 MaxAckPending int `json:"max_ack_pending"` 69 MemoryMaxStreamBytes int64 `json:"memory_max_stream_bytes"` 70 StoreMaxStreamBytes int64 `json:"storage_max_stream_bytes"` 71 MaxBytesRequired bool `json:"max_bytes_required"` 72 } 73 74 type JetStreamTier struct { 75 Memory uint64 `json:"memory"` 76 Store uint64 `json:"storage"` 77 ReservedMemory uint64 `json:"reserved_memory"` 78 ReservedStore uint64 `json:"reserved_storage"` 79 Streams int `json:"streams"` 80 Consumers int `json:"consumers"` 81 Limits JetStreamAccountLimits `json:"limits"` 82 } 83 84 // JetStreamAccountStats returns current statistics about the account's JetStream usage. 85 type JetStreamAccountStats struct { 86 JetStreamTier // in case tiers are used, reflects totals with limits not set 87 Domain string `json:"domain,omitempty"` 88 API JetStreamAPIStats `json:"api"` 89 Tiers map[string]JetStreamTier `json:"tiers,omitempty"` // indexed by tier name 90 } 91 92 type JetStreamAPIStats struct { 93 Total uint64 `json:"total"` 94 Errors uint64 `json:"errors"` 95 Inflight uint64 `json:"inflight,omitempty"` 96 } 97 98 // This is for internal accounting for JetStream for this server. 99 type jetStream struct { 100 // These are here first because of atomics on 32bit systems. 101 apiInflight int64 102 apiTotal int64 103 apiErrors int64 104 memReserved int64 105 storeReserved int64 106 memUsed int64 107 storeUsed int64 108 clustered int32 109 mu sync.RWMutex 110 srv *Server 111 config JetStreamConfig 112 cluster *jetStreamCluster 113 accounts map[string]*jsAccount 114 apiSubs *Sublist 115 started time.Time 116 117 // System level request to purge a stream move 118 accountPurge *subscription 119 120 // Some bools regarding general state. 121 metaRecovering bool 122 standAlone bool 123 oos bool 124 shuttingDown bool 125 126 // Atomic versions 127 disabled atomic.Bool 128 } 129 130 type remoteUsage struct { 131 tiers map[string]*jsaUsage // indexed by tier name 132 api uint64 133 err uint64 134 } 135 136 type jsaStorage struct { 137 total jsaUsage 138 local jsaUsage 139 } 140 141 // This represents a jetstream enabled account. 142 // Worth noting that we include the jetstream pointer, this is because 143 // in general we want to be very efficient when receiving messages on 144 // an internal sub for a stream, so we will direct link to the stream 145 // and walk backwards as needed vs multiple hash lookups and locks, etc. 146 type jsAccount struct { 147 mu sync.RWMutex 148 js *jetStream 149 account *Account 150 storeDir string 151 inflight sync.Map 152 streams map[string]*stream 153 templates map[string]*streamTemplate 154 store TemplateStore 155 156 // From server 157 sendq *ipQueue[*pubMsg] 158 159 // For limiting only running one checkAndSync at a time. 160 sync atomic.Bool 161 162 // Usage/limits related fields that will be protected by usageMu 163 usageMu sync.RWMutex 164 limits map[string]JetStreamAccountLimits // indexed by tierName 165 usage map[string]*jsaStorage // indexed by tierName 166 rusage map[string]*remoteUsage // indexed by node id 167 apiTotal uint64 168 apiErrors uint64 169 usageApi uint64 170 usageErr uint64 171 updatesPub string 172 updatesSub *subscription 173 lupdate time.Time 174 utimer *time.Timer 175 } 176 177 // Track general usage for this account. 178 type jsaUsage struct { 179 mem int64 180 store int64 181 } 182 183 // EnableJetStream will enable JetStream support on this server with the given configuration. 184 // A nil configuration will dynamically choose the limits and temporary file storage directory. 185 func (s *Server) EnableJetStream(config *JetStreamConfig) error { 186 if s.JetStreamEnabled() { 187 return fmt.Errorf("jetstream already enabled") 188 } 189 190 s.Noticef("Starting JetStream") 191 if config == nil || config.MaxMemory <= 0 || config.MaxStore <= 0 { 192 var storeDir, domain, uniqueTag string 193 var maxStore, maxMem int64 194 if config != nil { 195 storeDir, domain, uniqueTag = config.StoreDir, config.Domain, config.UniqueTag 196 maxStore, maxMem = config.MaxStore, config.MaxMemory 197 } 198 config = s.dynJetStreamConfig(storeDir, maxStore, maxMem) 199 if maxMem > 0 { 200 config.MaxMemory = maxMem 201 } 202 if domain != _EMPTY_ { 203 config.Domain = domain 204 } 205 if uniqueTag != _EMPTY_ { 206 config.UniqueTag = uniqueTag 207 } 208 s.Debugf("JetStream creating dynamic configuration - %s memory, %s disk", friendlyBytes(config.MaxMemory), friendlyBytes(config.MaxStore)) 209 } else if config.StoreDir != _EMPTY_ { 210 config.StoreDir = filepath.Join(config.StoreDir, JetStreamStoreDir) 211 } 212 213 cfg := *config 214 if cfg.StoreDir == _EMPTY_ { 215 cfg.StoreDir = filepath.Join(os.TempDir(), JetStreamStoreDir) 216 } 217 218 // We will consistently place the 'jetstream' directory under the storedir that was handed to us. Prior to 2.2.3 though 219 // we could have a directory on disk without the 'jetstream' directory. This will check and fix if needed. 220 if err := s.checkStoreDir(&cfg); err != nil { 221 return err 222 } 223 224 return s.enableJetStream(cfg) 225 } 226 227 // Function signature to generate a key encryption key. 228 type keyGen func(context []byte) ([]byte, error) 229 230 // Return a key generation function or nil if encryption not enabled. 231 // keyGen defined in filestore.go - keyGen func(iv, context []byte) []byte 232 func (s *Server) jsKeyGen(jsKey, info string) keyGen { 233 if ek := jsKey; ek != _EMPTY_ { 234 return func(context []byte) ([]byte, error) { 235 h := hmac.New(sha256.New, []byte(ek)) 236 if _, err := h.Write([]byte(info)); err != nil { 237 return nil, err 238 } 239 if _, err := h.Write(context); err != nil { 240 return nil, err 241 } 242 return h.Sum(nil), nil 243 } 244 } 245 return nil 246 } 247 248 // Decode the encrypted metafile. 249 func (s *Server) decryptMeta(sc StoreCipher, ekey, buf []byte, acc, context string) ([]byte, bool, error) { 250 if len(ekey) < minMetaKeySize { 251 return nil, false, errBadKeySize 252 } 253 var osc StoreCipher 254 switch sc { 255 case AES: 256 osc = ChaCha 257 case ChaCha: 258 osc = AES 259 } 260 type prfWithCipher struct { 261 keyGen 262 StoreCipher 263 } 264 var prfs []prfWithCipher 265 if prf := s.jsKeyGen(s.getOpts().JetStreamKey, acc); prf == nil { 266 return nil, false, errNoEncryption 267 } else { 268 // First of all, try our current encryption keys with both 269 // store cipher algorithms. 270 prfs = append(prfs, prfWithCipher{prf, sc}) 271 prfs = append(prfs, prfWithCipher{prf, osc}) 272 } 273 if prf := s.jsKeyGen(s.getOpts().JetStreamOldKey, acc); prf != nil { 274 // Then, if we have an old encryption key, try with also with 275 // both store cipher algorithms. 276 prfs = append(prfs, prfWithCipher{prf, sc}) 277 prfs = append(prfs, prfWithCipher{prf, osc}) 278 } 279 280 for i, prf := range prfs { 281 rb, err := prf.keyGen([]byte(context)) 282 if err != nil { 283 continue 284 } 285 kek, err := genEncryptionKey(prf.StoreCipher, rb) 286 if err != nil { 287 continue 288 } 289 ns := kek.NonceSize() 290 seed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil) 291 if err != nil { 292 continue 293 } 294 aek, err := genEncryptionKey(prf.StoreCipher, seed) 295 if err != nil { 296 continue 297 } 298 if aek.NonceSize() != kek.NonceSize() { 299 continue 300 } 301 plain, err := aek.Open(nil, buf[:ns], buf[ns:], nil) 302 if err != nil { 303 continue 304 } 305 return plain, i > 0, nil 306 } 307 return nil, false, fmt.Errorf("unable to recover keys") 308 } 309 310 // Check to make sure directory has the jetstream directory. 311 // We will have it properly configured here now regardless, so need to look inside. 312 func (s *Server) checkStoreDir(cfg *JetStreamConfig) error { 313 fis, _ := os.ReadDir(cfg.StoreDir) 314 // If we have nothing underneath us, could be just starting new, but if we see this we can check. 315 if len(fis) != 0 { 316 return nil 317 } 318 // Let's check the directory above. If it has us 'jetstream' but also other stuff that we can 319 // identify as accounts then we can fix. 320 fis, _ = os.ReadDir(filepath.Dir(cfg.StoreDir)) 321 // If just one that is us 'jetstream' and all is ok. 322 if len(fis) == 1 { 323 return nil 324 } 325 326 haveJetstreamDir := false 327 for _, fi := range fis { 328 if fi.Name() == JetStreamStoreDir { 329 haveJetstreamDir = true 330 break 331 } 332 } 333 334 for _, fi := range fis { 335 // Skip the 'jetstream' directory. 336 if fi.Name() == JetStreamStoreDir { 337 continue 338 } 339 // Let's see if this is an account. 340 if accName := fi.Name(); accName != _EMPTY_ { 341 _, ok := s.accounts.Load(accName) 342 if !ok && s.AccountResolver() != nil && nkeys.IsValidPublicAccountKey(accName) { 343 // Account is not local but matches the NKEY account public key, 344 // this is enough indication to move this directory, no need to 345 // fetch the account. 346 ok = true 347 } 348 // If this seems to be an account go ahead and move the directory. This will include all assets 349 // like streams and consumers. 350 if ok { 351 if !haveJetstreamDir { 352 err := os.Mkdir(filepath.Join(filepath.Dir(cfg.StoreDir), JetStreamStoreDir), defaultDirPerms) 353 if err != nil { 354 return err 355 } 356 haveJetstreamDir = true 357 } 358 old := filepath.Join(filepath.Dir(cfg.StoreDir), fi.Name()) 359 new := filepath.Join(cfg.StoreDir, fi.Name()) 360 s.Noticef("JetStream relocated account %q to %q", old, new) 361 if err := os.Rename(old, new); err != nil { 362 return err 363 } 364 } 365 } 366 } 367 368 return nil 369 } 370 371 // enableJetStream will start up the JetStream subsystem. 372 func (s *Server) enableJetStream(cfg JetStreamConfig) error { 373 js := &jetStream{srv: s, config: cfg, accounts: make(map[string]*jsAccount), apiSubs: NewSublistNoCache()} 374 s.gcbMu.Lock() 375 if s.gcbOutMax = s.getOpts().JetStreamMaxCatchup; s.gcbOutMax == 0 { 376 s.gcbOutMax = defaultMaxTotalCatchupOutBytes 377 } 378 s.gcbMu.Unlock() 379 380 s.js.Store(js) 381 382 // FIXME(dlc) - Allow memory only operation? 383 if stat, err := os.Stat(cfg.StoreDir); os.IsNotExist(err) { 384 if err := os.MkdirAll(cfg.StoreDir, defaultDirPerms); err != nil { 385 return fmt.Errorf("could not create storage directory - %v", err) 386 } 387 } else { 388 // Make sure its a directory and that we can write to it. 389 if stat == nil || !stat.IsDir() { 390 return fmt.Errorf("storage directory is not a directory") 391 } 392 tmpfile, err := os.CreateTemp(cfg.StoreDir, "_test_") 393 if err != nil { 394 return fmt.Errorf("storage directory is not writable") 395 } 396 tmpfile.Close() 397 os.Remove(tmpfile.Name()) 398 } 399 400 // JetStream is an internal service so we need to make sure we have a system account. 401 // This system account will export the JetStream service endpoints. 402 if s.SystemAccount() == nil { 403 s.SetDefaultSystemAccount() 404 } 405 406 opts := s.getOpts() 407 if !opts.DisableJetStreamBanner { 408 s.Noticef(" _ ___ _____ ___ _____ ___ ___ _ __ __") 409 s.Noticef(" _ | | __|_ _/ __|_ _| _ \\ __| /_\\ | \\/ |") 410 s.Noticef("| || | _| | | \\__ \\ | | | / _| / _ \\| |\\/| |") 411 s.Noticef(" \\__/|___| |_| |___/ |_| |_|_\\___/_/ \\_\\_| |_|") 412 s.Noticef("") 413 s.Noticef(" https://docs.nats.io/jetstream") 414 s.Noticef("") 415 } 416 s.Noticef("---------------- JETSTREAM ----------------") 417 s.Noticef(" Max Memory: %s", friendlyBytes(cfg.MaxMemory)) 418 s.Noticef(" Max Storage: %s", friendlyBytes(cfg.MaxStore)) 419 s.Noticef(" Store Directory: \"%s\"", cfg.StoreDir) 420 if cfg.Domain != _EMPTY_ { 421 s.Noticef(" Domain: %s", cfg.Domain) 422 } 423 424 if ek := opts.JetStreamKey; ek != _EMPTY_ { 425 s.Noticef(" Encryption: %s", opts.JetStreamCipher) 426 } 427 s.Noticef("-------------------------------------------") 428 429 // Setup our internal subscriptions. 430 if err := s.setJetStreamExportSubs(); err != nil { 431 return fmt.Errorf("setting up internal jetstream subscriptions failed: %v", err) 432 } 433 434 // Setup our internal system exports. 435 s.Debugf(" Exports:") 436 s.Debugf(" %s", jsAllAPI) 437 s.setupJetStreamExports() 438 439 standAlone, canExtend := s.standAloneMode(), s.canExtendOtherDomain() 440 if standAlone && canExtend && s.getOpts().JetStreamExtHint != jsWillExtend { 441 canExtend = false 442 s.Noticef("Standalone server started in clustered mode do not support extending domains") 443 s.Noticef(`Manually disable standalone mode by setting the JetStream Option "extension_hint: %s"`, jsWillExtend) 444 } 445 446 // Indicate if we will be standalone for checking resource reservations, etc. 447 js.setJetStreamStandAlone(standAlone && !canExtend) 448 449 // Enable accounts and restore state before starting clustering. 450 if err := s.enableJetStreamAccounts(); err != nil { 451 return err 452 } 453 454 // If we are in clustered mode go ahead and start the meta controller. 455 if !standAlone || canExtend { 456 if err := s.enableJetStreamClustering(); err != nil { 457 return err 458 } 459 } 460 461 // Mark when we are up and running. 462 js.setStarted() 463 464 return nil 465 } 466 467 const jsNoExtend = "no_extend" 468 const jsWillExtend = "will_extend" 469 470 // This will check if we have a solicited leafnode that shares the system account 471 // and extension is not manually disabled 472 func (s *Server) canExtendOtherDomain() bool { 473 opts := s.getOpts() 474 sysAcc := s.SystemAccount().GetName() 475 for _, r := range opts.LeafNode.Remotes { 476 if r.LocalAccount == sysAcc { 477 for _, denySub := range r.DenyImports { 478 if subjectIsSubsetMatch(denySub, raftAllSubj) { 479 return false 480 } 481 } 482 return true 483 } 484 } 485 return false 486 } 487 488 func (s *Server) updateJetStreamInfoStatus(enabled bool) { 489 s.mu.Lock() 490 s.info.JetStream = enabled 491 s.mu.Unlock() 492 } 493 494 // restartJetStream will try to re-enable JetStream during a reload if it had been disabled during runtime. 495 func (s *Server) restartJetStream() error { 496 opts := s.getOpts() 497 cfg := JetStreamConfig{ 498 StoreDir: opts.StoreDir, 499 SyncInterval: opts.SyncInterval, 500 SyncAlways: opts.SyncAlways, 501 MaxMemory: opts.JetStreamMaxMemory, 502 MaxStore: opts.JetStreamMaxStore, 503 Domain: opts.JetStreamDomain, 504 } 505 s.Noticef("Restarting JetStream") 506 err := s.EnableJetStream(&cfg) 507 if err != nil { 508 s.Warnf("Can't start JetStream: %v", err) 509 return s.DisableJetStream() 510 } 511 s.updateJetStreamInfoStatus(true) 512 return nil 513 } 514 515 // checkJetStreamExports will check if we have the JS exports setup 516 // on the system account, and if not go ahead and set them up. 517 func (s *Server) checkJetStreamExports() { 518 if sacc := s.SystemAccount(); sacc != nil { 519 sacc.mu.RLock() 520 se := sacc.getServiceExport(jsAllAPI) 521 sacc.mu.RUnlock() 522 if se == nil { 523 s.setupJetStreamExports() 524 } 525 } 526 } 527 528 func (s *Server) setupJetStreamExports() { 529 // Setup our internal system export. 530 if err := s.SystemAccount().AddServiceExport(jsAllAPI, nil); err != nil { 531 s.Warnf("Error setting up jetstream service exports: %v", err) 532 } 533 } 534 535 func (s *Server) jetStreamOOSPending() (wasPending bool) { 536 if js := s.getJetStream(); js != nil { 537 js.mu.Lock() 538 wasPending = js.oos 539 js.oos = true 540 js.mu.Unlock() 541 } 542 return wasPending 543 } 544 545 func (s *Server) setJetStreamDisabled() { 546 if js := s.getJetStream(); js != nil { 547 js.disabled.Store(true) 548 } 549 } 550 551 func (s *Server) handleOutOfSpace(mset *stream) { 552 if s.JetStreamEnabled() && !s.jetStreamOOSPending() { 553 var stream string 554 if mset != nil { 555 stream = mset.name() 556 s.Errorf("JetStream out of %s resources, will be DISABLED", mset.Store().Type()) 557 } else { 558 s.Errorf("JetStream out of resources, will be DISABLED") 559 } 560 561 go s.DisableJetStream() 562 563 adv := &JSServerOutOfSpaceAdvisory{ 564 TypedEvent: TypedEvent{ 565 Type: JSServerOutOfStorageAdvisoryType, 566 ID: nuid.Next(), 567 Time: time.Now().UTC(), 568 }, 569 Server: s.Name(), 570 ServerID: s.ID(), 571 Stream: stream, 572 Cluster: s.cachedClusterName(), 573 Domain: s.getOpts().JetStreamDomain, 574 } 575 s.publishAdvisory(nil, JSAdvisoryServerOutOfStorage, adv) 576 } 577 } 578 579 // DisableJetStream will turn off JetStream and signals in clustered mode 580 // to have the metacontroller remove us from the peer list. 581 func (s *Server) DisableJetStream() error { 582 if !s.JetStreamEnabled() { 583 return nil 584 } 585 586 s.setJetStreamDisabled() 587 588 if s.JetStreamIsClustered() { 589 isLeader := s.JetStreamIsLeader() 590 js, cc := s.getJetStreamCluster() 591 if js == nil { 592 s.shutdownJetStream() 593 return nil 594 } 595 js.mu.RLock() 596 meta := cc.meta 597 js.mu.RUnlock() 598 599 if meta != nil { 600 if isLeader { 601 s.Warnf("JetStream initiating meta leader transfer") 602 meta.StepDown() 603 select { 604 case <-s.quitCh: 605 return nil 606 case <-time.After(2 * time.Second): 607 } 608 if !s.JetStreamIsCurrent() { 609 s.Warnf("JetStream timeout waiting for meta leader transfer") 610 } 611 } 612 meta.Delete() 613 } 614 } 615 616 // Update our info status. 617 s.updateJetStreamInfoStatus(false) 618 619 // Normal shutdown. 620 s.shutdownJetStream() 621 622 // Shut down the RAFT groups. 623 s.shutdownRaftNodes() 624 625 return nil 626 } 627 628 func (s *Server) enableJetStreamAccounts() error { 629 // If we have no configured accounts setup then setup imports on global account. 630 if s.globalAccountOnly() { 631 gacc := s.GlobalAccount() 632 gacc.mu.Lock() 633 if len(gacc.jsLimits) == 0 { 634 gacc.jsLimits = defaultJSAccountTiers 635 } 636 gacc.mu.Unlock() 637 if err := s.configJetStream(gacc); err != nil { 638 return err 639 } 640 } else if err := s.configAllJetStreamAccounts(); err != nil { 641 return fmt.Errorf("Error enabling jetstream on configured accounts: %v", err) 642 } 643 return nil 644 } 645 646 // enableAllJetStreamServiceImportsAndMappings turns on all service imports and mappings for jetstream for this account. 647 func (a *Account) enableAllJetStreamServiceImportsAndMappings() error { 648 a.mu.RLock() 649 s := a.srv 650 a.mu.RUnlock() 651 652 if s == nil { 653 return fmt.Errorf("jetstream account not registered") 654 } 655 656 if !a.serviceImportExists(jsAllAPI) { 657 // Capture si so we can turn on implicit sharing with JetStream layer. 658 // Make sure to set "to" otherwise will incur performance slow down. 659 si, err := a.addServiceImport(s.SystemAccount(), jsAllAPI, jsAllAPI, nil) 660 if err != nil { 661 return fmt.Errorf("Error setting up jetstream service imports for account: %v", err) 662 } 663 a.mu.Lock() 664 si.share = true 665 a.mu.Unlock() 666 } 667 668 // Check if we have a Domain specified. 669 // If so add in a subject mapping that will allow local connected clients to reach us here as well. 670 if opts := s.getOpts(); opts.JetStreamDomain != _EMPTY_ { 671 mappings := generateJSMappingTable(opts.JetStreamDomain) 672 a.mu.RLock() 673 for _, m := range a.mappings { 674 delete(mappings, m.src) 675 } 676 a.mu.RUnlock() 677 for src, dest := range mappings { 678 if err := a.AddMapping(src, dest); err != nil { 679 s.Errorf("Error adding JetStream domain mapping: %v", err) 680 } 681 } 682 } 683 684 return nil 685 } 686 687 // enableJetStreamInfoServiceImportOnly will enable the single service import responder. 688 // Should we do them all regardless? 689 func (a *Account) enableJetStreamInfoServiceImportOnly() error { 690 // Check if this import would be overshadowed. This can happen when accounts 691 // are importing from another account for JS access. 692 if a.serviceImportShadowed(JSApiAccountInfo) { 693 return nil 694 } 695 696 return a.enableAllJetStreamServiceImportsAndMappings() 697 } 698 699 func (s *Server) configJetStream(acc *Account) error { 700 if acc == nil { 701 return nil 702 } 703 acc.mu.RLock() 704 jsLimits := acc.jsLimits 705 acc.mu.RUnlock() 706 if jsLimits != nil { 707 // Check if already enabled. This can be during a reload. 708 if acc.JetStreamEnabled() { 709 if err := acc.enableAllJetStreamServiceImportsAndMappings(); err != nil { 710 return err 711 } 712 if err := acc.UpdateJetStreamLimits(jsLimits); err != nil { 713 return err 714 } 715 } else { 716 if err := acc.EnableJetStream(jsLimits); err != nil { 717 return err 718 } 719 if s.gateway.enabled { 720 s.switchAccountToInterestMode(acc.GetName()) 721 } 722 } 723 } else if acc != s.SystemAccount() { 724 if acc.JetStreamEnabled() { 725 acc.DisableJetStream() 726 } 727 // We will setup basic service imports to respond to 728 // requests if JS is enabled for this account. 729 if err := acc.enableJetStreamInfoServiceImportOnly(); err != nil { 730 return err 731 } 732 } 733 return nil 734 } 735 736 // configAllJetStreamAccounts walk all configured accounts and turn on jetstream if requested. 737 func (s *Server) configAllJetStreamAccounts() error { 738 // Check to see if system account has been enabled. We could arrive here via reload and 739 // a non-default system account. 740 s.checkJetStreamExports() 741 742 // Bail if server not enabled. If it was enabled and a reload turns it off 743 // that will be handled elsewhere. 744 js := s.getJetStream() 745 if js == nil { 746 return nil 747 } 748 749 // Snapshot into our own list. Might not be needed. 750 s.mu.RLock() 751 if s.sys != nil { 752 // clustered stream removal will perform this cleanup as well 753 // this is mainly for initial cleanup 754 saccName := s.sys.account.Name 755 accStoreDirs, _ := os.ReadDir(js.config.StoreDir) 756 for _, acc := range accStoreDirs { 757 if accName := acc.Name(); accName != saccName { 758 // no op if not empty 759 accDir := filepath.Join(js.config.StoreDir, accName) 760 os.Remove(filepath.Join(accDir, streamsDir)) 761 os.Remove(accDir) 762 } 763 } 764 } 765 766 var jsAccounts []*Account 767 s.accounts.Range(func(k, v any) bool { 768 jsAccounts = append(jsAccounts, v.(*Account)) 769 return true 770 }) 771 accounts := &s.accounts 772 s.mu.RUnlock() 773 774 // Process any jetstream enabled accounts here. These will be accounts we are 775 // already aware of at startup etc. 776 for _, acc := range jsAccounts { 777 if err := s.configJetStream(acc); err != nil { 778 return err 779 } 780 } 781 782 // Now walk all the storage we have and resolve any accounts that we did not process already. 783 // This is important in resolver/operator models. 784 fis, _ := os.ReadDir(js.config.StoreDir) 785 for _, fi := range fis { 786 if accName := fi.Name(); accName != _EMPTY_ { 787 // Only load up ones not already loaded since they are processed above. 788 if _, ok := accounts.Load(accName); !ok { 789 if acc, err := s.lookupAccount(accName); err != nil && acc != nil { 790 if err := s.configJetStream(acc); err != nil { 791 return err 792 } 793 } 794 } 795 } 796 } 797 798 return nil 799 } 800 801 // Mark our started time. 802 func (js *jetStream) setStarted() { 803 js.mu.Lock() 804 defer js.mu.Unlock() 805 js.started = time.Now() 806 } 807 808 func (js *jetStream) isEnabled() bool { 809 if js == nil { 810 return false 811 } 812 return !js.disabled.Load() 813 } 814 815 // Mark that we will be in standlone mode. 816 func (js *jetStream) setJetStreamStandAlone(isStandAlone bool) { 817 if js == nil { 818 return 819 } 820 js.mu.Lock() 821 defer js.mu.Unlock() 822 if js.standAlone = isStandAlone; js.standAlone { 823 // Update our server atomic. 824 js.srv.isMetaLeader.Store(true) 825 js.accountPurge, _ = js.srv.systemSubscribe(JSApiAccountPurge, _EMPTY_, false, nil, js.srv.jsLeaderAccountPurgeRequest) 826 } else if js.accountPurge != nil { 827 js.srv.sysUnsubscribe(js.accountPurge) 828 } 829 } 830 831 // JetStreamEnabled reports if jetstream is enabled for this server. 832 func (s *Server) JetStreamEnabled() bool { 833 return s.getJetStream().isEnabled() 834 } 835 836 // JetStreamEnabledForDomain will report if any servers have JetStream enabled within this domain. 837 func (s *Server) JetStreamEnabledForDomain() bool { 838 if s.JetStreamEnabled() { 839 return true 840 } 841 842 var jsFound bool 843 // If we are here we do not have JetStream enabled for ourselves, but we need to check all connected servers. 844 // TODO(dlc) - Could optimize and memoize this. 845 s.nodeToInfo.Range(func(k, v interface{}) bool { 846 // This should not be dependent on online status, so only check js. 847 if v.(nodeInfo).js { 848 jsFound = true 849 return false 850 } 851 return true 852 }) 853 854 return jsFound 855 } 856 857 // Will signal that all pull requests for consumers on this server are now invalid. 858 func (s *Server) signalPullConsumers() { 859 js := s.getJetStream() 860 if js == nil { 861 return 862 } 863 864 js.mu.RLock() 865 defer js.mu.RUnlock() 866 867 // In case we have stale pending requests. 868 const hdr = "NATS/1.0 409 Server Shutdown\r\n" + JSPullRequestPendingMsgs + ": %d\r\n" + JSPullRequestPendingBytes + ": %d\r\n\r\n" 869 var didSend bool 870 871 for _, jsa := range js.accounts { 872 jsa.mu.RLock() 873 for _, stream := range jsa.streams { 874 stream.mu.RLock() 875 for _, o := range stream.consumers { 876 o.mu.RLock() 877 // Only signal on R1. 878 if o.cfg.Replicas <= 1 { 879 for reply, wr := range o.pendingRequests() { 880 shdr := fmt.Sprintf(hdr, wr.n, wr.b) 881 o.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, []byte(shdr), nil, nil, 0)) 882 didSend = true 883 } 884 } 885 o.mu.RUnlock() 886 } 887 stream.mu.RUnlock() 888 } 889 jsa.mu.RUnlock() 890 } 891 // Give time for migration information to make it out of our server. 892 if didSend { 893 time.Sleep(50 * time.Millisecond) 894 } 895 } 896 897 // Helper for determining if we are shutting down. 898 func (js *jetStream) isShuttingDown() bool { 899 js.mu.RLock() 900 defer js.mu.RUnlock() 901 return js.shuttingDown 902 } 903 904 // Shutdown jetstream for this server. 905 func (s *Server) shutdownJetStream() { 906 js := s.getJetStream() 907 if js == nil { 908 return 909 } 910 911 s.Noticef("Initiating JetStream Shutdown...") 912 defer s.Noticef("JetStream Shutdown") 913 914 // If we have folks blocked on sync requests, unblock. 915 // Send 1 is enough, but use select in case they were all present. 916 select { 917 case s.syncOutSem <- struct{}{}: 918 default: 919 } 920 921 var _a [512]*Account 922 accounts := _a[:0] 923 924 js.mu.Lock() 925 // Collect accounts. 926 for _, jsa := range js.accounts { 927 if a := jsa.acc(); a != nil { 928 accounts = append(accounts, a) 929 } 930 } 931 accPurgeSub := js.accountPurge 932 js.accountPurge = nil 933 // Signal we are shutting down. 934 js.shuttingDown = true 935 js.mu.Unlock() 936 937 if accPurgeSub != nil { 938 s.sysUnsubscribe(accPurgeSub) 939 } 940 941 for _, a := range accounts { 942 a.removeJetStream() 943 } 944 945 s.js.Store(nil) 946 947 js.mu.Lock() 948 js.accounts = nil 949 950 var qch chan struct{} 951 952 if cc := js.cluster; cc != nil { 953 if cc.qch != nil { 954 qch = cc.qch 955 cc.qch = nil 956 } 957 js.stopUpdatesSub() 958 if cc.c != nil { 959 cc.c.closeConnection(ClientClosed) 960 cc.c = nil 961 } 962 cc.meta = nil 963 } 964 js.mu.Unlock() 965 966 // If we were clustered signal the monitor cluster go routine. 967 // We will wait for a bit for it to close. 968 // Do this without the lock. 969 if qch != nil { 970 select { 971 case qch <- struct{}{}: 972 select { 973 case <-qch: 974 case <-time.After(2 * time.Second): 975 s.Warnf("Did not receive signal for successful shutdown of cluster routine") 976 } 977 default: 978 } 979 } 980 } 981 982 // JetStreamConfig will return the current config. Useful if the system 983 // created a dynamic configuration. A copy is returned. 984 func (s *Server) JetStreamConfig() *JetStreamConfig { 985 var c *JetStreamConfig 986 if js := s.getJetStream(); js != nil { 987 copy := js.config 988 c = &(copy) 989 } 990 return c 991 } 992 993 // StoreDir returns the current JetStream directory. 994 func (s *Server) StoreDir() string { 995 js := s.getJetStream() 996 if js == nil { 997 return _EMPTY_ 998 } 999 return js.config.StoreDir 1000 } 1001 1002 // JetStreamNumAccounts returns the number of enabled accounts this server is tracking. 1003 func (s *Server) JetStreamNumAccounts() int { 1004 js := s.getJetStream() 1005 if js == nil { 1006 return 0 1007 } 1008 js.mu.Lock() 1009 defer js.mu.Unlock() 1010 return len(js.accounts) 1011 } 1012 1013 // JetStreamReservedResources returns the reserved resources if JetStream is enabled. 1014 func (s *Server) JetStreamReservedResources() (int64, int64, error) { 1015 js := s.getJetStream() 1016 if js == nil { 1017 return -1, -1, NewJSNotEnabledForAccountError() 1018 } 1019 js.mu.RLock() 1020 defer js.mu.RUnlock() 1021 return js.memReserved, js.storeReserved, nil 1022 } 1023 1024 func (s *Server) getJetStream() *jetStream { 1025 return s.js.Load() 1026 } 1027 1028 func (a *Account) assignJetStreamLimits(limits map[string]JetStreamAccountLimits) { 1029 a.mu.Lock() 1030 a.jsLimits = limits 1031 a.mu.Unlock() 1032 } 1033 1034 // EnableJetStream will enable JetStream on this account with the defined limits. 1035 // This is a helper for JetStreamEnableAccount. 1036 func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) error { 1037 a.mu.RLock() 1038 s := a.srv 1039 a.mu.RUnlock() 1040 1041 if s == nil { 1042 return fmt.Errorf("jetstream account not registered") 1043 } 1044 1045 if s.SystemAccount() == a { 1046 return fmt.Errorf("jetstream can not be enabled on the system account") 1047 } 1048 1049 s.mu.RLock() 1050 if s.sys == nil { 1051 s.mu.RUnlock() 1052 return ErrServerNotRunning 1053 } 1054 sendq := s.sys.sendq 1055 s.mu.RUnlock() 1056 1057 // No limits means we dynamically set up limits. 1058 // We also place limits here so we know that the account is configured for JetStream. 1059 if len(limits) == 0 { 1060 limits = defaultJSAccountTiers 1061 } 1062 1063 a.assignJetStreamLimits(limits) 1064 1065 js := s.getJetStream() 1066 if js == nil { 1067 return NewJSNotEnabledError() 1068 } 1069 1070 js.mu.Lock() 1071 if jsa, ok := js.accounts[a.Name]; ok { 1072 a.mu.Lock() 1073 a.js = jsa 1074 a.mu.Unlock() 1075 js.mu.Unlock() 1076 return a.enableAllJetStreamServiceImportsAndMappings() 1077 } 1078 1079 // Check the limits against existing reservations. 1080 if err := js.sufficientResources(limits); err != nil { 1081 js.mu.Unlock() 1082 return err 1083 } 1084 1085 sysNode := s.Node() 1086 1087 jsa := &jsAccount{js: js, account: a, limits: limits, streams: make(map[string]*stream), sendq: sendq, usage: make(map[string]*jsaStorage)} 1088 jsa.storeDir = filepath.Join(js.config.StoreDir, a.Name) 1089 1090 // A single server does not need to do the account updates at this point. 1091 if js.cluster != nil || !s.standAloneMode() { 1092 jsa.usageMu.Lock() 1093 jsa.utimer = time.AfterFunc(usageTick, jsa.sendClusterUsageUpdateTimer) 1094 // Cluster mode updates to resource usage. System internal prevents echos. 1095 jsa.updatesPub = fmt.Sprintf(jsaUpdatesPubT, a.Name, sysNode) 1096 jsa.updatesSub, _ = s.sysSubscribe(fmt.Sprintf(jsaUpdatesSubT, a.Name), jsa.remoteUpdateUsage) 1097 jsa.usageMu.Unlock() 1098 } 1099 1100 js.accounts[a.Name] = jsa 1101 // Stamp inside account as well. Needs to be done under js's lock. 1102 a.mu.Lock() 1103 a.js = jsa 1104 a.mu.Unlock() 1105 js.mu.Unlock() 1106 1107 // Create the proper imports here. 1108 if err := a.enableAllJetStreamServiceImportsAndMappings(); err != nil { 1109 return err 1110 } 1111 1112 s.Debugf("Enabled JetStream for account %q", a.Name) 1113 if l, ok := limits[_EMPTY_]; ok { 1114 s.Debugf(" Max Memory: %s", friendlyBytes(l.MaxMemory)) 1115 s.Debugf(" Max Storage: %s", friendlyBytes(l.MaxStore)) 1116 } else { 1117 for t, l := range limits { 1118 s.Debugf(" Tier: %s", t) 1119 s.Debugf(" Max Memory: %s", friendlyBytes(l.MaxMemory)) 1120 s.Debugf(" Max Storage: %s", friendlyBytes(l.MaxStore)) 1121 } 1122 } 1123 1124 // Clean up any old snapshots that were orphaned while staging. 1125 os.RemoveAll(filepath.Join(js.config.StoreDir, snapStagingDir)) 1126 1127 sdir := filepath.Join(jsa.storeDir, streamsDir) 1128 if _, err := os.Stat(sdir); os.IsNotExist(err) { 1129 if err := os.MkdirAll(sdir, defaultDirPerms); err != nil { 1130 return fmt.Errorf("could not create storage streams directory - %v", err) 1131 } 1132 // Just need to make sure we can write to the directory. 1133 // Remove the directory will create later if needed. 1134 os.RemoveAll(sdir) 1135 // when empty remove parent directory, which may have been created as well 1136 os.Remove(jsa.storeDir) 1137 } else { 1138 // Restore any state here. 1139 s.Debugf("Recovering JetStream state for account %q", a.Name) 1140 } 1141 1142 // Check templates first since messsage sets will need proper ownership. 1143 // FIXME(dlc) - Make this consistent. 1144 tdir := filepath.Join(jsa.storeDir, tmplsDir) 1145 if stat, err := os.Stat(tdir); err == nil && stat.IsDir() { 1146 key := sha256.Sum256([]byte("templates")) 1147 hh, err := highwayhash.New64(key[:]) 1148 if err != nil { 1149 return err 1150 } 1151 fis, _ := os.ReadDir(tdir) 1152 for _, fi := range fis { 1153 metafile := filepath.Join(tdir, fi.Name(), JetStreamMetaFile) 1154 metasum := filepath.Join(tdir, fi.Name(), JetStreamMetaFileSum) 1155 buf, err := os.ReadFile(metafile) 1156 if err != nil { 1157 s.Warnf(" Error reading StreamTemplate metafile %q: %v", metasum, err) 1158 continue 1159 } 1160 if _, err := os.Stat(metasum); os.IsNotExist(err) { 1161 s.Warnf(" Missing StreamTemplate checksum for %q", metasum) 1162 continue 1163 } 1164 sum, err := os.ReadFile(metasum) 1165 if err != nil { 1166 s.Warnf(" Error reading StreamTemplate checksum %q: %v", metasum, err) 1167 continue 1168 } 1169 hh.Reset() 1170 hh.Write(buf) 1171 checksum := hex.EncodeToString(hh.Sum(nil)) 1172 if checksum != string(sum) { 1173 s.Warnf(" StreamTemplate checksums do not match %q vs %q", sum, checksum) 1174 continue 1175 } 1176 var cfg StreamTemplateConfig 1177 if err := json.Unmarshal(buf, &cfg); err != nil { 1178 s.Warnf(" Error unmarshalling StreamTemplate metafile: %v", err) 1179 continue 1180 } 1181 cfg.Config.Name = _EMPTY_ 1182 if _, err := a.addStreamTemplate(&cfg); err != nil { 1183 s.Warnf(" Error recreating StreamTemplate %q: %v", cfg.Name, err) 1184 continue 1185 } 1186 } 1187 } 1188 1189 // Collect consumers, do after all streams. 1190 type ce struct { 1191 mset *stream 1192 odir string 1193 } 1194 var consumers []*ce 1195 1196 // Collect any interest policy streams to check for 1197 // https://github.com/nats-io/nats-server/issues/3612 1198 var ipstreams []*stream 1199 1200 // Remember if we should be encrypted and what cipher we think we should use. 1201 encrypted := s.getOpts().JetStreamKey != _EMPTY_ 1202 plaintext := true 1203 sc := s.getOpts().JetStreamCipher 1204 1205 // Now recover the streams. 1206 fis, _ := os.ReadDir(sdir) 1207 for _, fi := range fis { 1208 mdir := filepath.Join(sdir, fi.Name()) 1209 // Check for partially deleted streams. They are marked with "." prefix. 1210 if strings.HasPrefix(fi.Name(), tsep) { 1211 go os.RemoveAll(mdir) 1212 continue 1213 } 1214 key := sha256.Sum256([]byte(fi.Name())) 1215 hh, err := highwayhash.New64(key[:]) 1216 if err != nil { 1217 return err 1218 } 1219 metafile := filepath.Join(mdir, JetStreamMetaFile) 1220 metasum := filepath.Join(mdir, JetStreamMetaFileSum) 1221 if _, err := os.Stat(metafile); os.IsNotExist(err) { 1222 s.Warnf(" Missing stream metafile for %q", metafile) 1223 continue 1224 } 1225 buf, err := os.ReadFile(metafile) 1226 if err != nil { 1227 s.Warnf(" Error reading metafile %q: %v", metafile, err) 1228 continue 1229 } 1230 if _, err := os.Stat(metasum); os.IsNotExist(err) { 1231 s.Warnf(" Missing stream checksum file %q", metasum) 1232 continue 1233 } 1234 sum, err := os.ReadFile(metasum) 1235 if err != nil { 1236 s.Warnf(" Error reading Stream metafile checksum %q: %v", metasum, err) 1237 continue 1238 } 1239 hh.Write(buf) 1240 checksum := hex.EncodeToString(hh.Sum(nil)) 1241 if checksum != string(sum) { 1242 s.Warnf(" Stream metafile %q: checksums do not match %q vs %q", metafile, sum, checksum) 1243 continue 1244 } 1245 1246 // Track if we are converting ciphers. 1247 var convertingCiphers bool 1248 1249 // Check if we are encrypted. 1250 keyFile := filepath.Join(mdir, JetStreamMetaFileKey) 1251 keyBuf, err := os.ReadFile(keyFile) 1252 if err == nil { 1253 s.Debugf(" Stream metafile is encrypted, reading encrypted keyfile") 1254 if len(keyBuf) < minMetaKeySize { 1255 s.Warnf(" Bad stream encryption key length of %d", len(keyBuf)) 1256 continue 1257 } 1258 // Decode the buffer before proceeding. 1259 var nbuf []byte 1260 nbuf, convertingCiphers, err = s.decryptMeta(sc, keyBuf, buf, a.Name, fi.Name()) 1261 if err != nil { 1262 s.Warnf(" Error decrypting our stream metafile: %v", err) 1263 continue 1264 } 1265 buf = nbuf 1266 plaintext = false 1267 } 1268 1269 var cfg FileStreamInfo 1270 if err := json.Unmarshal(buf, &cfg); err != nil { 1271 s.Warnf(" Error unmarshalling stream metafile %q: %v", metafile, err) 1272 continue 1273 } 1274 1275 if cfg.Template != _EMPTY_ { 1276 if err := jsa.addStreamNameToTemplate(cfg.Template, cfg.Name); err != nil { 1277 s.Warnf(" Error adding stream %q to template %q: %v", cfg.Name, cfg.Template, err) 1278 } 1279 } 1280 1281 // We had a bug that set a default de dupe window on mirror, despite that being not a valid config 1282 fixCfgMirrorWithDedupWindow(&cfg.StreamConfig) 1283 1284 // We had a bug that could allow subjects in that had prefix or suffix spaces. We check for that here 1285 // and will patch them on the fly for now. We will warn about them. 1286 var hadSubjErr bool 1287 for i, subj := range cfg.StreamConfig.Subjects { 1288 if !IsValidSubject(subj) { 1289 s.Warnf(" Detected bad subject %q while adding stream %q, will attempt to repair", subj, cfg.Name) 1290 if nsubj := strings.TrimSpace(subj); IsValidSubject(nsubj) { 1291 s.Warnf(" Bad subject %q repaired to %q", subj, nsubj) 1292 cfg.StreamConfig.Subjects[i] = nsubj 1293 } else { 1294 s.Warnf(" Error recreating stream %q: %v", cfg.Name, "invalid subject") 1295 hadSubjErr = true 1296 break 1297 } 1298 } 1299 } 1300 if hadSubjErr { 1301 continue 1302 } 1303 1304 // The other possible bug is assigning subjects to mirrors, so check for that and patch as well. 1305 if cfg.StreamConfig.Mirror != nil && len(cfg.StreamConfig.Subjects) > 0 { 1306 s.Warnf(" Detected subjects on a mirrored stream %q, will remove", cfg.Name) 1307 cfg.StreamConfig.Subjects = nil 1308 } 1309 1310 s.Noticef(" Starting restore for stream '%s > %s'", a.Name, cfg.StreamConfig.Name) 1311 rt := time.Now() 1312 1313 // Log if we are converting from plaintext to encrypted. 1314 if encrypted { 1315 if plaintext { 1316 s.Noticef(" Encrypting stream '%s > %s'", a.Name, cfg.StreamConfig.Name) 1317 } else if convertingCiphers { 1318 s.Noticef(" Converting to %s for stream '%s > %s'", sc, a.Name, cfg.StreamConfig.Name) 1319 // Remove the key file to have system regenerate with the new cipher. 1320 os.Remove(keyFile) 1321 } 1322 } 1323 1324 // Add in the stream. 1325 mset, err := a.addStream(&cfg.StreamConfig) 1326 if err != nil { 1327 s.Warnf(" Error recreating stream %q: %v", cfg.Name, err) 1328 // If we removed a keyfile from above make sure to put it back. 1329 if convertingCiphers { 1330 err := os.WriteFile(keyFile, keyBuf, defaultFilePerms) 1331 if err != nil { 1332 s.Warnf(" Error replacing meta keyfile for stream %q: %v", cfg.Name, err) 1333 } 1334 } 1335 continue 1336 } 1337 if !cfg.Created.IsZero() { 1338 mset.setCreatedTime(cfg.Created) 1339 } 1340 1341 state := mset.state() 1342 s.Noticef(" Restored %s messages for stream '%s > %s' in %v", 1343 comma(int64(state.Msgs)), mset.accName(), mset.name(), time.Since(rt).Round(time.Millisecond)) 1344 1345 // Collect to check for dangling messages. 1346 // TODO(dlc) - Can be removed eventually. 1347 if cfg.StreamConfig.Retention == InterestPolicy { 1348 ipstreams = append(ipstreams, mset) 1349 } 1350 1351 // Now do the consumers. 1352 odir := filepath.Join(sdir, fi.Name(), consumerDir) 1353 consumers = append(consumers, &ce{mset, odir}) 1354 } 1355 1356 for _, e := range consumers { 1357 ofis, _ := os.ReadDir(e.odir) 1358 if len(ofis) > 0 { 1359 s.Noticef(" Recovering %d consumers for stream - '%s > %s'", len(ofis), e.mset.accName(), e.mset.name()) 1360 } 1361 for _, ofi := range ofis { 1362 metafile := filepath.Join(e.odir, ofi.Name(), JetStreamMetaFile) 1363 metasum := filepath.Join(e.odir, ofi.Name(), JetStreamMetaFileSum) 1364 if _, err := os.Stat(metafile); os.IsNotExist(err) { 1365 s.Warnf(" Missing consumer metafile %q", metafile) 1366 continue 1367 } 1368 buf, err := os.ReadFile(metafile) 1369 if err != nil { 1370 s.Warnf(" Error reading consumer metafile %q: %v", metafile, err) 1371 continue 1372 } 1373 if _, err := os.Stat(metasum); os.IsNotExist(err) { 1374 s.Warnf(" Missing consumer checksum for %q", metasum) 1375 continue 1376 } 1377 1378 // Check if we are encrypted. 1379 if key, err := os.ReadFile(filepath.Join(e.odir, ofi.Name(), JetStreamMetaFileKey)); err == nil { 1380 s.Debugf(" Consumer metafile is encrypted, reading encrypted keyfile") 1381 // Decode the buffer before proceeding. 1382 ctxName := e.mset.name() + tsep + ofi.Name() 1383 nbuf, _, err := s.decryptMeta(sc, key, buf, a.Name, ctxName) 1384 if err != nil { 1385 s.Warnf(" Error decrypting our consumer metafile: %v", err) 1386 continue 1387 } 1388 buf = nbuf 1389 } 1390 1391 var cfg FileConsumerInfo 1392 if err := json.Unmarshal(buf, &cfg); err != nil { 1393 s.Warnf(" Error unmarshalling consumer metafile %q: %v", metafile, err) 1394 continue 1395 } 1396 isEphemeral := !isDurableConsumer(&cfg.ConsumerConfig) 1397 if isEphemeral { 1398 // This is an ephermal consumer and this could fail on restart until 1399 // the consumer can reconnect. We will create it as a durable and switch it. 1400 cfg.ConsumerConfig.Durable = ofi.Name() 1401 } 1402 obs, err := e.mset.addConsumerWithAssignment(&cfg.ConsumerConfig, _EMPTY_, nil, true, ActionCreateOrUpdate) 1403 if err != nil { 1404 s.Warnf(" Error adding consumer %q: %v", cfg.Name, err) 1405 continue 1406 } 1407 if isEphemeral { 1408 obs.switchToEphemeral() 1409 } 1410 if !cfg.Created.IsZero() { 1411 obs.setCreatedTime(cfg.Created) 1412 } 1413 lseq := e.mset.lastSeq() 1414 obs.mu.Lock() 1415 err = obs.readStoredState(lseq) 1416 obs.mu.Unlock() 1417 if err != nil { 1418 s.Warnf(" Error restoring consumer %q state: %v", cfg.Name, err) 1419 } 1420 } 1421 } 1422 1423 // Make sure to cleanup any old remaining snapshots. 1424 os.RemoveAll(filepath.Join(jsa.storeDir, snapsDir)) 1425 1426 // Check interest policy streams for auto cleanup. 1427 for _, mset := range ipstreams { 1428 mset.checkForOrphanMsgs() 1429 mset.checkConsumerReplication() 1430 } 1431 1432 s.Debugf("JetStream state for account %q recovered", a.Name) 1433 1434 return nil 1435 } 1436 1437 // Return whether we require MaxBytes to be set and if > 0 an upper limit for stream size exists 1438 // Both limits are independent of each other. 1439 func (a *Account) maxBytesLimits(cfg *StreamConfig) (bool, int64) { 1440 a.mu.RLock() 1441 jsa := a.js 1442 a.mu.RUnlock() 1443 if jsa == nil { 1444 return false, 0 1445 } 1446 jsa.usageMu.RLock() 1447 selectedLimits, _, ok := jsa.selectLimits(cfg) 1448 jsa.usageMu.RUnlock() 1449 if !ok { 1450 return false, 0 1451 } 1452 maxStreamBytes := int64(0) 1453 if cfg.Storage == MemoryStorage { 1454 maxStreamBytes = selectedLimits.MemoryMaxStreamBytes 1455 } else { 1456 maxStreamBytes = selectedLimits.StoreMaxStreamBytes 1457 } 1458 return selectedLimits.MaxBytesRequired, maxStreamBytes 1459 } 1460 1461 // NumStreams will return how many streams we have. 1462 func (a *Account) numStreams() int { 1463 a.mu.RLock() 1464 jsa := a.js 1465 a.mu.RUnlock() 1466 if jsa == nil { 1467 return 0 1468 } 1469 jsa.mu.Lock() 1470 n := len(jsa.streams) 1471 jsa.mu.Unlock() 1472 return n 1473 } 1474 1475 // Streams will return all known streams. 1476 func (a *Account) streams() []*stream { 1477 return a.filteredStreams(_EMPTY_) 1478 } 1479 1480 func (a *Account) filteredStreams(filter string) []*stream { 1481 a.mu.RLock() 1482 jsa := a.js 1483 a.mu.RUnlock() 1484 1485 if jsa == nil { 1486 return nil 1487 } 1488 1489 jsa.mu.Lock() 1490 defer jsa.mu.Unlock() 1491 1492 var msets []*stream 1493 for _, mset := range jsa.streams { 1494 if filter != _EMPTY_ { 1495 for _, subj := range mset.cfg.Subjects { 1496 if SubjectsCollide(filter, subj) { 1497 msets = append(msets, mset) 1498 break 1499 } 1500 } 1501 } else { 1502 msets = append(msets, mset) 1503 } 1504 } 1505 1506 return msets 1507 } 1508 1509 // lookupStream will lookup a stream by name. 1510 func (a *Account) lookupStream(name string) (*stream, error) { 1511 a.mu.RLock() 1512 jsa := a.js 1513 a.mu.RUnlock() 1514 1515 if jsa == nil { 1516 return nil, NewJSNotEnabledForAccountError() 1517 } 1518 jsa.mu.Lock() 1519 defer jsa.mu.Unlock() 1520 1521 mset, ok := jsa.streams[name] 1522 if !ok { 1523 return nil, NewJSStreamNotFoundError() 1524 } 1525 return mset, nil 1526 } 1527 1528 // UpdateJetStreamLimits will update the account limits for a JetStream enabled account. 1529 func (a *Account) UpdateJetStreamLimits(limits map[string]JetStreamAccountLimits) error { 1530 a.mu.RLock() 1531 s, jsa := a.srv, a.js 1532 a.mu.RUnlock() 1533 1534 if s == nil { 1535 return fmt.Errorf("jetstream account not registered") 1536 } 1537 js := s.getJetStream() 1538 if js == nil { 1539 return NewJSNotEnabledError() 1540 } 1541 if jsa == nil { 1542 return NewJSNotEnabledForAccountError() 1543 } 1544 1545 if len(limits) == 0 { 1546 limits = defaultJSAccountTiers 1547 } 1548 1549 // Calculate the delta between what we have and what we want. 1550 jsa.usageMu.RLock() 1551 dl := diffCheckedLimits(jsa.limits, limits) 1552 jsa.usageMu.RUnlock() 1553 1554 js.mu.Lock() 1555 // Check the limits against existing reservations. 1556 if err := js.sufficientResources(dl); err != nil { 1557 js.mu.Unlock() 1558 return err 1559 } 1560 js.mu.Unlock() 1561 1562 // Update 1563 jsa.usageMu.Lock() 1564 jsa.limits = limits 1565 jsa.usageMu.Unlock() 1566 1567 return nil 1568 } 1569 1570 func diffCheckedLimits(a, b map[string]JetStreamAccountLimits) map[string]JetStreamAccountLimits { 1571 diff := map[string]JetStreamAccountLimits{} 1572 for t, la := range a { 1573 // in a, not in b will return 0 1574 lb := b[t] 1575 diff[t] = JetStreamAccountLimits{ 1576 MaxMemory: lb.MaxMemory - la.MaxMemory, 1577 MaxStore: lb.MaxStore - la.MaxStore, 1578 } 1579 } 1580 for t, lb := range b { 1581 if la, ok := a[t]; !ok { 1582 // only in b not in a. (in a and b already covered) 1583 diff[t] = JetStreamAccountLimits{ 1584 MaxMemory: lb.MaxMemory - la.MaxMemory, 1585 MaxStore: lb.MaxStore - la.MaxStore, 1586 } 1587 } 1588 } 1589 return diff 1590 } 1591 1592 // Return reserved bytes for memory and store for this account on this server. 1593 // Lock should be held. 1594 func (jsa *jsAccount) reservedStorage(tier string) (mem, store uint64) { 1595 for _, mset := range jsa.streams { 1596 cfg := &mset.cfg 1597 if tier == _EMPTY_ || tier == tierName(cfg) && cfg.MaxBytes > 0 { 1598 switch cfg.Storage { 1599 case FileStorage: 1600 store += uint64(cfg.MaxBytes) 1601 case MemoryStorage: 1602 mem += uint64(cfg.MaxBytes) 1603 } 1604 } 1605 } 1606 return mem, store 1607 } 1608 1609 // Return reserved bytes for memory and store for this account in clustered mode. 1610 // js lock should be held. 1611 func reservedStorage(sas map[string]*streamAssignment, tier string) (mem, store uint64) { 1612 for _, sa := range sas { 1613 cfg := sa.Config 1614 if tier == _EMPTY_ || tier == tierName(cfg) && cfg.MaxBytes > 0 { 1615 switch cfg.Storage { 1616 case FileStorage: 1617 store += uint64(cfg.MaxBytes) 1618 case MemoryStorage: 1619 mem += uint64(cfg.MaxBytes) 1620 } 1621 } 1622 } 1623 return mem, store 1624 } 1625 1626 // JetStreamUsage reports on JetStream usage and limits for an account. 1627 func (a *Account) JetStreamUsage() JetStreamAccountStats { 1628 a.mu.RLock() 1629 jsa, aname := a.js, a.Name 1630 accJsLimits := a.jsLimits 1631 a.mu.RUnlock() 1632 1633 var stats JetStreamAccountStats 1634 if jsa != nil { 1635 js := jsa.js 1636 js.mu.RLock() 1637 cc := js.cluster 1638 singleServer := cc == nil 1639 jsa.mu.RLock() 1640 jsa.usageMu.RLock() 1641 stats.Memory, stats.Store = jsa.storageTotals() 1642 stats.Domain = js.config.Domain 1643 stats.API = JetStreamAPIStats{ 1644 Total: jsa.apiTotal, 1645 Errors: jsa.apiErrors, 1646 } 1647 if singleServer { 1648 stats.ReservedMemory, stats.ReservedStore = jsa.reservedStorage(_EMPTY_) 1649 } else { 1650 stats.ReservedMemory, stats.ReservedStore = reservedStorage(cc.streams[aname], _EMPTY_) 1651 } 1652 l, defaultTier := jsa.limits[_EMPTY_] 1653 if defaultTier { 1654 stats.Limits = l 1655 } else { 1656 skipped := 0 1657 stats.Tiers = make(map[string]JetStreamTier) 1658 for t, total := range jsa.usage { 1659 if _, ok := jsa.limits[t]; !ok && (*total) == (jsaStorage{}) { 1660 // skip tiers not present that don't contain a count 1661 // In case this shows an empty stream, that tier will be added when iterating over streams 1662 skipped++ 1663 } else { 1664 tier := JetStreamTier{ 1665 Memory: uint64(total.total.mem), 1666 Store: uint64(total.total.store), 1667 Limits: jsa.limits[t], 1668 } 1669 if singleServer { 1670 tier.ReservedMemory, tier.ReservedStore = jsa.reservedStorage(t) 1671 } else { 1672 tier.ReservedMemory, tier.ReservedStore = reservedStorage(cc.streams[aname], t) 1673 } 1674 stats.Tiers[t] = tier 1675 } 1676 } 1677 if len(accJsLimits) != len(jsa.usage)-skipped { 1678 // insert unused limits 1679 for t, lim := range accJsLimits { 1680 if _, ok := stats.Tiers[t]; !ok { 1681 tier := JetStreamTier{Limits: lim} 1682 if singleServer { 1683 tier.ReservedMemory, tier.ReservedStore = jsa.reservedStorage(t) 1684 } else { 1685 tier.ReservedMemory, tier.ReservedStore = reservedStorage(cc.streams[aname], t) 1686 } 1687 stats.Tiers[t] = tier 1688 } 1689 } 1690 } 1691 } 1692 jsa.usageMu.RUnlock() 1693 1694 // Clustered 1695 if cc := js.cluster; cc != nil { 1696 sas := cc.streams[aname] 1697 if defaultTier { 1698 stats.Streams = len(sas) 1699 stats.ReservedMemory, stats.ReservedStore = reservedStorage(sas, _EMPTY_) 1700 } 1701 for _, sa := range sas { 1702 stats.Consumers += len(sa.consumers) 1703 if !defaultTier { 1704 tier := tierName(sa.Config) 1705 u, ok := stats.Tiers[tier] 1706 if !ok { 1707 u = JetStreamTier{} 1708 } 1709 u.Streams++ 1710 stats.Streams++ 1711 u.Consumers += len(sa.consumers) 1712 stats.Tiers[tier] = u 1713 } 1714 } 1715 } else { 1716 if defaultTier { 1717 stats.Streams = len(jsa.streams) 1718 } 1719 for _, mset := range jsa.streams { 1720 consCount := mset.numConsumers() 1721 stats.Consumers += consCount 1722 if !defaultTier { 1723 u, ok := stats.Tiers[mset.tier] 1724 if !ok { 1725 u = JetStreamTier{} 1726 } 1727 u.Streams++ 1728 stats.Streams++ 1729 u.Consumers += consCount 1730 stats.Tiers[mset.tier] = u 1731 } 1732 } 1733 } 1734 jsa.mu.RUnlock() 1735 js.mu.RUnlock() 1736 } 1737 return stats 1738 } 1739 1740 // DisableJetStream will disable JetStream for this account. 1741 func (a *Account) DisableJetStream() error { 1742 return a.removeJetStream() 1743 } 1744 1745 // removeJetStream is called when JetStream has been disabled for this account. 1746 func (a *Account) removeJetStream() error { 1747 a.mu.Lock() 1748 s := a.srv 1749 a.js = nil 1750 a.mu.Unlock() 1751 1752 if s == nil { 1753 return fmt.Errorf("jetstream account not registered") 1754 } 1755 1756 js := s.getJetStream() 1757 if js == nil { 1758 return NewJSNotEnabledForAccountError() 1759 } 1760 1761 return js.disableJetStream(js.lookupAccount(a)) 1762 } 1763 1764 // Disable JetStream for the account. 1765 func (js *jetStream) disableJetStream(jsa *jsAccount) error { 1766 if jsa == nil || jsa.account == nil { 1767 return NewJSNotEnabledForAccountError() 1768 } 1769 1770 js.mu.Lock() 1771 delete(js.accounts, jsa.account.Name) 1772 js.mu.Unlock() 1773 1774 jsa.delete() 1775 1776 return nil 1777 } 1778 1779 // jetStreamConfigured reports whether the account has JetStream configured, regardless of this 1780 // servers JetStream status. 1781 func (a *Account) jetStreamConfigured() bool { 1782 if a == nil { 1783 return false 1784 } 1785 a.mu.RLock() 1786 defer a.mu.RUnlock() 1787 return len(a.jsLimits) > 0 1788 } 1789 1790 // JetStreamEnabled is a helper to determine if jetstream is enabled for an account. 1791 func (a *Account) JetStreamEnabled() bool { 1792 if a == nil { 1793 return false 1794 } 1795 a.mu.RLock() 1796 enabled := a.js != nil 1797 a.mu.RUnlock() 1798 return enabled 1799 } 1800 1801 func (jsa *jsAccount) remoteUpdateUsage(sub *subscription, c *client, _ *Account, subject, _ string, msg []byte) { 1802 // jsa.js.srv is immutable and guaranteed to no be nil, so no lock needed. 1803 s := jsa.js.srv 1804 1805 jsa.usageMu.Lock() 1806 defer jsa.usageMu.Unlock() 1807 1808 if len(msg) < minUsageUpdateLen { 1809 s.Warnf("Ignoring remote usage update with size too short") 1810 return 1811 } 1812 var rnode string 1813 if li := strings.LastIndexByte(subject, btsep); li > 0 && li < len(subject) { 1814 rnode = subject[li+1:] 1815 } 1816 if rnode == _EMPTY_ { 1817 s.Warnf("Received remote usage update with no remote node") 1818 return 1819 } 1820 rUsage, ok := jsa.rusage[rnode] 1821 if !ok { 1822 if jsa.rusage == nil { 1823 jsa.rusage = make(map[string]*remoteUsage) 1824 } 1825 rUsage = &remoteUsage{tiers: make(map[string]*jsaUsage)} 1826 jsa.rusage[rnode] = rUsage 1827 } 1828 updateTotal := func(tierName string, memUsed, storeUsed int64) { 1829 total, ok := jsa.usage[tierName] 1830 if !ok { 1831 total = &jsaStorage{} 1832 jsa.usage[tierName] = total 1833 } 1834 // Update the usage for this remote. 1835 if usage := rUsage.tiers[tierName]; usage != nil { 1836 // Decrement our old values. 1837 total.total.mem -= usage.mem 1838 total.total.store -= usage.store 1839 usage.mem, usage.store = memUsed, storeUsed 1840 } else { 1841 rUsage.tiers[tierName] = &jsaUsage{memUsed, storeUsed} 1842 } 1843 total.total.mem += memUsed 1844 total.total.store += storeUsed 1845 } 1846 1847 var le = binary.LittleEndian 1848 apiTotal, apiErrors := le.Uint64(msg[16:]), le.Uint64(msg[24:]) 1849 memUsed, storeUsed := int64(le.Uint64(msg[0:])), int64(le.Uint64(msg[8:])) 1850 1851 // We later extended the data structure to support multiple tiers 1852 var excessRecordCnt uint32 1853 var tierName string 1854 1855 if len(msg) >= usageMultiTiersLen { 1856 excessRecordCnt = le.Uint32(msg[minUsageUpdateLen:]) 1857 length := le.Uint64(msg[minUsageUpdateLen+4:]) 1858 // Need to protect past this point in case this is wrong. 1859 if uint64(len(msg)) < usageMultiTiersLen+length { 1860 s.Warnf("Received corrupt remote usage update") 1861 return 1862 } 1863 tierName = string(msg[usageMultiTiersLen : usageMultiTiersLen+length]) 1864 msg = msg[usageMultiTiersLen+length:] 1865 } 1866 updateTotal(tierName, memUsed, storeUsed) 1867 for ; excessRecordCnt > 0 && len(msg) >= usageRecordLen; excessRecordCnt-- { 1868 memUsed, storeUsed := int64(le.Uint64(msg[0:])), int64(le.Uint64(msg[8:])) 1869 length := le.Uint64(msg[16:]) 1870 if uint64(len(msg)) < usageRecordLen+length { 1871 s.Warnf("Received corrupt remote usage update on excess record") 1872 return 1873 } 1874 tierName = string(msg[usageRecordLen : usageRecordLen+length]) 1875 msg = msg[usageRecordLen+length:] 1876 updateTotal(tierName, memUsed, storeUsed) 1877 } 1878 jsa.apiTotal -= rUsage.api 1879 jsa.apiErrors -= rUsage.err 1880 rUsage.api = apiTotal 1881 rUsage.err = apiErrors 1882 jsa.apiTotal += apiTotal 1883 jsa.apiErrors += apiErrors 1884 } 1885 1886 // When we detect a skew of some sort this will verify the usage reporting is correct. 1887 // No locks should be held. 1888 func (jsa *jsAccount) checkAndSyncUsage(tierName string, storeType StorageType) { 1889 // This will run in a separate go routine, so check that we are only running once. 1890 if !jsa.sync.CompareAndSwap(false, true) { 1891 return 1892 } 1893 defer jsa.sync.Store(false) 1894 1895 // Hold the account read lock and the usage lock while we calculate. 1896 // We scope by tier and storage type, but if R3 File has 200 streams etc. could 1897 // show a pause. I did test with > 100 non-active streams and was 80-200ns or so. 1898 // Should be rare this gets called as well. 1899 jsa.mu.RLock() 1900 defer jsa.mu.RUnlock() 1901 js := jsa.js 1902 if js == nil { 1903 return 1904 } 1905 s := js.srv 1906 1907 // We need to collect the stream stores before we acquire the usage lock since in storeUpdates the 1908 // stream lock could be held if deletion are inline with storing a new message, e.g. via limits. 1909 var stores []StreamStore 1910 for _, mset := range jsa.streams { 1911 mset.mu.RLock() 1912 if mset.tier == tierName && mset.stype == storeType && mset.store != nil { 1913 stores = append(stores, mset.store) 1914 } 1915 mset.mu.RUnlock() 1916 } 1917 1918 // Now range and qualify, hold usage lock to prevent updates. 1919 jsa.usageMu.Lock() 1920 defer jsa.usageMu.Unlock() 1921 1922 usage, ok := jsa.usage[tierName] 1923 if !ok { 1924 return 1925 } 1926 1927 // Collect current total for all stream stores that matched. 1928 var total int64 1929 var state StreamState 1930 for _, store := range stores { 1931 store.FastState(&state) 1932 total += int64(state.Bytes) 1933 } 1934 1935 var needClusterUpdate bool 1936 // If we do not match on our calculations compute delta and adjust. 1937 if storeType == MemoryStorage { 1938 if total != usage.local.mem { 1939 s.Warnf("MemStore usage drift of %v vs %v detected for account %q", 1940 friendlyBytes(total), friendlyBytes(usage.local.mem), jsa.account.GetName()) 1941 delta := total - usage.local.mem 1942 usage.local.mem += delta 1943 usage.total.mem += delta 1944 atomic.AddInt64(&js.memUsed, delta) 1945 needClusterUpdate = true 1946 } 1947 } else { 1948 if total != usage.local.store { 1949 s.Warnf("FileStore usage drift of %v vs %v detected for account %q", 1950 friendlyBytes(total), friendlyBytes(usage.local.store), jsa.account.GetName()) 1951 delta := total - usage.local.store 1952 usage.local.store += delta 1953 usage.total.store += delta 1954 atomic.AddInt64(&js.storeUsed, delta) 1955 needClusterUpdate = true 1956 } 1957 } 1958 1959 // Publish our local updates if in clustered mode. 1960 if needClusterUpdate && js.isClusteredNoLock() { 1961 jsa.sendClusterUsageUpdate() 1962 } 1963 } 1964 1965 // Updates accounting on in use memory and storage. This is called from locally 1966 // by the lower storage layers. 1967 func (jsa *jsAccount) updateUsage(tierName string, storeType StorageType, delta int64) { 1968 // jsa.js is immutable and cannot be nil, so ok w/o lock. 1969 js := jsa.js 1970 // updateUsage() may be invoked under the mset's lock, so we can't get 1971 // the js' lock to check if clustered. So use this function that make 1972 // use of an atomic to do the check without having data race reports. 1973 isClustered := js.isClusteredNoLock() 1974 1975 var needsCheck bool 1976 jsa.usageMu.Lock() 1977 s, ok := jsa.usage[tierName] 1978 if !ok { 1979 s = &jsaStorage{} 1980 jsa.usage[tierName] = s 1981 } 1982 if storeType == MemoryStorage { 1983 s.local.mem += delta 1984 s.total.mem += delta 1985 atomic.AddInt64(&js.memUsed, delta) 1986 needsCheck = s.local.mem < 0 1987 } else { 1988 s.local.store += delta 1989 s.total.store += delta 1990 atomic.AddInt64(&js.storeUsed, delta) 1991 needsCheck = s.local.store < 0 1992 } 1993 // Publish our local updates if in clustered mode. 1994 if isClustered { 1995 jsa.sendClusterUsageUpdate() 1996 } 1997 jsa.usageMu.Unlock() 1998 1999 if needsCheck { 2000 // We could be holding the stream lock from up in the stack, and this 2001 // will want the jsa lock, which would violate locking order. 2002 // So do this in a Go routine. The function will check if it is already running. 2003 go jsa.checkAndSyncUsage(tierName, storeType) 2004 } 2005 } 2006 2007 var usageTick = 1500 * time.Millisecond 2008 2009 func (jsa *jsAccount) sendClusterUsageUpdateTimer() { 2010 jsa.usageMu.Lock() 2011 defer jsa.usageMu.Unlock() 2012 jsa.sendClusterUsageUpdate() 2013 if jsa.utimer != nil { 2014 jsa.utimer.Reset(usageTick) 2015 } 2016 } 2017 2018 // For usage fields. 2019 const ( 2020 minUsageUpdateLen = 32 2021 stackUsageUpdate = 72 2022 usageRecordLen = 24 2023 usageMultiTiersLen = 44 2024 apiStatsAndNumTiers = 20 2025 minUsageUpdateWindow = 250 * time.Millisecond 2026 ) 2027 2028 // Send updates to our account usage for this server. 2029 // jsa.usageMu lock should be held. 2030 func (jsa *jsAccount) sendClusterUsageUpdate() { 2031 // These values are absolute so we can limit send rates. 2032 now := time.Now() 2033 if now.Sub(jsa.lupdate) < minUsageUpdateWindow { 2034 return 2035 } 2036 jsa.lupdate = now 2037 2038 lenUsage := len(jsa.usage) 2039 if lenUsage == 0 { 2040 return 2041 } 2042 // every base record contains mem/store/len(tier) as well as the tier name 2043 l := usageRecordLen * lenUsage 2044 for tier := range jsa.usage { 2045 l += len(tier) 2046 } 2047 // first record contains api/usage errors as well as count for extra base records 2048 l += apiStatsAndNumTiers 2049 2050 var raw [stackUsageUpdate]byte 2051 var b []byte 2052 if l > stackUsageUpdate { 2053 b = make([]byte, l) 2054 } else { 2055 b = raw[:l] 2056 } 2057 2058 var i int 2059 var le = binary.LittleEndian 2060 for tier, usage := range jsa.usage { 2061 le.PutUint64(b[i+0:], uint64(usage.local.mem)) 2062 le.PutUint64(b[i+8:], uint64(usage.local.store)) 2063 if i == 0 { 2064 le.PutUint64(b[16:], jsa.usageApi) 2065 le.PutUint64(b[24:], jsa.usageErr) 2066 le.PutUint32(b[32:], uint32(len(jsa.usage)-1)) 2067 le.PutUint64(b[36:], uint64(len(tier))) 2068 copy(b[usageMultiTiersLen:], tier) 2069 i = usageMultiTiersLen + len(tier) 2070 } else { 2071 le.PutUint64(b[i+16:], uint64(len(tier))) 2072 copy(b[i+usageRecordLen:], tier) 2073 i += usageRecordLen + len(tier) 2074 } 2075 } 2076 jsa.sendq.push(newPubMsg(nil, jsa.updatesPub, _EMPTY_, nil, nil, b, noCompression, false, false)) 2077 } 2078 2079 func (js *jetStream) wouldExceedLimits(storeType StorageType, sz int) bool { 2080 var ( 2081 total *int64 2082 max int64 2083 ) 2084 if storeType == MemoryStorage { 2085 total, max = &js.memUsed, js.config.MaxMemory 2086 } else { 2087 total, max = &js.storeUsed, js.config.MaxStore 2088 } 2089 return atomic.LoadInt64(total) > (max + int64(sz)) 2090 } 2091 2092 func (js *jetStream) limitsExceeded(storeType StorageType) bool { 2093 return js.wouldExceedLimits(storeType, 0) 2094 } 2095 2096 func tierName(cfg *StreamConfig) string { 2097 // TODO (mh) this is where we could select based off a placement tag as well "qos:tier" 2098 replicas := cfg.Replicas 2099 if replicas == 0 { 2100 replicas = 1 2101 } 2102 return fmt.Sprintf("R%d", replicas) 2103 } 2104 2105 func isSameTier(cfgA, cfgB *StreamConfig) bool { 2106 // TODO (mh) this is where we could select based off a placement tag as well "qos:tier" 2107 return cfgA.Replicas == cfgB.Replicas 2108 } 2109 2110 func (jsa *jsAccount) jetStreamAndClustered() (*jetStream, bool) { 2111 jsa.mu.RLock() 2112 js := jsa.js 2113 jsa.mu.RUnlock() 2114 return js, js.isClustered() 2115 } 2116 2117 // jsa.usageMu read lock should be held. 2118 func (jsa *jsAccount) selectLimits(cfg *StreamConfig) (JetStreamAccountLimits, string, bool) { 2119 if selectedLimits, ok := jsa.limits[_EMPTY_]; ok { 2120 return selectedLimits, _EMPTY_, true 2121 } 2122 tier := tierName(cfg) 2123 if selectedLimits, ok := jsa.limits[tier]; ok { 2124 return selectedLimits, tier, true 2125 } 2126 return JetStreamAccountLimits{}, _EMPTY_, false 2127 } 2128 2129 // Lock should be held. 2130 func (jsa *jsAccount) countStreams(tier string, cfg *StreamConfig) int { 2131 streams := len(jsa.streams) 2132 if tier != _EMPTY_ { 2133 streams = 0 2134 for _, sa := range jsa.streams { 2135 if isSameTier(&sa.cfg, cfg) { 2136 streams++ 2137 } 2138 } 2139 } 2140 return streams 2141 } 2142 2143 // jsa.usageMu read lock (at least) should be held. 2144 func (jsa *jsAccount) storageTotals() (uint64, uint64) { 2145 mem := uint64(0) 2146 store := uint64(0) 2147 for _, sa := range jsa.usage { 2148 mem += uint64(sa.total.mem) 2149 store += uint64(sa.total.store) 2150 } 2151 return mem, store 2152 } 2153 2154 func (jsa *jsAccount) limitsExceeded(storeType StorageType, tierName string, replicas int) (bool, *ApiError) { 2155 return jsa.wouldExceedLimits(storeType, tierName, replicas, _EMPTY_, nil, nil) 2156 } 2157 2158 func (jsa *jsAccount) wouldExceedLimits(storeType StorageType, tierName string, replicas int, subj string, hdr, msg []byte) (bool, *ApiError) { 2159 jsa.usageMu.RLock() 2160 defer jsa.usageMu.RUnlock() 2161 2162 selectedLimits, ok := jsa.limits[tierName] 2163 if !ok { 2164 return true, NewJSNoLimitsError() 2165 } 2166 inUse := jsa.usage[tierName] 2167 if inUse == nil { 2168 // Imply totals of 0 2169 return false, nil 2170 } 2171 r := int64(replicas) 2172 // Make sure replicas is correct. 2173 if r < 1 { 2174 r = 1 2175 } 2176 // This is for limits. If we have no tier, consider all to be flat, vs tiers like R3 where we want to scale limit by replication. 2177 lr := r 2178 if tierName == _EMPTY_ { 2179 lr = 1 2180 } 2181 2182 // Since tiers are flat we need to scale limit up by replicas when checking. 2183 if storeType == MemoryStorage { 2184 totalMem := inUse.total.mem + (int64(memStoreMsgSize(subj, hdr, msg)) * r) 2185 if selectedLimits.MemoryMaxStreamBytes > 0 && totalMem > selectedLimits.MemoryMaxStreamBytes*lr { 2186 return true, nil 2187 } 2188 if selectedLimits.MaxMemory >= 0 && totalMem > selectedLimits.MaxMemory*lr { 2189 return true, nil 2190 } 2191 } else { 2192 totalStore := inUse.total.store + (int64(fileStoreMsgSize(subj, hdr, msg)) * r) 2193 if selectedLimits.StoreMaxStreamBytes > 0 && totalStore > selectedLimits.StoreMaxStreamBytes*lr { 2194 return true, nil 2195 } 2196 if selectedLimits.MaxStore >= 0 && totalStore > selectedLimits.MaxStore*lr { 2197 return true, nil 2198 } 2199 } 2200 2201 return false, nil 2202 } 2203 2204 // Check account limits. 2205 // Read Lock should be held 2206 func (js *jetStream) checkAccountLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes int64) error { 2207 return js.checkLimits(selected, config, false, currentRes, 0) 2208 } 2209 2210 // Check account and server limits. 2211 // Read Lock should be held 2212 func (js *jetStream) checkAllLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes, maxBytesOffset int64) error { 2213 return js.checkLimits(selected, config, true, currentRes, maxBytesOffset) 2214 } 2215 2216 // Check if a new proposed msg set while exceed our account limits. 2217 // Lock should be held. 2218 func (js *jetStream) checkLimits(selected *JetStreamAccountLimits, config *StreamConfig, checkServer bool, currentRes, maxBytesOffset int64) error { 2219 // Check MaxConsumers 2220 if config.MaxConsumers > 0 && selected.MaxConsumers > 0 && config.MaxConsumers > selected.MaxConsumers { 2221 return NewJSMaximumConsumersLimitError() 2222 } 2223 // stream limit is checked separately on stream create only! 2224 // Check storage, memory or disk. 2225 return js.checkBytesLimits(selected, config.MaxBytes, config.Storage, checkServer, currentRes, maxBytesOffset) 2226 } 2227 2228 // Check if additional bytes will exceed our account limits and optionally the server itself. 2229 // Read Lock should be held. 2230 func (js *jetStream) checkBytesLimits(selectedLimits *JetStreamAccountLimits, addBytes int64, storage StorageType, checkServer bool, currentRes, maxBytesOffset int64) error { 2231 if addBytes < 0 { 2232 addBytes = 1 2233 } 2234 totalBytes := addBytes + maxBytesOffset 2235 2236 switch storage { 2237 case MemoryStorage: 2238 // Account limits defined. 2239 if selectedLimits.MaxMemory >= 0 && currentRes+totalBytes > selectedLimits.MaxMemory { 2240 return NewJSMemoryResourcesExceededError() 2241 } 2242 // Check if this server can handle request. 2243 if checkServer && js.memReserved+addBytes > js.config.MaxMemory { 2244 return NewJSMemoryResourcesExceededError() 2245 } 2246 case FileStorage: 2247 // Account limits defined. 2248 if selectedLimits.MaxStore >= 0 && currentRes+totalBytes > selectedLimits.MaxStore { 2249 return NewJSStorageResourcesExceededError() 2250 } 2251 // Check if this server can handle request. 2252 if checkServer && js.storeReserved+addBytes > js.config.MaxStore { 2253 return NewJSStorageResourcesExceededError() 2254 } 2255 } 2256 2257 return nil 2258 } 2259 2260 func (jsa *jsAccount) acc() *Account { 2261 return jsa.account 2262 } 2263 2264 // Delete the JetStream resources. 2265 func (jsa *jsAccount) delete() { 2266 var streams []*stream 2267 var ts []string 2268 2269 jsa.mu.Lock() 2270 // The update timer and subs need to be protected by usageMu lock 2271 jsa.usageMu.Lock() 2272 if jsa.utimer != nil { 2273 jsa.utimer.Stop() 2274 jsa.utimer = nil 2275 } 2276 if jsa.updatesSub != nil && jsa.js.srv != nil { 2277 s := jsa.js.srv 2278 s.sysUnsubscribe(jsa.updatesSub) 2279 jsa.updatesSub = nil 2280 } 2281 jsa.usageMu.Unlock() 2282 2283 for _, ms := range jsa.streams { 2284 streams = append(streams, ms) 2285 } 2286 acc := jsa.account 2287 for _, t := range jsa.templates { 2288 ts = append(ts, t.Name) 2289 } 2290 jsa.templates = nil 2291 jsa.mu.Unlock() 2292 2293 for _, ms := range streams { 2294 ms.stop(false, false) 2295 } 2296 2297 for _, t := range ts { 2298 acc.deleteStreamTemplate(t) 2299 } 2300 } 2301 2302 // Lookup the jetstream account for a given account. 2303 func (js *jetStream) lookupAccount(a *Account) *jsAccount { 2304 if a == nil { 2305 return nil 2306 } 2307 js.mu.RLock() 2308 jsa := js.accounts[a.Name] 2309 js.mu.RUnlock() 2310 return jsa 2311 } 2312 2313 // Report on JetStream stats and usage for this server. 2314 func (js *jetStream) usageStats() *JetStreamStats { 2315 var stats JetStreamStats 2316 js.mu.RLock() 2317 stats.Accounts = len(js.accounts) 2318 stats.ReservedMemory = uint64(js.memReserved) 2319 stats.ReservedStore = uint64(js.storeReserved) 2320 s := js.srv 2321 js.mu.RUnlock() 2322 stats.API.Total = uint64(atomic.LoadInt64(&js.apiTotal)) 2323 stats.API.Errors = uint64(atomic.LoadInt64(&js.apiErrors)) 2324 stats.API.Inflight = uint64(atomic.LoadInt64(&js.apiInflight)) 2325 // Make sure we do not report negative. 2326 used := atomic.LoadInt64(&js.memUsed) 2327 if used < 0 { 2328 used = 0 2329 } 2330 stats.Memory = uint64(used) 2331 used = atomic.LoadInt64(&js.storeUsed) 2332 if used < 0 { 2333 used = 0 2334 } 2335 stats.Store = uint64(used) 2336 stats.HAAssets = s.numRaftNodes() 2337 return &stats 2338 } 2339 2340 // Check to see if we have enough system resources for this account. 2341 // Lock should be held. 2342 func (js *jetStream) sufficientResources(limits map[string]JetStreamAccountLimits) error { 2343 // If we are clustered we do not really know how many resources will be ultimately available. 2344 // This needs to be handled out of band. 2345 // If we are a single server, we can make decisions here. 2346 if limits == nil || !js.standAlone { 2347 return nil 2348 } 2349 2350 totalMaxBytes := func(limits map[string]JetStreamAccountLimits) (int64, int64) { 2351 totalMaxMemory := int64(0) 2352 totalMaxStore := int64(0) 2353 for _, l := range limits { 2354 if l.MaxMemory > 0 { 2355 totalMaxMemory += l.MaxMemory 2356 } 2357 if l.MaxStore > 0 { 2358 totalMaxStore += l.MaxStore 2359 } 2360 } 2361 return totalMaxMemory, totalMaxStore 2362 } 2363 2364 totalMaxMemory, totalMaxStore := totalMaxBytes(limits) 2365 2366 // Reserved is now specific to the MaxBytes for streams. 2367 if js.memReserved+totalMaxMemory > js.config.MaxMemory { 2368 return NewJSMemoryResourcesExceededError() 2369 } 2370 if js.storeReserved+totalMaxStore > js.config.MaxStore { 2371 return NewJSStorageResourcesExceededError() 2372 } 2373 2374 // Since we know if we are here we are single server mode, check the account reservations. 2375 var storeReserved, memReserved int64 2376 for _, jsa := range js.accounts { 2377 if jsa.account.IsExpired() { 2378 continue 2379 } 2380 jsa.usageMu.RLock() 2381 maxMemory, maxStore := totalMaxBytes(jsa.limits) 2382 jsa.usageMu.RUnlock() 2383 memReserved += maxMemory 2384 storeReserved += maxStore 2385 } 2386 2387 if memReserved+totalMaxMemory > js.config.MaxMemory { 2388 return NewJSMemoryResourcesExceededError() 2389 } 2390 if storeReserved+totalMaxStore > js.config.MaxStore { 2391 return NewJSStorageResourcesExceededError() 2392 } 2393 2394 return nil 2395 } 2396 2397 // This will reserve the stream resources requested. 2398 // This will spin off off of MaxBytes. 2399 func (js *jetStream) reserveStreamResources(cfg *StreamConfig) { 2400 if cfg == nil || cfg.MaxBytes <= 0 { 2401 return 2402 } 2403 2404 js.mu.Lock() 2405 switch cfg.Storage { 2406 case MemoryStorage: 2407 js.memReserved += cfg.MaxBytes 2408 case FileStorage: 2409 js.storeReserved += cfg.MaxBytes 2410 } 2411 s, clustered := js.srv, !js.standAlone 2412 js.mu.Unlock() 2413 // If clustered send an update to the system immediately. 2414 if clustered { 2415 s.sendStatszUpdate() 2416 } 2417 } 2418 2419 // Release reserved resources held by a stream. 2420 func (js *jetStream) releaseStreamResources(cfg *StreamConfig) { 2421 if cfg == nil || cfg.MaxBytes <= 0 { 2422 return 2423 } 2424 2425 js.mu.Lock() 2426 switch cfg.Storage { 2427 case MemoryStorage: 2428 js.memReserved -= cfg.MaxBytes 2429 case FileStorage: 2430 js.storeReserved -= cfg.MaxBytes 2431 } 2432 s, clustered := js.srv, !js.standAlone 2433 js.mu.Unlock() 2434 // If clustered send an update to the system immediately. 2435 if clustered { 2436 s.sendStatszUpdate() 2437 } 2438 } 2439 2440 const ( 2441 // JetStreamStoreDir is the prefix we use. 2442 JetStreamStoreDir = "jetstream" 2443 // JetStreamMaxStoreDefault is the default disk storage limit. 1TB 2444 JetStreamMaxStoreDefault = 1024 * 1024 * 1024 * 1024 2445 // JetStreamMaxMemDefault is only used when we can't determine system memory. 256MB 2446 JetStreamMaxMemDefault = 1024 * 1024 * 256 2447 // snapshot staging for restores. 2448 snapStagingDir = ".snap-staging" 2449 ) 2450 2451 // Dynamically create a config with a tmp based directory (repeatable) and 75% of system memory. 2452 func (s *Server) dynJetStreamConfig(storeDir string, maxStore, maxMem int64) *JetStreamConfig { 2453 jsc := &JetStreamConfig{} 2454 if storeDir != _EMPTY_ { 2455 jsc.StoreDir = filepath.Join(storeDir, JetStreamStoreDir) 2456 } else { 2457 // Create one in tmp directory, but make it consistent for restarts. 2458 jsc.StoreDir = filepath.Join(os.TempDir(), "nats", JetStreamStoreDir) 2459 } 2460 2461 opts := s.getOpts() 2462 2463 // Sync options. 2464 jsc.SyncInterval = opts.SyncInterval 2465 jsc.SyncAlways = opts.SyncAlways 2466 2467 if opts.maxStoreSet && maxStore >= 0 { 2468 jsc.MaxStore = maxStore 2469 } else { 2470 jsc.MaxStore = diskAvailable(jsc.StoreDir) 2471 } 2472 2473 if opts.maxMemSet && maxMem >= 0 { 2474 jsc.MaxMemory = maxMem 2475 } else { 2476 // Estimate to 75% of total memory if we can determine system memory. 2477 if sysMem := sysmem.Memory(); sysMem > 0 { 2478 // Check if we have been limited with GOMEMLIMIT and if lower use that value. 2479 if gml := debug.SetMemoryLimit(-1); gml != math.MaxInt64 && gml < sysMem { 2480 s.Debugf("JetStream detected GOMEMLIMIT of %v", friendlyBytes(gml)) 2481 sysMem = gml 2482 } 2483 jsc.MaxMemory = sysMem / 4 * 3 2484 } else { 2485 jsc.MaxMemory = JetStreamMaxMemDefault 2486 } 2487 } 2488 2489 return jsc 2490 } 2491 2492 // Helper function. 2493 func (a *Account) checkForJetStream() (*Server, *jsAccount, error) { 2494 a.mu.RLock() 2495 s := a.srv 2496 jsa := a.js 2497 a.mu.RUnlock() 2498 2499 if s == nil || jsa == nil { 2500 return nil, nil, NewJSNotEnabledForAccountError() 2501 } 2502 2503 return s, jsa, nil 2504 } 2505 2506 // StreamTemplateConfig allows a configuration to auto-create streams based on this template when a message 2507 // is received that matches. Each new stream will use the config as the template config to create them. 2508 type StreamTemplateConfig struct { 2509 Name string `json:"name"` 2510 Config *StreamConfig `json:"config"` 2511 MaxStreams uint32 `json:"max_streams"` 2512 } 2513 2514 // StreamTemplateInfo 2515 type StreamTemplateInfo struct { 2516 Config *StreamTemplateConfig `json:"config"` 2517 Streams []string `json:"streams"` 2518 } 2519 2520 // streamTemplate 2521 type streamTemplate struct { 2522 mu sync.Mutex 2523 tc *client 2524 jsa *jsAccount 2525 *StreamTemplateConfig 2526 streams []string 2527 } 2528 2529 func (t *StreamTemplateConfig) deepCopy() *StreamTemplateConfig { 2530 copy := *t 2531 cfg := *t.Config 2532 copy.Config = &cfg 2533 return © 2534 } 2535 2536 // addStreamTemplate will add a stream template to this account that allows auto-creation of streams. 2537 func (a *Account) addStreamTemplate(tc *StreamTemplateConfig) (*streamTemplate, error) { 2538 s, jsa, err := a.checkForJetStream() 2539 if err != nil { 2540 return nil, err 2541 } 2542 if tc.Config.Name != "" { 2543 return nil, fmt.Errorf("template config name should be empty") 2544 } 2545 if len(tc.Name) > JSMaxNameLen { 2546 return nil, fmt.Errorf("template name is too long, maximum allowed is %d", JSMaxNameLen) 2547 } 2548 2549 // FIXME(dlc) - Hacky 2550 tcopy := tc.deepCopy() 2551 tcopy.Config.Name = "_" 2552 cfg, apiErr := s.checkStreamCfg(tcopy.Config, a) 2553 if apiErr != nil { 2554 return nil, apiErr 2555 } 2556 tcopy.Config = &cfg 2557 t := &streamTemplate{ 2558 StreamTemplateConfig: tcopy, 2559 tc: s.createInternalJetStreamClient(), 2560 jsa: jsa, 2561 } 2562 t.tc.registerWithAccount(a) 2563 2564 jsa.mu.Lock() 2565 if jsa.templates == nil { 2566 jsa.templates = make(map[string]*streamTemplate) 2567 // Create the appropriate store 2568 if cfg.Storage == FileStorage { 2569 jsa.store = newTemplateFileStore(jsa.storeDir) 2570 } else { 2571 jsa.store = newTemplateMemStore() 2572 } 2573 } else if _, ok := jsa.templates[tcopy.Name]; ok { 2574 jsa.mu.Unlock() 2575 return nil, fmt.Errorf("template with name %q already exists", tcopy.Name) 2576 } 2577 jsa.templates[tcopy.Name] = t 2578 jsa.mu.Unlock() 2579 2580 // FIXME(dlc) - we can not overlap subjects between templates. Need to have test. 2581 2582 // Setup the internal subscriptions to trap the messages. 2583 if err := t.createTemplateSubscriptions(); err != nil { 2584 return nil, err 2585 } 2586 if err := jsa.store.Store(t); err != nil { 2587 t.delete() 2588 return nil, err 2589 } 2590 return t, nil 2591 } 2592 2593 func (t *streamTemplate) createTemplateSubscriptions() error { 2594 if t == nil { 2595 return fmt.Errorf("no template") 2596 } 2597 if t.tc == nil { 2598 return fmt.Errorf("template not enabled") 2599 } 2600 c := t.tc 2601 if !c.srv.EventsEnabled() { 2602 return ErrNoSysAccount 2603 } 2604 sid := 1 2605 for _, subject := range t.Config.Subjects { 2606 // Now create the subscription 2607 if _, err := c.processSub([]byte(subject), nil, []byte(strconv.Itoa(sid)), t.processInboundTemplateMsg, false); err != nil { 2608 c.acc.deleteStreamTemplate(t.Name) 2609 return err 2610 } 2611 sid++ 2612 } 2613 return nil 2614 } 2615 2616 func (t *streamTemplate) processInboundTemplateMsg(_ *subscription, pc *client, acc *Account, subject, reply string, msg []byte) { 2617 if t == nil || t.jsa == nil { 2618 return 2619 } 2620 jsa := t.jsa 2621 cn := canonicalName(subject) 2622 2623 jsa.mu.Lock() 2624 // If we already are registered then we can just return here. 2625 if _, ok := jsa.streams[cn]; ok { 2626 jsa.mu.Unlock() 2627 return 2628 } 2629 jsa.mu.Unlock() 2630 2631 // Check if we are at the maximum and grab some variables. 2632 t.mu.Lock() 2633 c := t.tc 2634 cfg := *t.Config 2635 cfg.Template = t.Name 2636 atLimit := len(t.streams) >= int(t.MaxStreams) 2637 if !atLimit { 2638 t.streams = append(t.streams, cn) 2639 } 2640 t.mu.Unlock() 2641 2642 if atLimit { 2643 c.RateLimitWarnf("JetStream could not create stream for account %q on subject %q, at limit", acc.Name, subject) 2644 return 2645 } 2646 2647 // We need to create the stream here. 2648 // Change the config from the template and only use literal subject. 2649 cfg.Name = cn 2650 cfg.Subjects = []string{subject} 2651 mset, err := acc.addStream(&cfg) 2652 if err != nil { 2653 acc.validateStreams(t) 2654 c.RateLimitWarnf("JetStream could not create stream for account %q on subject %q: %v", acc.Name, subject, err) 2655 return 2656 } 2657 2658 // Process this message directly by invoking mset. 2659 mset.processInboundJetStreamMsg(nil, pc, acc, subject, reply, msg) 2660 } 2661 2662 // lookupStreamTemplate looks up the names stream template. 2663 func (a *Account) lookupStreamTemplate(name string) (*streamTemplate, error) { 2664 _, jsa, err := a.checkForJetStream() 2665 if err != nil { 2666 return nil, err 2667 } 2668 jsa.mu.Lock() 2669 defer jsa.mu.Unlock() 2670 if jsa.templates == nil { 2671 return nil, fmt.Errorf("template not found") 2672 } 2673 t, ok := jsa.templates[name] 2674 if !ok { 2675 return nil, fmt.Errorf("template not found") 2676 } 2677 return t, nil 2678 } 2679 2680 // This function will check all named streams and make sure they are valid. 2681 func (a *Account) validateStreams(t *streamTemplate) { 2682 t.mu.Lock() 2683 var vstreams []string 2684 for _, sname := range t.streams { 2685 if _, err := a.lookupStream(sname); err == nil { 2686 vstreams = append(vstreams, sname) 2687 } 2688 } 2689 t.streams = vstreams 2690 t.mu.Unlock() 2691 } 2692 2693 func (t *streamTemplate) delete() error { 2694 if t == nil { 2695 return fmt.Errorf("nil stream template") 2696 } 2697 2698 t.mu.Lock() 2699 jsa := t.jsa 2700 c := t.tc 2701 t.tc = nil 2702 defer func() { 2703 if c != nil { 2704 c.closeConnection(ClientClosed) 2705 } 2706 }() 2707 t.mu.Unlock() 2708 2709 if jsa == nil { 2710 return NewJSNotEnabledForAccountError() 2711 } 2712 2713 jsa.mu.Lock() 2714 if jsa.templates == nil { 2715 jsa.mu.Unlock() 2716 return fmt.Errorf("template not found") 2717 } 2718 if _, ok := jsa.templates[t.Name]; !ok { 2719 jsa.mu.Unlock() 2720 return fmt.Errorf("template not found") 2721 } 2722 delete(jsa.templates, t.Name) 2723 acc := jsa.account 2724 jsa.mu.Unlock() 2725 2726 // Remove streams associated with this template. 2727 var streams []*stream 2728 t.mu.Lock() 2729 for _, name := range t.streams { 2730 if mset, err := acc.lookupStream(name); err == nil { 2731 streams = append(streams, mset) 2732 } 2733 } 2734 t.mu.Unlock() 2735 2736 if jsa.store != nil { 2737 if err := jsa.store.Delete(t); err != nil { 2738 return fmt.Errorf("error deleting template from store: %v", err) 2739 } 2740 } 2741 2742 var lastErr error 2743 for _, mset := range streams { 2744 if err := mset.delete(); err != nil { 2745 lastErr = err 2746 } 2747 } 2748 return lastErr 2749 } 2750 2751 func (a *Account) deleteStreamTemplate(name string) error { 2752 t, err := a.lookupStreamTemplate(name) 2753 if err != nil { 2754 return NewJSStreamTemplateNotFoundError() 2755 } 2756 return t.delete() 2757 } 2758 2759 func (a *Account) templates() []*streamTemplate { 2760 var ts []*streamTemplate 2761 _, jsa, err := a.checkForJetStream() 2762 if err != nil { 2763 return nil 2764 } 2765 2766 jsa.mu.Lock() 2767 for _, t := range jsa.templates { 2768 // FIXME(dlc) - Copy? 2769 ts = append(ts, t) 2770 } 2771 jsa.mu.Unlock() 2772 2773 return ts 2774 } 2775 2776 // Will add a stream to a template, this is for recovery. 2777 func (jsa *jsAccount) addStreamNameToTemplate(tname, mname string) error { 2778 if jsa.templates == nil { 2779 return fmt.Errorf("template not found") 2780 } 2781 t, ok := jsa.templates[tname] 2782 if !ok { 2783 return fmt.Errorf("template not found") 2784 } 2785 // We found template. 2786 t.mu.Lock() 2787 t.streams = append(t.streams, mname) 2788 t.mu.Unlock() 2789 return nil 2790 } 2791 2792 // This will check if a template owns this stream. 2793 // jsAccount lock should be held 2794 func (jsa *jsAccount) checkTemplateOwnership(tname, sname string) bool { 2795 if jsa.templates == nil { 2796 return false 2797 } 2798 t, ok := jsa.templates[tname] 2799 if !ok { 2800 return false 2801 } 2802 // We found template, make sure we are in streams. 2803 for _, streamName := range t.streams { 2804 if sname == streamName { 2805 return true 2806 } 2807 } 2808 return false 2809 } 2810 2811 type Number interface { 2812 int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 2813 } 2814 2815 // friendlyBytes returns a string with the given bytes int64 2816 // represented as a size, such as 1KB, 10MB, etc... 2817 func friendlyBytes[T Number](bytes T) string { 2818 fbytes := float64(bytes) 2819 base := 1024 2820 pre := []string{"K", "M", "G", "T", "P", "E"} 2821 if fbytes < float64(base) { 2822 return fmt.Sprintf("%v B", fbytes) 2823 } 2824 exp := int(math.Log(fbytes) / math.Log(float64(base))) 2825 index := exp - 1 2826 return fmt.Sprintf("%.2f %sB", fbytes/math.Pow(float64(base), float64(exp)), pre[index]) 2827 } 2828 2829 func isValidName(name string) bool { 2830 if name == _EMPTY_ { 2831 return false 2832 } 2833 return !strings.ContainsAny(name, " \t\r\n\f.*>") 2834 } 2835 2836 // CanonicalName will replace all token separators '.' with '_'. 2837 // This can be used when naming streams or consumers with multi-token subjects. 2838 func canonicalName(name string) string { 2839 return strings.ReplaceAll(name, ".", "_") 2840 } 2841 2842 // To throttle the out of resources errors. 2843 func (s *Server) resourcesExceededError() { 2844 var didAlert bool 2845 2846 s.rerrMu.Lock() 2847 if now := time.Now(); now.Sub(s.rerrLast) > 10*time.Second { 2848 s.Errorf("JetStream resource limits exceeded for server") 2849 s.rerrLast = now 2850 didAlert = true 2851 } 2852 s.rerrMu.Unlock() 2853 2854 // If we are meta leader we should relinguish that here. 2855 if didAlert { 2856 if js := s.getJetStream(); js != nil { 2857 js.mu.RLock() 2858 if cc := js.cluster; cc != nil && cc.isLeader() { 2859 cc.meta.StepDown() 2860 } 2861 js.mu.RUnlock() 2862 } 2863 } 2864 } 2865 2866 // For validating options. 2867 func validateJetStreamOptions(o *Options) error { 2868 // in non operator mode, the account names need to be configured 2869 if len(o.JsAccDefaultDomain) > 0 { 2870 if len(o.TrustedOperators) == 0 { 2871 for a, domain := range o.JsAccDefaultDomain { 2872 found := false 2873 if isReservedAccount(a) { 2874 found = true 2875 } else { 2876 for _, acc := range o.Accounts { 2877 if a == acc.GetName() { 2878 if len(acc.jsLimits) > 0 && domain != _EMPTY_ { 2879 return fmt.Errorf("default_js_domain contains account name %q with enabled JetStream", a) 2880 } 2881 found = true 2882 break 2883 } 2884 } 2885 } 2886 if !found { 2887 return fmt.Errorf("in non operator mode, `default_js_domain` references non existing account %q", a) 2888 } 2889 } 2890 } else { 2891 for a := range o.JsAccDefaultDomain { 2892 if !nkeys.IsValidPublicAccountKey(a) { 2893 return fmt.Errorf("default_js_domain contains account name %q, which is not a valid public account nkey", a) 2894 } 2895 } 2896 } 2897 for a, d := range o.JsAccDefaultDomain { 2898 sacc := DEFAULT_SYSTEM_ACCOUNT 2899 if o.SystemAccount != _EMPTY_ { 2900 sacc = o.SystemAccount 2901 } 2902 if a == sacc { 2903 return fmt.Errorf("system account %q can not be in default_js_domain", a) 2904 } 2905 if d == _EMPTY_ { 2906 continue 2907 } 2908 if sub := fmt.Sprintf(jsDomainAPI, d); !IsValidSubject(sub) { 2909 return fmt.Errorf("default_js_domain contains account %q with invalid domain name %q", a, d) 2910 } 2911 } 2912 } 2913 if o.JetStreamDomain != _EMPTY_ { 2914 if subj := fmt.Sprintf(jsDomainAPI, o.JetStreamDomain); !IsValidSubject(subj) { 2915 return fmt.Errorf("invalid domain name: derived %q is not a valid subject", subj) 2916 } 2917 2918 if !isValidName(o.JetStreamDomain) { 2919 return fmt.Errorf("invalid domain name: may not contain ., * or >") 2920 } 2921 } 2922 // If not clustered no checks needed past here. 2923 if !o.JetStream || o.Cluster.Port == 0 { 2924 return nil 2925 } 2926 if o.ServerName == _EMPTY_ { 2927 return fmt.Errorf("jetstream cluster requires `server_name` to be set") 2928 } 2929 if o.Cluster.Name == _EMPTY_ { 2930 return fmt.Errorf("jetstream cluster requires `cluster.name` to be set") 2931 } 2932 2933 h := strings.ToLower(o.JetStreamExtHint) 2934 switch h { 2935 case jsWillExtend, jsNoExtend, _EMPTY_: 2936 o.JetStreamExtHint = h 2937 default: 2938 return fmt.Errorf("expected 'no_extend' for string value, got '%s'", h) 2939 } 2940 2941 if o.JetStreamMaxCatchup < 0 { 2942 return fmt.Errorf("jetstream max catchup cannot be negative") 2943 } 2944 return nil 2945 } 2946 2947 // We had a bug that set a default de dupe window on mirror, despite that being not a valid config 2948 func fixCfgMirrorWithDedupWindow(cfg *StreamConfig) { 2949 if cfg == nil || cfg.Mirror == nil { 2950 return 2951 } 2952 if cfg.Duplicates != 0 { 2953 cfg.Duplicates = 0 2954 } 2955 }