1 /* Copyright 2012-present Facebook, Inc. 2 * Licensed under the Apache License, Version 2.0 */ 3 #pragma once 4 #include <deque> 5 #include <unordered_map> 6 #include <unordered_set> 7 #include "Logging.h" 8 #include "watchman_synchronized.h" 9 10 struct watchman_client_subscription; 11 12 struct watchman_client_state_assertion { 13 std::shared_ptr<w_root_t> root; // Holds a ref on the root 14 w_string name; 15 long id; 16 17 watchman_client_state_assertion( 18 const std::shared_ptr<w_root_t>& root, 19 const w_string& name); 20 }; 21 22 struct watchman_client : public std::enable_shared_from_this<watchman_client> { 23 std::unique_ptr<watchman_stream> stm; 24 std::unique_ptr<watchman_event> ping; 25 w_jbuffer_t reader, writer; 26 bool client_mode{false}; 27 bool client_is_owner{false}; 28 enum w_pdu_type pdu_type; 29 uint32_t capabilities; 30 31 // The command currently being processed by dispatch_command 32 json_ref current_command; 33 w_perf_t* perf_sample{nullptr}; 34 35 // Queue of things to send to the client. 36 std::deque<json_ref> responses; 37 38 // Logging Subscriptions 39 std::shared_ptr<watchman::Publisher::Subscriber> debugSub; 40 std::shared_ptr<watchman::Publisher::Subscriber> errorSub; 41 42 watchman_client(); 43 explicit watchman_client(std::unique_ptr<watchman_stream>&& stm); 44 virtual ~watchman_client(); 45 46 void enqueueResponse(json_ref&& resp, bool ping = true); 47 }; 48 49 struct watchman_user_client; 50 51 struct watchman_client_subscription 52 : public std::enable_shared_from_this<watchman_client_subscription> { 53 std::shared_ptr<w_root_t> root; 54 w_string name; 55 /* whether this subscription is paused */ 56 bool debug_paused = false; 57 58 std::shared_ptr<w_query> query; 59 bool vcs_defer; 60 uint32_t last_sub_tick; 61 // map of statename => bool. If true, policy is drop, else defer 62 std::unordered_map<w_string, bool> drop_or_defer; 63 std::weak_ptr<watchman_client> weakClient; 64 65 explicit watchman_client_subscription( 66 const std::shared_ptr<w_root_t>& root, 67 std::weak_ptr<watchman_client> client); 68 ~watchman_client_subscription(); 69 void processSubscription(); 70 71 std::shared_ptr<watchman_user_client> lockClient(); 72 json_ref buildSubscriptionResults( 73 const std::shared_ptr<w_root_t>& root, 74 ClockSpec& position); 75 76 private: 77 ClockSpec runSubscriptionRules( 78 watchman_user_client* client, 79 const std::shared_ptr<w_root_t>& root); 80 void updateSubscriptionTicks(w_query_res* res); 81 }; 82 83 // Represents the server side session maintained for a client of 84 // the watchman per-user process 85 struct watchman_user_client : public watchman_client { 86 /* map of subscription name => struct watchman_client_subscription */ 87 std::unordered_map<w_string, std::shared_ptr<watchman_client_subscription>> 88 subscriptions; 89 90 /* map of unique id => watchman_client_state_assertion. 91 * The values are owned by root::asserted_states */ 92 std::unordered_map<long, std::weak_ptr<watchman_client_state_assertion>> 93 states; 94 long next_state_id{0}; 95 96 // Subscriber to root::unilateralResponses 97 std::unordered_map< 98 std::shared_ptr<watchman_client_subscription>, 99 std::shared_ptr<watchman::Publisher::Subscriber>> 100 unilateralSub; 101 102 explicit watchman_user_client(std::unique_ptr<watchman_stream>&& stm); 103 ~watchman_user_client() override; 104 105 bool unsubByName(const w_string& name); 106 }; 107 108 extern watchman::Synchronized< 109 std::unordered_set<std::shared_ptr<watchman_client>>> 110 clients; 111 112 void w_client_vacate_states(struct watchman_user_client *client); 113