aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storage/distributor/ownership_transfer_safe_time_point_calculator.cpp
blob: 9e7e09bdfe8896dba9fd1a4e275742cea37d2bd0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "ownership_transfer_safe_time_point_calculator.h"
#include <thread>

namespace storage::distributor {

vespalib::system_time
OwnershipTransferSafeTimePointCalculator::safeTimePoint(vespalib::system_time now) const
{
    if (_max_cluster_clock_skew.count() == 0) {
        return {};
    }
    // Rationale: distributors always generate time stamps by taking
    // the current second and adding a synthetic microsecond counter.
    // This means that if we assume a 1 second max skew and one node
    // operates with t=5.95, another node may be operating with t=4.95.
    // If they both receive their first operation within that second,
    // they will be 5.000001 and 4.000001, respectively. If we just
    // waited for max clock skew number of seconds, we would end up
    // with t=5.95 -> t=6.95 and 4.95 -> 5.95. In the second node's case,
    // the first timestamp it would generate would be 5.000001, which
    // collides with the one already generated by the the other node!
    // To avoid this, we round upwards to the nearest whole second before
    // adding the max skew. This prevents generating time stamps within
    // the same whole second as another distributor already has done for
    // any of the buckets a node now owns.
    auto now_sec = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
    return vespalib::system_time(now_sec + std::chrono::seconds(1) + _max_cluster_clock_skew);
}

}