forked from facebook/watchman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatchman_client.h
145 lines (117 loc) · 4.28 KB
/
watchman_client.h
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* Copyright 2012-present Facebook, Inc.
* Licensed under the Apache License, Version 2.0 */
#pragma once
#include <folly/Synchronized.h>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include "Logging.h"
#include "watchman_pdu.h"
#include "watchman_perf.h"
struct w_query;
struct w_query_res;
struct watchman_client_subscription;
namespace watchman {
enum ClientStateDisposition {
PendingEnter,
Asserted,
PendingLeave,
Done,
};
class ClientStateAssertion {
public:
const std::shared_ptr<w_root_t> root; // Holds a ref on the root
const w_string name;
// locking: You must hold root->assertedStates lock to access this member
ClientStateDisposition disposition{PendingEnter};
// Deferred payload to send when this assertion makes it to the front
// of the queue.
// locking: You must hold root->assertedStates lock to access this member.
json_ref enterPayload;
ClientStateAssertion(
const std::shared_ptr<w_root_t>& root,
const w_string& name)
: root(root), name(name) {}
};
} // namespace watchman
struct watchman_client : public std::enable_shared_from_this<watchman_client> {
const uint64_t unique_id;
std::unique_ptr<watchman_stream> stm;
std::unique_ptr<watchman_event> ping;
w_jbuffer_t reader, writer;
bool client_mode{false};
bool client_is_owner{false};
enum w_pdu_type pdu_type;
uint32_t capabilities;
// The command currently being processed by dispatch_command
json_ref current_command;
w_perf_t* perf_sample{nullptr};
// Queue of things to send to the client.
std::deque<json_ref> responses;
// Logging Subscriptions
std::shared_ptr<watchman::Publisher::Subscriber> debugSub;
std::shared_ptr<watchman::Publisher::Subscriber> errorSub;
watchman_client();
explicit watchman_client(std::unique_ptr<watchman_stream>&& stm);
virtual ~watchman_client();
void enqueueResponse(json_ref&& resp, bool ping = true);
};
struct watchman_user_client;
enum class OnStateTransition { QueryAnyway, DontAdvance };
struct watchman_client_subscription
: public std::enable_shared_from_this<watchman_client_subscription> {
struct LoggedResponse {
// TODO: also track the time when the response was enqueued
std::chrono::system_clock::time_point written;
json_ref response;
};
std::shared_ptr<w_root_t> root;
w_string name;
/* whether this subscription is paused */
bool debug_paused = false;
std::shared_ptr<w_query> query;
bool vcs_defer;
uint32_t last_sub_tick{0};
// map of statename => bool. If true, policy is drop, else defer
std::unordered_map<w_string, bool> drop_or_defer;
std::weak_ptr<watchman_client> weakClient;
std::deque<LoggedResponse> lastResponses;
explicit watchman_client_subscription(
const std::shared_ptr<w_root_t>& root,
std::weak_ptr<watchman_client> client);
~watchman_client_subscription();
void processSubscription();
std::shared_ptr<watchman_user_client> lockClient();
json_ref buildSubscriptionResults(
const std::shared_ptr<w_root_t>& root,
ClockSpec& position,
OnStateTransition onStateTransition);
private:
ClockSpec runSubscriptionRules(
watchman_user_client* client,
const std::shared_ptr<w_root_t>& root);
void updateSubscriptionTicks(w_query_res* res);
void processSubscriptionImpl();
};
// Represents the server side session maintained for a client of
// the watchman per-user process
struct watchman_user_client : public watchman_client {
/* map of subscription name => struct watchman_client_subscription */
std::unordered_map<w_string, std::shared_ptr<watchman_client_subscription>>
subscriptions;
/* map of state-name => ClientStateAssertion
* The values are owned by root::assertedStates */
std::unordered_map<w_string, std::weak_ptr<watchman::ClientStateAssertion>>
states;
// Subscriber to root::unilateralResponses
std::unordered_map<
std::shared_ptr<watchman_client_subscription>,
std::shared_ptr<watchman::Publisher::Subscriber>>
unilateralSub;
explicit watchman_user_client(std::unique_ptr<watchman_stream>&& stm);
~watchman_user_client() override;
bool unsubByName(const w_string& name);
};
extern folly::Synchronized<std::unordered_set<std::shared_ptr<watchman_client>>>
clients;
void w_client_vacate_states(struct watchman_user_client* client);