0022627: Change OCCT memory management defaults
[occt.git] / src / Draw / Draw_BasicCommands.cxx
CommitLineData
7fd59977 1// File: Draw_BasicCommands.cxx
2// Created: Thu Feb 23 18:21:17 1995
3// Author: Remi LEQUETTE
4// <rle@bravox>
5
6#include <Standard_Macro.hxx>
7#include <Standard_Stream.hxx>
8#include <Standard_SStream.hxx>
9
10#include <Draw.ixx>
11#include <Draw_Appli.hxx>
12#include <Draw_Printer.hxx>
13
14#include <Message.hxx>
15#include <Message_Messenger.hxx>
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20
21#if defined(HAVE_TIME_H) || defined(WNT)
22# include <time.h>
23#endif
24
25#ifdef HAVE_SIGNAL_H
26# include <signal.h>
27#endif
28
29#ifndef WNT
30# include <sys/resource.h>
31# ifdef HAVE_STRINGS_H
32# include <strings.h>
33# endif
34#else
35//WNT
36extern Standard_Boolean Draw_Batch;
37#include <windows.h>
38#include <winbase.h>
39#include <process.h>
40#include <stdio.h>
41#include <stdlib.h>
42#ifdef HAVE_LIMITS
43# include <limits>
44#elif defined (HAVE_LIMITS_H)
45# include <limits.h>
46#endif
47
48#ifdef WNT
49# include <limits>
50#endif
51
52static clock_t MDTV_CPU_LIMIT; // Cpu_limit in Sec.
53static clock_t MDTV_CPU_CURRENT; // cpu time already used at last
54 // cpulimit call. (sec.)
55//#define strcasecmp strcmp Already defined
56#define RLIM_INFINITY 0x7fffffff
57#endif
58
59#include <Draw_Chronometer.hxx>
7af17f1e 60#include <OSD_MAllocHook.hxx>
47cbc555 61#include <OSD_Chronometer.hxx>
7fd59977 62
63#if defined (__hpux) || defined ( HPUX )
64#define RLIM_INFINITY 0x7fffffff
65#define RLIMIT_CPU 0
66#endif
67
68
69
70//=======================================================================
71// chronom
72//=======================================================================
73
74extern Standard_Boolean Draw_Chrono;
75
76static Standard_Integer chronom(Draw_Interpretor& di,
77 Standard_Integer n,const char** a)
78{
79 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
80 if (n == 1)
81 Draw_Chrono = !Draw_Chrono;
82 else
83 Draw_Chrono = (*a[1] == '1');
84
85 if (Draw_Chrono) di << "Chronometers activated."<<"\n";
86 else di << "Chronometers desactivated."<<"\n";
87 }
88 else {
89 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
90 Handle(Draw_Chronometer) C;
91 if (!D.IsNull()) {
92 C = Handle(Draw_Chronometer)::DownCast(D);
93 }
94 if (C.IsNull()) {
95 C = new Draw_Chronometer();
96 Draw::Set(a[1],C,Standard_False);
97 }
98 if (n <= 2) {
99 C->Timer().Reset();
100 }
101 else {
102 if (!strcasecmp(a[2],"reset"))
103 C->Timer().Reset();
104 if (!strcasecmp(a[2],"start"))
105 C->Timer().Start();
106 if (!strcasecmp(a[2],"stop"))
107 C->Timer().Stop();
108 if (!strcasecmp(a[2],"show"))
109 C->Timer().Show();
110 }
111 }
112 return 0;
113}
114
115static Standard_Integer dchronom(Draw_Interpretor& I,
116 Standard_Integer n,const char** a)
117{
118 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
119 if (n == 1)
120 Draw_Chrono = !Draw_Chrono;
121 else
122 Draw_Chrono = (*a[1] == '1');
123
124 if (Draw_Chrono) I << "Chronometers activated."<<"\n";
125 else I << "Chronometers desactivated."<<"\n";
126 }
127 else {
128 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
129 Handle(Draw_Chronometer) C;
130 if (!D.IsNull()) {
131 C = Handle(Draw_Chronometer)::DownCast(D);
132 }
133 if (C.IsNull()) {
134 C = new Draw_Chronometer();
135 Draw::Set(a[1],C,Standard_False);
136 }
137 if (n <= 2) {
138 C->Timer().Reset();
139 }
140 else {
141 if (!strcasecmp(a[2],"reset"))
142 C->Timer().Reset();
143 if (!strcasecmp(a[2],"start"))
144 C->Timer().Start();
145 if (!strcasecmp(a[2],"stop"))
146 C->Timer().Stop();
147 if (!strcasecmp(a[2],"show")) {
148 Standard_SStream ss;
149 C->Timer().Show(ss);
150 I << ss;
151 }
152 }
153 }
154 return 0;
155}
156
157
158
159//=======================================================================
160//function : ifbatch
161//purpose :
162//=======================================================================
163
164static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
165{
166 if (Draw_Batch)
167 DI << "1";
168 else
169 DI << "0";
170
171 return 0;
172}
173
174//=======================================================================
175//function : spy
176//purpose :
177//=======================================================================
178
179extern Standard_Boolean Draw_Spying;
180extern filebuf Draw_Spyfile;
181
182static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
183{
184 if (Draw_Spying)
185 Draw_Spyfile.close();
186 Draw_Spying = Standard_False;
187 if (n > 1) {
188 if (!Draw_Spyfile.open(a[1],ios::out)) {
189 di << "Cannot open "<<a[1]<<" for writing"<<"\n";
190 return 1;
191 }
192 Draw_Spying = Standard_True;
193 }
194 return 0;
195}
196
197//=======================================================================
198//function : wait
199//purpose :
200//=======================================================================
201
202static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
203{
204 Standard_Integer w = 10;
205 if (n > 1)
206 w = atoi(a[1]);
207 time_t ct = time(NULL) + w;
208 while (time(NULL) < ct) {};
209 return 0;
210}
211
47cbc555
A
212//=======================================================================
213//function : cpulimit
214//purpose :
215//=======================================================================
216#ifdef WNT
217static unsigned int __stdcall CpuFunc (void * param)
218{
219 clock_t aCurrent;
220 while (1)
221 {
222 Sleep (5);
223 Standard_Real anUserSeconds, aSystemSeconds;
224 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
225 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
226
227 if ((aCurrent - MDTV_CPU_CURRENT) >= MDTV_CPU_LIMIT)
228 {
229 printf ("CpuFunc : Fin sur Cpu Limit \n");
230 ExitProcess (2);
231 return 0;
232 }
233 }
234 return 0;
235}
236#endif
7fd59977 237
238static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
239{
240#ifndef WNT
241 rlimit rlp;
242 rlp.rlim_max = RLIM_INFINITY;
243 if (n <= 1)
244 rlp.rlim_cur = RLIM_INFINITY;
245 else
246 rlp.rlim_cur = atoi(a[1]);
247
248 int status;
249 status=setrlimit(RLIMIT_CPU,&rlp);
250 if (status !=0)
251 di << "status cpulimit setrlimit : " << status << "\n";
252
253#else
254//WNT
47cbc555 255 static int aFirst = 1;
7fd59977 256
47cbc555
A
257 unsigned int __stdcall CpuFunc (void *);
258 unsigned aThreadID;
259
260 if (n <= 1)
261 MDTV_CPU_LIMIT = RLIM_INFINITY;
262 else
263 {
264 MDTV_CPU_LIMIT = atoi (a[1]);
265 Standard_Real anUserSeconds, aSystemSeconds;
266 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
267 MDTV_CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
268
269 if (aFirst) // Launch the thread only at the 1st call.
270 {
271 aFirst = 0;
272 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
273 }
7fd59977 274 }
275
7fd59977 276#endif
277
278 return 0;
279}
280
7af17f1e
MA
281//=======================================================================
282//function : mallochook
283//purpose :
284//=======================================================================
285
286static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
287 const char** a)
288{
289 if (n < 2)
290 {
291 di << "\
292usage: mallochook cmd\n\
293where cmd is one of:\n\
294 set [<op>] - set callback to malloc/free; op is one of the following:\n\
295 0 - set callback to NULL,\n\
296 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
297 2 - set callback OSD_MAllocHook::LogFileHandler\n\
298 reset - reset the CollectBySize handler\n\
299 report1 [<outfile>]\n\
300 - write report from CollectBySize handler in <outfile>\n\
301 open [<logfile>]\n\
302 - open file for writing the log with LogFileHandler\n\
303 close - close the log file with LogFileHandler\n\
304 report2 [<flag>] [<logfile>] [<outfile>]\n\
305 - scan <logfile> written with LogFileHandler\n\
306 and make synthesized report in <outfile>; <flag> can be:\n\
307 0 - simple stats by sizes (default),\n\
308 1 - with alive allocation numbers\n\
309By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
310 << "\n";
311 return 0;
312 }
313 if (strcmp(a[1], "set") == 0)
314 {
315 int aType = (n > 2 ? atoi(a[2]) : 1);
316 if (aType < 0 || aType > 2)
317 {
318 di << "unknown op of the command set" << "\n";
319 return 1;
320 }
321 else if (aType == 0)
322 {
323 OSD_MAllocHook::SetCallback(NULL);
324 di << "callback is unset" << "\n";
325 }
326 else if (aType == 1)
327 {
328 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
329 di << "callback is set to CollectBySize" << "\n";
330 }
331 else //if (aType == 2)
332 {
333 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
334 di << "callback is set to LogFileHandler" << "\n";
335 }
336 }
337 else if (strcmp(a[1], "reset") == 0)
338 {
339 OSD_MAllocHook::GetCollectBySize()->Reset();
340 di << "CollectBySize handler is reset" << "\n";
341 }
342 else if (strcmp(a[1], "open") == 0)
343 {
344 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
345 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
346 {
347 di << "cannot create file " << aFileName << " for writing" << "\n";
348 return 1;
349 }
350 di << "log file " << aFileName << " is opened for writing" << "\n";
351 }
352 else if (strcmp(a[1], "close") == 0)
353 {
354 OSD_MAllocHook::GetLogFileHandler()->Close();
355 di << "log file is closed" << "\n";
356 }
357 else if (strcmp(a[1], "report1") == 0)
358 {
359 const char* aOutFile = "mem-stat.txt";
360 if (n > 2)
361 aOutFile = a[2];
362 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
363 {
364 di << "report " << aOutFile << " has been created" << "\n";
365 }
366 else
367 {
368 di << "cannot create report " << aOutFile << "\n";
369 return 1;
370 }
371 }
372 else if (strcmp(a[1], "report2") == 0)
373 {
374 Standard_Boolean includeAlive = Standard_False;
375 const char* aLogFile = "mem-log.txt";
376 const char* aOutFile = "mem-stat.txt";
377 if (n > 2)
378 {
379 includeAlive = (atoi(a[2]) != 0);
380 if (n > 3)
381 {
382 aLogFile = a[3];
383 if (n > 4)
384 aOutFile = a[4];
385 }
386 }
387 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
388 {
389 di << "report " << aOutFile << " has been created" << "\n";
390 }
391 else
392 {
393 di << "cannot create report " << aOutFile << " from the log file "
394 << aLogFile << "\n";
395 return 1;
396 }
397 }
398 else
399 {
400 di << "unrecognized command " << a[1] << "\n";
401 return 1;
402 }
403 return 0;
404}
405
7fd59977 406
407void Draw::BasicCommands(Draw_Interpretor& theCommands)
408{
409 static Standard_Boolean Done = Standard_False;
410 if (Done) return;
411 Done = Standard_True;
412
413 const char* g = "DRAW General Commands";
414
415 theCommands.Add("batch", "returns 1 in batch mode",
416 __FILE__,ifbatch,g);
417 theCommands.Add("spy","spy [file], Save commands in file. no file close",
418 __FILE__,spy,g);
419 theCommands.Add("wait","wait [time(10)], wait time seconds",
420 __FILE__,Draw_wait,g);
421 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
422 __FILE__,cpulimit,g);
423 theCommands.Add("chrono","chrono [ name start/stop/reset/show]",
424 __FILE__,chronom,g);
425 theCommands.Add("dchrono","dchrono [ name start/stop/reset/show]",
426 __FILE__,dchronom,g);
7af17f1e
MA
427 theCommands.Add("mallochook",
428 "debug memory allocation/deallocation, w/o args for help",
429 __FILE__, mallochook, g);
7fd59977 430}