1 /* Copyright 2012-present Facebook, Inc.
2  * Licensed under the Apache License, Version 2.0 */
3 #pragma once
4 #include <unordered_map>
5 #include "watchman_synchronized.h"
6 
7 struct watchman_clock {
8   uint32_t ticks;
9   time_t timestamp;
10 };
11 typedef struct watchman_clock w_clock_t;
12 
13 struct w_query_ctx;
14 struct w_query_since;
15 
16 struct ClockPosition {
17   uint32_t rootNumber{0};
18   uint32_t ticks{0};
19 
20   ClockPosition() = default;
ClockPositionClockPosition21   ClockPosition(uint32_t rootNumber, uint32_t ticks)
22       : rootNumber(rootNumber), ticks(ticks) {}
23 
24   w_string toClockString() const;
25 };
26 
27 enum w_clockspec_tag {
28   w_cs_timestamp,
29   w_cs_clock,
30   w_cs_named_cursor
31 };
32 
33 struct ClockSpec {
34   enum w_clockspec_tag tag;
35   time_t timestamp;
36   struct {
37     uint64_t start_time;
38     int pid;
39     ClockPosition position;
40   } clock;
41   struct {
42     w_string cursor;
43   } named_cursor;
44 
45   // Optional SCM merge base parameters
46   w_string scmMergeBase;
47   w_string scmMergeBaseWith;
48 
49   ClockSpec();
50   explicit ClockSpec(const ClockPosition& position);
51   explicit ClockSpec(const json_ref& value);
52 
53   /** Given a json value, parse out a clockspec.
54    * Will return nullptr if the input was json null, indicating
55    * an absence of a specified clock value.
56    * Throws std::domain_error for badly formed clockspec value.
57    */
58   static std::unique_ptr<ClockSpec> parseOptionalClockSpec(
59       const json_ref& value);
60 
61   /** Evaluate the clockspec against the inputs, returning
62    * the effective since parameter.
63    * If cursorMap is passed in, it MUST be unlocked, as this method
64    * will acquire a lock to evaluate a named cursor. */
65   struct w_query_since evaluate(
66       const ClockPosition& position,
67       const uint32_t lastAgeOutTick,
68       watchman::Synchronized<std::unordered_map<w_string, uint32_t>>*
69           cursorMap = nullptr) const;
70 
71   /** Initializes some global state needed for clockspec evaluation */
72   static void init();
73 
positionClockSpec74   inline const ClockPosition& position() const {
75     w_check(tag == w_cs_clock, "position() called for non-clock clockspec");
76     return clock.position;
77   }
78 
79   bool hasScmParams() const;
80 
81   /** Returns a json value representing the current state of this ClockSpec
82    * that can be parsed by the ClockSpec(const json_ref&)
83    * constructor of this class */
84   json_ref toJson() const;
85 };
86