roxiedebug.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef ROXIEDEBUG_HPP
  14. #define ROXIEDEBUG_HPP
  15. #include "thorhelper.hpp"
  16. #include "roxiedebug.ipp"
  17. #include "jprop.hpp"
  18. // enum BreakpointMode { BreakpointModeNone, BreakpointModeEdge, BreakpointModeNode, BreakpointModeGraph }; in header file
  19. static const char *BreakpointModes[] = {"none", "edge", "node", "graph", "global", NULL };
  20. // enum BreakpointActionMode { BreakpointActionBreak, BreakpointActionSkip, BreakpointActionLimit, BreakpointActionContinue };
  21. static const char *BreakpointActionModes[] = {"break", "skip", "limit", "continue", NULL };
  22. enum BreakpointConditionMode { BreakpointConditionNone, BreakpointConditionEquals, BreakpointConditionContains, BreakpointConditionStartsWith, BreakpointConditionLess,
  23. BreakpointConditionGreater, BreakpointConditionLessEqual, BreakpointConditionGreaterEqual, BreakpointConditionNotEqual, BreakpointConditionEOG, BreakpointConditionEOF };
  24. static const char *BreakpointConditionModes[] = {"none", "equals", "contains", "startswith", "<", ">", "<=", ">=", "!=", "eog", "eof", NULL };
  25. enum BreakpointCountMode { BreakpointCountNone, BreakpointCountEquals, BreakpointCountAtleast };
  26. static const char *BreakpointCountModes[] = { "none", "equals" , "atleast", NULL };
  27. //=======================================================================================
  28. class THORHELPER_API CDebugCommandHandler : public CInterface, implements IInterface
  29. {
  30. public:
  31. IMPLEMENT_IINTERFACE;
  32. static bool checkCommand(IXmlWriter &out, const char *&supplied, const char *expected);
  33. void doDebugCommand(IPropertyTree *query, IDebuggerContext *debugContext, FlushingStringBuffer &output);
  34. };
  35. //=======================================================================================
  36. interface IActivityDebugContext;
  37. interface IBreakpointInfo : extends IInterface
  38. {
  39. virtual bool equals(IBreakpointInfo &other) const = 0;
  40. virtual void toXML(IXmlWriter *output) const = 0;
  41. virtual bool matches(const void *row, bool isEOF, unsigned edgeRowCount, IOutputMetaData *outputMeta) const = 0;
  42. virtual bool idMatch(BreakpointMode mode, const char *id) const = 0;
  43. virtual BreakpointMode queryMode() const = 0;
  44. virtual BreakpointActionMode queryAction() const = 0;
  45. virtual void noteEdge(IActivityDebugContext &edge) = 0;
  46. virtual void removeEdge(IActivityDebugContext &edge) = 0;
  47. virtual bool canMatchAny(IOutputMetaData *outputMeta) = 0;
  48. virtual void serialize(MemoryBuffer &to) const = 0;
  49. virtual unsigned queryUID() const = 0;
  50. };
  51. //=======================================================================================
  52. #define RESULT_FLUSH_THRESHOLD 10000u
  53. #ifdef _DEBUG
  54. #define SOAP_SPLIT_THRESHOLD 100u
  55. #define SOAP_SPLIT_RESERVE 200u
  56. #else
  57. #define SOAP_SPLIT_THRESHOLD 64000u
  58. #define SOAP_SPLIT_RESERVE 65535u
  59. #endif
  60. //=======================================================================================
  61. class HistoryRow : implements IHistoryRow
  62. {
  63. friend class DebugProbe;
  64. const void *row;
  65. unsigned sequence;
  66. unsigned rowCount;
  67. bool skipped;
  68. bool limited;
  69. bool rowEof;
  70. bool rowEog;
  71. public:
  72. HistoryRow()
  73. {
  74. row = NULL;
  75. sequence = 0;
  76. rowCount = 0;
  77. skipped = false;
  78. limited = false;
  79. rowEof = false;
  80. rowEog = false;
  81. }
  82. virtual const void *queryRow() const { return row; }
  83. virtual unsigned querySequence() const { return sequence; }
  84. virtual unsigned queryRowCount() const { return rowCount; }
  85. virtual bool wasSkipped() const { return skipped; }
  86. virtual bool wasLimited() const { return limited; }
  87. virtual void setSkipped() { skipped = true; }
  88. virtual void setLimited() { limited = true; }
  89. virtual bool wasEof() const { return rowEof; }
  90. virtual bool wasEog() const { return rowEog; }
  91. virtual void setEof() { rowEof = true; }
  92. virtual void setEog() { rowEog = true; }
  93. };
  94. //=======================================================================================
  95. extern THORHELPER_API IRowMatcher *createRowMatcher(const char *fieldName, BreakpointConditionMode condition, const char *value, bool caseSensitive);
  96. extern THORHELPER_API IRowMatcher *createRowMatcher(MemoryBuffer &serialized);
  97. class THORHELPER_API CBreakpointInfo : public CInterface, implements IBreakpointInfo
  98. {
  99. private:
  100. BreakpointMode mode;
  101. BreakpointActionMode action;
  102. BreakpointConditionMode condition;
  103. BreakpointCountMode rowCountMode;
  104. StringAttr id;
  105. unsigned rowCount;
  106. unsigned uid;
  107. ICopyArrayOf<IActivityDebugContext> activeEdges;
  108. Owned<IRowMatcher> rowMatcher;
  109. static SpinLock UIDlock;
  110. static unsigned nextUIDvalue;
  111. static inline unsigned nextUID()
  112. {
  113. SpinBlock b(UIDlock);
  114. return ++nextUIDvalue;
  115. }
  116. public:
  117. IMPLEMENT_IINTERFACE;
  118. CBreakpointInfo(BreakpointMode _mode, const char *_id, BreakpointActionMode _action,
  119. const char *_fieldName, BreakpointConditionMode _condition, const char *_value, bool _caseSensitive,
  120. unsigned _rowCount, BreakpointCountMode _rowCountMode);
  121. CBreakpointInfo(BreakpointMode _mode);
  122. CBreakpointInfo(MemoryBuffer &from);
  123. virtual void serialize(MemoryBuffer &to) const;
  124. virtual unsigned queryUID() const;
  125. virtual void noteEdge(IActivityDebugContext &edge);
  126. virtual void removeEdge(IActivityDebugContext &edge);
  127. virtual bool equals(IBreakpointInfo &other) const;
  128. virtual bool matches(const void *row, bool isEOF, unsigned edgeRowCount, IOutputMetaData *outputMeta) const;
  129. virtual bool idMatch(BreakpointMode _mode, const char *_id) const;
  130. virtual BreakpointMode queryMode() const;
  131. virtual BreakpointActionMode queryAction() const;
  132. virtual void toXML(IXmlWriter *output) const;
  133. virtual bool canMatchAny(IOutputMetaData *meta);
  134. };
  135. //=======================================================================================
  136. interface IDebugGraphManager;
  137. class THORHELPER_API DebugActivityRecord : public CInterface, implements IInterface
  138. {
  139. public:
  140. unsigned __int64 totalCycles;
  141. unsigned __int64 localCycles;
  142. Linked<IActivityBase> activity;
  143. unsigned iteration;
  144. unsigned channel;
  145. unsigned sequence;
  146. IArrayOf<IDebugGraphManager> childGraphs;
  147. StringBuffer idText;
  148. Owned<IProperties> properties;
  149. IMPLEMENT_IINTERFACE;
  150. DebugActivityRecord (IActivityBase *_activity, unsigned _iteration, unsigned _channel, unsigned _sequence);
  151. void outputId(IXmlWriter *output, const char *fieldName);
  152. const char *queryIdString();
  153. void outputProperties(IXmlWriter *output);
  154. void setProperty(const char *propName, const char *propValue, unsigned sequence);
  155. void updateTimes(unsigned _sequence);
  156. };
  157. class THORHELPER_API DebugEdgeRecord : public CInterface, implements IGlobalEdgeRecord
  158. {
  159. unsigned count;
  160. unsigned lastSequence;
  161. public:
  162. IMPLEMENT_IINTERFACE;
  163. DebugEdgeRecord(unsigned sequence) { count = 0; lastSequence = 0; }
  164. // MORE - any of these need locks??
  165. virtual unsigned queryCount() const { return count; }
  166. virtual void incrementCount(int inc, unsigned sequence) { count+= inc; lastSequence = sequence; }
  167. virtual unsigned queryLastSequence() { return lastSequence; }
  168. virtual void reset() { count = 0; lastSequence = 0; }
  169. };
  170. //=======================================================================================
  171. class THORHELPER_API CBaseDebugContext : public CInterface, implements IDebuggableContext
  172. {
  173. protected:
  174. enum WatchState
  175. {
  176. WatchStateStep,
  177. WatchStateNext,
  178. WatchStateOver,
  179. WatchStateGraph,
  180. WatchStateQuit,
  181. WatchStateContinue
  182. };
  183. CriticalSection breakCrit;
  184. mutable MapStringToMyClass<IGlobalEdgeRecord> globalCounts;
  185. // All of these need to be serialized from server to slave...
  186. IArrayOf<IBreakpointInfo> breakpoints; // note- must be destroyed AFTER currentActivity/nextActivity or can have issues.
  187. bool running;
  188. bool detached;
  189. bool stopOnLimits;
  190. bool skipRequested;
  191. WatchState watchState;
  192. unsigned sequence;
  193. // These need to go BACK to server...
  194. unsigned currentBreakpointUID;
  195. // These I haven't thought about yet
  196. IDebugGraphManager *currentGraph;
  197. unsigned graphChangeSequence;
  198. unsigned prevGraphChangeSequence;
  199. bool pendingBreakpointsDone;
  200. unsigned defaultHistoryCapacity;
  201. bool executeSequentially;
  202. // These I think are maintained independently on slave and server
  203. Linked<DebugActivityRecord> currentNode;
  204. Linked<IActivityDebugContext> currentActivity;
  205. Linked<IActivityDebugContext> nextActivity; // Hmmm - needs to be cleared on slave when cleared on server though...
  206. Linked<IException> currentException; // ditto
  207. mutable CriticalSection debugCrit;
  208. const IContextLogger &logctx;
  209. DebugState currentState; // What program was doing when it was interrupted
  210. unsigned debuggerActive;
  211. Semaphore debuggerSem;
  212. unsigned __int64 debugCyclesAdjust;
  213. static const char * queryStateString(DebugState state);
  214. bool _checkPendingBreakpoints(DebugState state, const char *graphName);
  215. // Owned<IProperties> completedGraphs;
  216. IBreakpointInfo *findBreakpoint(unsigned uid) const;
  217. public:
  218. IMPLEMENT_IINTERFACE;
  219. CBaseDebugContext(const IContextLogger &_logctx);
  220. virtual void noteGraphChanged();
  221. virtual unsigned queryChannel() const;
  222. virtual void debugInitialize(const char *id, const char *_queryName, bool _breakAtStart);
  223. virtual void debugTerminate();
  224. virtual BreakpointActionMode checkBreakpoint(DebugState state, IActivityDebugContext *probe, const void *extra);
  225. virtual void waitForDebugger(DebugState state, IActivityDebugContext *probe) = 0;
  226. virtual bool onDebuggerTimeout() = 0;
  227. virtual void noteManager(IDebugGraphManager *mgr);
  228. virtual void releaseManager(IDebugGraphManager *mgr);
  229. virtual unsigned querySequence();
  230. virtual unsigned getDefaultHistoryCapacity() const;
  231. virtual bool getExecuteSequentially() const;
  232. virtual void checkDelayedBreakpoints(IActivityDebugContext *edge);
  233. virtual void serialize(MemoryBuffer &buff) const;
  234. virtual void deserialize(MemoryBuffer &buff);
  235. virtual void addBreakpoint(IBreakpointInfo &bp);
  236. virtual void removeBreakpoint(IBreakpointInfo &bp);
  237. virtual IGlobalEdgeRecord *getEdgeRecord(const char *edgeId);
  238. virtual unsigned __int64 getCyclesAdjustment() const;
  239. };
  240. //=======================================================================================
  241. //Shared by CRoxieServerDebugContext and CHThorDebugContext
  242. #define DEBUGEE_TIMEOUT 10000
  243. class THORHELPER_API CBaseServerDebugContext : public CBaseDebugContext, implements IDebuggerContext
  244. {
  245. // Some questions:
  246. // 1. Do we let all threads go even when say step? Probably... (may allow a thread to be suspended at some point)
  247. // 2. Doesn't that then make a bit of a mockery of step (when there are multiple threads active)... I _think_ it actually means we DON'T try to wait for all
  248. // threads to hit a stop, but allow any that hit stop while we are paused to be queued up to be returned by step.... perhaps actually stop them in critsec rather than
  249. // semaphore and it all becomes easier to code... Anything calling checkBreakPoint while program state is "in debugger" will block on that critSec.
  250. // 3. I think we need to recheck breakpoints on server but just check not deleted
  251. protected:
  252. StringAttr debugId;
  253. SafeSocket &client;
  254. Owned<IPropertyTree> queryXGMML;
  255. Semaphore debugeeSem;
  256. StringAttr queryName;
  257. unsigned previousSequence;
  258. void doStandardResult(IXmlWriter *output) const;
  259. void _listBreakpoint(IXmlWriter *output, IBreakpointInfo &bp, unsigned idx) const;
  260. void _continue(WatchState watch) ;
  261. static unsigned checkOption(const char *supplied, const char *name, const char *accepted[]);
  262. IBreakpointInfo *createDummyBreakpoint();
  263. IBreakpointInfo *_createBreakpoint(const char *modeString, const char *id, const char *action=NULL,
  264. const char *fieldName = NULL, const char *condition=NULL, const char *value=NULL, bool caseSensitive=false,
  265. unsigned hitCount=0, const char *hitCountMode=NULL);
  266. virtual void waitForDebugger(DebugState state, IActivityDebugContext *probe);
  267. public:
  268. IMPLEMENT_IINTERFACE;
  269. CBaseServerDebugContext(const IContextLogger &_logctx, IPropertyTree *_queryXGMML, SafeSocket &_client) ;
  270. void serializeBreakpoints(MemoryBuffer &to);
  271. virtual void debugInitialize(const char *id, const char *_queryName, bool _breakAtStart);
  272. virtual void debugTerminate();
  273. virtual void addBreakpoint(IXmlWriter *output, const char *modeString, const char *id, const char *action,
  274. const char *fieldName, const char *condition, const char *value, bool caseSensitive,
  275. unsigned hitCount, const char *hitCountMode);
  276. virtual void removeBreakpoint(IXmlWriter *output, unsigned removeIdx);
  277. virtual void removeAllBreakpoints(IXmlWriter *output);
  278. virtual void listBreakpoint(IXmlWriter *output, unsigned listIdx) const;
  279. virtual void listAllBreakpoints(IXmlWriter *output) const;
  280. virtual void debugInterrupt(IXmlWriter *output);
  281. virtual void debugContinue(IXmlWriter *output, const char *modeString, const char *id);
  282. virtual void debugRun(IXmlWriter *output) ;
  283. virtual void debugQuit(IXmlWriter *output) ;
  284. virtual void debugSkip(IXmlWriter *output);
  285. virtual void debugStatus(IXmlWriter *output) const;
  286. virtual void debugStep(IXmlWriter *output, const char *modeString);
  287. virtual void debugNext(IXmlWriter *output);
  288. virtual void debugOver(IXmlWriter *output);
  289. virtual void debugChanges(IXmlWriter *output, unsigned sinceSequence) const;
  290. virtual void debugCounts(IXmlWriter *output, unsigned sinceSequence, bool reset);
  291. virtual void debugWhere(IXmlWriter *output) const;
  292. virtual void debugSearch(IXmlWriter *output, const char *fieldName, const char *condition, const char *value, bool caseSensitive, bool fullRows) const;
  293. virtual void debugPrint(IXmlWriter *output, const char *edgeId, unsigned startRow, unsigned numRows) const;
  294. virtual void debugGetConfig(IXmlWriter *output, const char *name, const char *id) const;
  295. virtual void debugSetConfig(IXmlWriter *output, const char *name, const char *value, const char *id);
  296. virtual void getCurrentGraphXGMML(IXmlWriter *output, bool original) const;
  297. virtual void getQueryXGMML(IXmlWriter *output) const;
  298. virtual void getGraphXGMML(IXmlWriter *output, const char *graphName) const;
  299. virtual const char *queryQueryName() const;
  300. virtual const char *queryDebugId() const;
  301. virtual void debugPrintVariable(IXmlWriter *output, const char *name, const char *type) const;
  302. };
  303. //=======================================================================================
  304. class THORHELPER_API CBaseDebugGraphManager : public CInterface, implements IProbeManager, implements IDebugGraphManager
  305. {
  306. class DebugDependencyRecord : public CInterface, implements IInterface
  307. {
  308. public:
  309. IActivityBase *sourceActivity;
  310. unsigned sourceIndex;
  311. unsigned controlId;
  312. unsigned sequence;
  313. const char *edgeId;
  314. IActivityBase *targetActivity;
  315. IMPLEMENT_IINTERFACE;
  316. DebugDependencyRecord(IActivityBase *_sourceActivity, unsigned _sourceIndex, unsigned _controlId, const char *_edgeId, IActivityBase *_targetActivity, unsigned _sequence)
  317. : sourceActivity(_sourceActivity),
  318. sourceIndex(_sourceIndex),
  319. controlId(_controlId),
  320. edgeId(_edgeId),
  321. targetActivity(_targetActivity),
  322. sequence(_sequence)
  323. {
  324. }
  325. };
  326. protected:
  327. IArrayOf<IDebugGraphManager> childGraphs;
  328. MapStringToMyClass<IActivityDebugContext> allProbes;
  329. MapXToMyClass<IActivityBase *, IActivityBase *, DebugActivityRecord> allActivities;
  330. IArrayOf<IActivityBase> sinks;
  331. IArrayOf<DebugDependencyRecord> dependencies;
  332. IDebuggableContext *debugContext;
  333. StringAttr graphName;
  334. mutable CriticalSection crit;
  335. unsigned id;
  336. StringBuffer idString;
  337. mutable memsize_t proxyId; // MORE - does it need to be threadsafe?
  338. DebugActivityRecord *noteActivity(IActivityBase *activity, unsigned iteration, unsigned channel, unsigned sequence);
  339. void outputLinksForChildGraph(IXmlWriter *output, const char *parentId);
  340. void outputChildGraph(IXmlWriter *output, unsigned sequence);
  341. public:
  342. virtual void Link() const;
  343. virtual bool Release() const;
  344. CBaseDebugGraphManager(IDebuggableContext *_debugContext, unsigned _id, const char *_graphName);
  345. virtual IDebugGraphManager *queryDebugManager();
  346. virtual const char *queryIdString() const;
  347. virtual unsigned queryId() const;
  348. virtual IInputBase *createProbe(IInputBase *in, IActivityBase *sourceAct, IActivityBase *targetAct, unsigned sourceIdx, unsigned targetIdx, unsigned iteration)
  349. {
  350. UNIMPLEMENTED;
  351. }
  352. virtual void noteSink(IActivityBase *sink);
  353. virtual void noteDependency(IActivityBase *sourceActivity, unsigned sourceIndex, unsigned controlId, const char *edgeId, IActivityBase *targetActivity);
  354. virtual DebugActivityRecord *getNodeByActivityBase(IActivityBase *activity) const;
  355. virtual void setNodeProperty(IActivityBase *node, const char *propName, const char *propValue);
  356. virtual void setNodePropertyInt(IActivityBase *node, const char *propName, unsigned __int64 propValue);
  357. virtual void getProbeResponse(IPropertyTree *query);
  358. virtual void setHistoryCapacity(unsigned newCapacity);
  359. virtual void clearHistories();
  360. virtual void setBreakpoint(IBreakpointInfo &bp);
  361. virtual void removeBreakpoint(IBreakpointInfo &bp);
  362. IActivityDebugContext *lookupActivityByEdgeId(const char *edgeId);
  363. virtual const char *queryGraphName() const;
  364. virtual void getXGMML(IXmlWriter *output, unsigned sequence, bool isActive);
  365. virtual void searchHistories(IXmlWriter *output, IRowMatcher *matcher, bool fullRows);
  366. virtual memsize_t queryProxyId() const
  367. {
  368. UNIMPLEMENTED;
  369. }
  370. virtual void serializeProxyGraphs(MemoryBuffer &buff);
  371. virtual void deserializeProxyGraphs(DebugState state, MemoryBuffer &buff, IActivityBase *parentActivity, unsigned channel)
  372. {
  373. UNIMPLEMENTED;
  374. }
  375. virtual void mergeRemoteCounts(IDebuggableContext *into) const;
  376. virtual IProbeManager *startChildGraph(unsigned childGraphId, IActivityBase *parent)
  377. {
  378. UNIMPLEMENTED;
  379. }
  380. virtual void endChildGraph(IProbeManager *child, IActivityBase *parent);
  381. virtual void deleteGraph(IArrayOf<IActivityBase> *activities, IArrayOf<IInputBase> *probes)
  382. {
  383. UNIMPLEMENTED;
  384. }
  385. virtual IDebuggableContext *queryContext() const;
  386. };
  387. #endif // ROXIEDEBUG_HPP;