Line data Source code
1 : /*
2 : ___________________________________________
3 : | _ ___ _ |
4 : | | | |__ \ | | |
5 : | | |__ ) |__ _ __ _ ___ _ __ | |_ |
6 : | | '_ \ / // _` |/ _` |/ _ \ '_ \| __| | HTTP/2 AGENT FOR MOCK TESTING
7 : | | | | |/ /| (_| | (_| | __/ | | | |_ | Version 0.0.z
8 : | |_| |_|____\__,_|\__, |\___|_| |_|\__| | https://github.com/testillano/h2agent
9 : | __/ | |
10 : | |___/ |
11 : |___________________________________________|
12 :
13 : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 : SPDX-License-Identifier: MIT
15 : Copyright (c) 2021 Eduardo Ramos
16 :
17 : Permission is hereby granted, free of charge, to any person obtaining a copy
18 : of this software and associated documentation files (the "Software"), to deal
19 : in the Software without restriction, including without limitation the rights
20 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 : copies of the Software, and to permit persons to whom the Software is
22 : furnished to do so, subject to the following conditions:
23 :
24 : The above copyright notice and this permission notice shall be included in all
25 : copies or substantial portions of the Software.
26 :
27 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 : SOFTWARE.
34 : */
35 :
36 : #pragma once
37 :
38 : #include <vector>
39 : #include <cstdint>
40 :
41 : #include <nlohmann/json.hpp>
42 :
43 : #include <Map.hpp>
44 : #include <MockEventsHistory.hpp>
45 : #include <MockEvent.hpp>
46 :
47 :
48 : namespace h2agent
49 : {
50 : namespace model
51 : {
52 :
53 :
54 : /**
55 : * This class stores the mock events.
56 : *
57 : * This is useful to post-verify the internal data (content and schema validation) on testing system.
58 : * Also, the last request for an specific key, is used to know the state which is used to get the
59 : * corresponding provision information.
60 : *
61 : * The event store is accessed on the TRAFFIC hot path: every request writes its
62 : * event (loadEvent -> per-key get + add / modifyOrInsert) and transformations
63 : * read past events (getEvent -> per-key get). Under high concurrency with MANY
64 : * DISTINCT keys (e.g. millions of subscribers, each with its own URI, plus FSM
65 : * state updates on that URI) a single global mutex would serialize all of them.
66 : * It is therefore backed by an N-way SHARDED Map (see Map.hpp): per-key access
67 : * locks only its shard, so independent keys do not contend. Whole-map ops
68 : * (summary/getJson/asJsonString/getSequence) lock all shards, but those are
69 : * administrative/report paths (GET on the admin server_data/client_data
70 : * endpoints), not the hot path.
71 : *
72 : * NOTE: this disperses contention on the MAP's mutex only. The per-entry
73 : * MockEventsHistory has its own mutex; deep history on the SAME key still
74 : * serializes there (orthogonal to Map sharding), but that is the natural
75 : * per-subscriber ordering and does not block other keys.
76 : */
77 : class MockData : public Map<mock_events_key_t, std::shared_ptr<MockEventsHistory>, MOCK_DATA_MUTEX_SHARDS>
78 : {
79 : protected:
80 : // Get the events list for data key provided, and pass by reference a boolean to know if the list must be inaugurated
81 : std::shared_ptr<MockEventsHistory> getEvents(const DataKey &dataKey, bool &maiden);
82 :
83 : public:
84 644 : MockData() {};
85 643 : ~MockData() = default;
86 :
87 : using KeyType = mock_events_key_t;
88 : using ValueType = std::shared_ptr<MockEventsHistory>;
89 :
90 :
91 : /** Clears internal data
92 : *
93 : * @param somethingDeleted boolean to know if something was deleted, by reference
94 : * @param ekey Event key given by data key and event history number (1..N) to filter selection
95 : * Empty event key will remove the whole history for data key provided.
96 : * Event number '-1' will select the latest event in events history.
97 : *
98 : * @return Boolean about success of operation (not related to the number of events removed)
99 : */
100 : bool clear(bool &somethingDeleted, const EventKey &ekey);
101 :
102 : /**
103 : * Json string representation for class information filtered (json array)
104 : *
105 : * @param elkey Event location key given by data key, event history number (1..N) and event path to filter selection
106 : * Event history number (1..N) is optional, but cannot be provided alone (needs data key).
107 : * If empty, whole history is selected for data key provided.
108 : * If provided '-1' (unsigned long long max), the latest event is selected.
109 : * Event Path within the event selected is optional, but cannot be provided alone (needs data key and event number).
110 : * @param validQuery Boolean result passed by reference.
111 : *
112 : * @return Json string representation ('[]' for empty array).
113 : * @warning This method may throw exception due to dump() when unexpected data is stored on json wrap: execute under try/catch block.
114 :
115 : */
116 : std::string asJsonString(const EventLocationKey &elkey, bool &validQuery) const;
117 :
118 : /**
119 : * Json string representation for class summary (total number of events and first/last/random keys).
120 : *
121 : * @param maxKeys Maximum number of keys to be displayed in the summary (protection for huge server data size). No limit by default.
122 : *
123 : * @return Json string representation.
124 : */
125 : std::string summary(const std::string &maxKeys = "") const;
126 :
127 : /**
128 : * Gets the mock server key event in specific position
129 : *
130 : * @param ekey Event key given by data key and event history number (1..N) to filter selection
131 : * Value '-1' (unsigned long long max) selects the latest event.
132 : * Value '0' is not accepted, and null will be returned in this case.
133 : *
134 : * All the parameters are mandatory to select the single request event.
135 : * If any is missing, nullptr is returned.
136 : *
137 : * @return mock request pointer
138 : * @see size()
139 : */
140 : std::shared_ptr<MockEvent> getEvent(const EventKey &ekey) const;
141 :
142 : /**
143 : * Builds json document for class information
144 : *
145 : * @return Json object
146 : */
147 : nlohmann::json getJson() const;
148 :
149 : /**
150 : * Finds most recent mock context entry state.
151 : *
152 : * @param key Data key triggered.
153 : * @param state Request current state filled by reference.
154 : * If nothing found or no state (unprovisioned events), 'initial' will be set.
155 : *
156 : * @return Boolean about if the request is found or not
157 : */
158 : bool findLastRegisteredRequestState(const DataKey &key, std::string &state) const;
159 :
160 : /**
161 : * Finds most recent mock context entry state and chain variables.
162 : *
163 : * @param key Data key triggered.
164 : * @param state Request current state filled by reference.
165 : * @param chainVariables Chain variables filled by reference.
166 : * If nothing found or no state (unprovisioned events), 'initial' will be set and variables will be empty.
167 : *
168 : * @return Boolean about if the request is found or not
169 : */
170 : bool findLastRegisteredRequestState(const DataKey &key, std::string &state, std::map<std::string, std::string> &chainVariables) const;
171 :
172 : /**
173 : * Stores chain variables for a given data key.
174 : *
175 : * @param key Data key.
176 : * @param chainVariables Chain variables to store.
177 : */
178 : void storeChainVariables(const DataKey &key, const std::map<std::string, std::string> &chainVariables);
179 : };
180 :
181 : }
182 : }
183 :
|