Return values: 1. allocated ID 2. whether the ID is newly allocated from kvstore 3. whether this is the first owner that holds a reference to the key in localkeys store 4. error in case of failure
(ctx context.Context, key AllocatorKey)
| 528 | // localkeys store |
| 529 | // 4. error in case of failure |
| 530 | func (a *Allocator) lockedAllocate(ctx context.Context, key AllocatorKey) (idpool.ID, bool, bool, error) { |
| 531 | var firstUse bool |
| 532 | |
| 533 | kvstore.Trace(a.logger, "Allocating key in kvstore", fieldKey, key) |
| 534 | |
| 535 | k := key.GetKey() |
| 536 | lock, err := a.backend.Lock(ctx, key) |
| 537 | if err != nil { |
| 538 | return 0, false, false, err |
| 539 | } |
| 540 | |
| 541 | defer lock.Unlock(context.Background()) |
| 542 | |
| 543 | // fetch first key that matches /value/<key> |
| 544 | value, err := a.GetIfLocked(ctx, key, lock) |
| 545 | if err != nil { |
| 546 | return 0, false, false, err |
| 547 | } |
| 548 | |
| 549 | kvstore.Trace(a.logger, "kvstore state is: ", fieldID, value) |
| 550 | |
| 551 | a.slaveKeysMutex.Lock() |
| 552 | defer a.slaveKeysMutex.Unlock() |
| 553 | |
| 554 | // We shouldn't assume the fact the master key does not exist in the kvstore |
| 555 | // that localKeys does not have it. The KVStore might have lost all of its |
| 556 | // data but the local agent still holds a reference for the given master key. |
| 557 | if value == 0 { |
| 558 | value = a.localKeys.lookupKey(k) |
| 559 | if value != 0 { |
| 560 | // re-create master key |
| 561 | if err := a.backend.UpdateKeyIfLocked(ctx, value, key, true, lock); err != nil { |
| 562 | return 0, false, false, fmt.Errorf("unable to re-create missing master key '%s': %s while allocating ID: %w", key, value, err) |
| 563 | } |
| 564 | } |
| 565 | } else { |
| 566 | _, firstUse, err = a.localKeys.allocate(k, key, value) |
| 567 | if err != nil { |
| 568 | return 0, false, false, fmt.Errorf("unable to reserve local key '%s': %w", k, err) |
| 569 | } |
| 570 | |
| 571 | if firstUse { |
| 572 | a.logger.Debug("Reserved new local key", logfields.Key, k) |
| 573 | } else { |
| 574 | a.logger.Debug("Reusing existing local key", logfields.Key, k) |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | if value != 0 { |
| 579 | a.logger.Debug("Reusing existing global key", logfields.Key, k) |
| 580 | |
| 581 | if err = a.backend.AcquireReference(ctx, value, key, lock); err != nil { |
| 582 | a.localKeys.release(k) |
| 583 | return 0, false, false, fmt.Errorf("unable to create secondary key '%s': %w", k, err) |
| 584 | } |
| 585 | |
| 586 | // mark the key as verified in the local cache |
| 587 | if err := a.localKeys.verify(k); err != nil { |
no test coverage detected