Overte C++ Documentation
OctreeServer.h
1 //
2 // OctreeServer.h
3 // assignment-client/src/octree
4 //
5 // Created by Brad Hefta-Gaub on 8/21/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_OctreeServer_h
13 #define hifi_OctreeServer_h
14 
15 #include <memory>
16 
17 #include <QStringList>
18 #include <QDateTime>
19 #include <QtCore/QCoreApplication>
20 #include <QtCore/QSharedPointer>
21 
22 #include <HTTPManager.h>
23 
24 #include <ThreadedAssignment.h>
25 
26 #include "OctreePersistThread.h"
27 #include "OctreeSendThread.h"
28 #include "OctreeServerConsts.h"
29 #include "OctreeInboundPacketProcessor.h"
30 
31 #include <QLoggingCategory>
32 
33 Q_DECLARE_LOGGING_CATEGORY(octree_server)
34 
35 const int DEFAULT_PACKETS_PER_INTERVAL = 2000; // some 120,000 packets per second total
36 
38 class OctreeServer : public ThreadedAssignment, public HTTPRequestHandler {
39  Q_OBJECT
40 public:
41  OctreeServer(ReceivedMessage& message);
42  ~OctreeServer();
43 
45  void setArguments(int argc, char** argv);
46 
47  bool wantsDebugSending() const { return _debugSending; }
48  bool wantsDebugReceiving() const { return _debugReceiving; }
49  bool wantsVerboseDebug() const { return _verboseDebug; }
50 
51  OctreePointer getOctree() { return _tree; }
52 
53  int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval,
54  std::max(1, getPacketsTotalPerInterval() / std::max(1, getCurrentClientCount()))); }
55 
56  int getPacketsPerClientPerSecond() const { return getPacketsPerClientPerInterval() * INTERVALS_PER_SECOND; }
57  int getPacketsTotalPerInterval() const { return _packetsTotalPerInterval; }
58  int getPacketsTotalPerSecond() const { return getPacketsTotalPerInterval() * INTERVALS_PER_SECOND; }
59 
60  static int getCurrentClientCount() { return _clientCount; }
61  static void clientConnected() { _clientCount++; }
62  static void clientDisconnected() { _clientCount--; }
63 
64  bool isInitialLoadComplete() const { return (_persistManager) ? _persistManager->isInitialLoadComplete() : true; }
65  bool isPersistEnabled() const { return (_persistManager) ? true : false; }
66  quint64 getLoadElapsedTime() const { return (_persistManager) ? _persistManager->getLoadElapsedTime() : 0; }
67  QString getPersistFilename() const { return (_persistManager) ? _persistManager->getPersistFilename() : ""; }
68  QString getPersistFileMimeType() const { return (_persistManager) ? _persistManager->getPersistFileMimeType() : "text/plain"; }
69  QByteArray getPersistFileContents() const { return (_persistManager) ? _persistManager->getPersistFileContents() : QByteArray(); }
70 
71  // Subclasses must implement these methods
72  virtual std::unique_ptr<OctreeQueryNode> createOctreeQueryNode() = 0;
73  virtual char getMyNodeType() const = 0;
74  virtual PacketType getMyQueryMessageType() const = 0;
75  virtual const char* getMyServerName() const = 0;
76  virtual const char* getMyLoggingServerTargetName() const = 0;
77  virtual const char* getMyDefaultPersistFilename() const = 0;
78  virtual PacketType getMyEditNackType() const = 0;
79  virtual QString getMyDomainSettingsKey() const { return QString("octree_server_settings"); }
80 
81  // subclass may implement these method
82  virtual void beforeRun() { }
83  virtual bool hasSpecialPacketsToSend(const SharedNodePointer& node) { return false; }
84  virtual int sendSpecialPackets(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { return 0; }
85  virtual QString serverSubclassStats() { return QString(); }
86  virtual void trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& viewerNode) { }
87  virtual void trackViewerGone(const QUuid& viewerNode) { }
88 
89  static float SKIP_TIME; // use this for trackXXXTime() calls for non-times
90 
91  static void trackLoopTime(float time) { _averageLoopTime.updateAverage(time); }
92  static float getAverageLoopTime() { return _averageLoopTime.getAverage(); }
93 
94  static void trackEncodeTime(float time);
95  static float getAverageEncodeTime() { return _averageEncodeTime.getAverage(); }
96 
97  static void trackInsideTime(float time) { _averageInsideTime.updateAverage(time); }
98  static float getAverageInsideTime() { return _averageInsideTime.getAverage(); }
99 
100  static void trackTreeWaitTime(float time);
101  static float getAverageTreeWaitTime() { return _averageTreeWaitTime.getAverage(); }
102 
103  static void trackTreeTraverseTime(float time) { _averageTreeTraverseTime.updateAverage(time); }
104  static float getAverageTreeTraverseTime() { return _averageTreeTraverseTime.getAverage(); }
105 
106  static void trackNodeWaitTime(float time) { _averageNodeWaitTime.updateAverage(time); }
107  static float getAverageNodeWaitTime() { return _averageNodeWaitTime.getAverage(); }
108 
109  static void trackCompressAndWriteTime(float time);
110  static float getAverageCompressAndWriteTime() { return _averageCompressAndWriteTime.getAverage(); }
111 
112  static void trackPacketSendingTime(float time);
113  static float getAveragePacketSendingTime() { return _averagePacketSendingTime.getAverage(); }
114 
115  static void trackProcessWaitTime(float time);
116  static float getAverageProcessWaitTime() { return _averageProcessWaitTime.getAverage(); }
117 
118  // these methods allow us to track which threads got to various states
119  static void didProcess(OctreeSendThread* thread);
120  static void didPacketDistributor(OctreeSendThread* thread);
121  static void didHandlePacketSend(OctreeSendThread* thread);
122  static void didCallWriteDatagram(OctreeSendThread* thread);
123  static void stopTrackingThread(OctreeSendThread* thread);
124 
125  static int howManyThreadsDidProcess(quint64 since = 0);
126  static int howManyThreadsDidPacketDistributor(quint64 since = 0);
127  static int howManyThreadsDidHandlePacketSend(quint64 since = 0);
128  static int howManyThreadsDidCallWriteDatagram(quint64 since = 0);
129 
130  bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) override;
131 
132  virtual void aboutToFinish() override;
133 
134 public slots:
136  void run() override;
137  virtual void nodeAdded(SharedNodePointer node);
138  virtual void nodeKilled(SharedNodePointer node);
139  void sendStatsPacket() override;
140 
141 private slots:
142  void domainSettingsRequestComplete();
143  void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
144  void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
145  void removeSendThread();
146 
147 protected:
148  using UniqueSendThread = std::unique_ptr<OctreeSendThread>;
149  using SendThreads = std::unordered_map<QUuid, UniqueSendThread>;
150 
151  virtual OctreePointer createTree() = 0;
152  bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
153  bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
154  bool readOptionInt64(const QString& optionName, const QJsonObject& settingsSectionObject, qint64& result);
155  bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result);
156  void readConfiguration();
157  virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { };
158  void parsePayload();
159  void initHTTPManager(int port);
160  void resetSendingStats();
161  QString getUptime();
162  double getUptimeSeconds();
163  QString getFileLoadTime();
164  double getFileLoadTimeSeconds();
165  QString getConfiguration();
166  QString getStatusLink();
167 
168  void beginRunning();
169 
170  UniqueSendThread createSendThread(const SharedNodePointer& node);
171  virtual UniqueSendThread newSendThread(const SharedNodePointer& node) = 0;
172 
173  int _argc;
174  const char** _argv;
175  char** _parsedArgV;
176  QJsonObject _settings;
177 
178  bool _isShuttingDown = false;
179 
180  std::unique_ptr<HTTPManager> _httpManager;
181  int _statusPort;
182  QString _statusHost;
183 
184  QString _persistFilePath;
185  QString _persistAbsoluteFilePath;
186  QString _persistAsFileType;
187  int _packetsPerClientPerInterval;
188  int _packetsTotalPerInterval;
189  OctreePointer _tree; // this IS a reaveraging tree
190  bool _wantPersist;
191  bool _debugSending;
192  bool _debugReceiving;
193  bool _debugTimestampNow;
194  bool _verboseDebug;
195  OctreeInboundPacketProcessor* _octreeInboundPacketProcessor;
196  OctreePersistThread* _persistManager;
197  QThread _persistThread;
198 
199  std::chrono::milliseconds _persistInterval;
200  bool _persistFileDownload;
201  int _maxBackupVersions;
202 
203  time_t _started;
204  quint64 _startedUSecs;
205  QString _safeServerName;
206 
207  SendThreads _sendThreads;
208 
209  static int _clientCount;
210  static SimpleMovingAverage _averageLoopTime;
211 
212  static SimpleMovingAverage _averageEncodeTime;
213  static SimpleMovingAverage _averageShortEncodeTime;
214  static SimpleMovingAverage _averageLongEncodeTime;
215  static SimpleMovingAverage _averageExtraLongEncodeTime;
216  static int _extraLongEncode;
217  static int _longEncode;
218  static int _shortEncode;
219  static int _noEncode;
220 
221  static SimpleMovingAverage _averageInsideTime;
222 
223  static SimpleMovingAverage _averageTreeWaitTime;
224  static SimpleMovingAverage _averageTreeShortWaitTime;
225  static SimpleMovingAverage _averageTreeLongWaitTime;
226  static SimpleMovingAverage _averageTreeExtraLongWaitTime;
227  static int _extraLongTreeWait;
228  static int _longTreeWait;
229  static int _shortTreeWait;
230  static int _noTreeWait;
231 
232  static SimpleMovingAverage _averageTreeTraverseTime;
233 
234  static SimpleMovingAverage _averageNodeWaitTime;
235 
236  static SimpleMovingAverage _averageCompressAndWriteTime;
237  static SimpleMovingAverage _averageShortCompressTime;
238  static SimpleMovingAverage _averageLongCompressTime;
239  static SimpleMovingAverage _averageExtraLongCompressTime;
240  static int _extraLongCompress;
241  static int _longCompress;
242  static int _shortCompress;
243  static int _noCompress;
244 
245  static SimpleMovingAverage _averagePacketSendingTime;
246  static int _noSend;
247 
248  static SimpleMovingAverage _averageProcessWaitTime;
249  static SimpleMovingAverage _averageProcessShortWaitTime;
250  static SimpleMovingAverage _averageProcessLongWaitTime;
251  static SimpleMovingAverage _averageProcessExtraLongWaitTime;
252  static int _extraLongProcessWait;
253  static int _longProcessWait;
254  static int _shortProcessWait;
255  static int _noProcessWait;
256 
257  static QMap<OctreeSendThread*, quint64> _threadsDidProcess;
258  static QMap<OctreeSendThread*, quint64> _threadsDidPacketDistributor;
259  static QMap<OctreeSendThread*, quint64> _threadsDidHandlePacketSend;
260  static QMap<OctreeSendThread*, quint64> _threadsDidCallWriteDatagram;
261 
262  static QMutex _threadsDidProcessMutex;
263  static QMutex _threadsDidPacketDistributorMutex;
264  static QMutex _threadsDidHandlePacketSendMutex;
265  static QMutex _threadsDidCallWriteDatagramMutex;
266 };
267 
268 #endif // hifi_OctreeServer_h
Handles a single HTTP connection.
Definition: HTTPConnection.h:43
Definition: OctreeInboundPacketProcessor.h:60
Threaded processor for sending octree packets to a single client.
Definition: OctreeSendThread.h:30
Handles assignments of type OctreeServer - sending octrees to various clients.
Definition: OctreeServer.h:38
void setArguments(int argc, char **argv)
allows setting of run arguments
Definition: OctreeServer.cpp:865
void run() override
runs the octree server assignment
Definition: OctreeServer.cpp:1133