blob: 977465775afe509c2179ddd3e6c66b6c42a655bf [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE %
7% R R E SS O O U U R R C E %
8% RRRR EEE SSS O O U U RRRR C EEE %
9% R R E SS O O U U R R C E %
10% R R EEEEE SSSSS OOO UUU R R CCCC EEEEE %
11% %
12% %
13% Get/Set MagickCore Resources %
14% %
15% Software Design %
16% John Cristy %
17% September 2002 %
18% %
19% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/cache.h"
44#include "MagickCore/configure.h"
45#include "MagickCore/exception.h"
46#include "MagickCore/exception-private.h"
47#include "MagickCore/hashmap.h"
48#include "MagickCore/log.h"
49#include "MagickCore/image.h"
50#include "MagickCore/memory_.h"
51#include "MagickCore/option.h"
52#include "MagickCore/policy.h"
53#include "MagickCore/random_.h"
54#include "MagickCore/registry.h"
55#include "MagickCore/resource_.h"
cristy0a4d92f2011-08-31 19:25:00 +000056#include "MagickCore/resource-private.h"
cristy4c08aed2011-07-01 19:47:50 +000057#include "MagickCore/semaphore.h"
58#include "MagickCore/signature-private.h"
59#include "MagickCore/string_.h"
60#include "MagickCore/string-private.h"
61#include "MagickCore/splay-tree.h"
62#include "MagickCore/thread-private.h"
63#include "MagickCore/token.h"
64#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000065#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000066
67/*
68 Typedef declarations.
69*/
70typedef struct _ResourceInfo
71{
72 MagickOffsetType
73 area,
74 memory,
75 map,
76 disk,
77 file,
78 thread,
cristy7fc1b852013-01-27 16:47:26 +000079 throttle,
cristy3ed852e2009-09-05 21:47:34 +000080 time;
81
82 MagickSizeType
83 area_limit,
84 memory_limit,
85 map_limit,
86 disk_limit,
87 file_limit,
88 thread_limit,
cristy7fc1b852013-01-27 16:47:26 +000089 throttle_limit,
cristy3ed852e2009-09-05 21:47:34 +000090 time_limit;
91} ResourceInfo;
92
93/*
94 Global declarations.
95*/
96static RandomInfo
97 *random_info = (RandomInfo *) NULL;
98
99static ResourceInfo
100 resource_info =
101 {
cristye3e3d7a2013-03-17 12:54:36 +0000102 MagickULLConstant(0), /* initial area */
103 MagickULLConstant(0), /* initial memory */
104 MagickULLConstant(0), /* initial map */
105 MagickULLConstant(0), /* initial disk */
106 MagickULLConstant(0), /* initial file */
107 MagickULLConstant(0), /* initial thread */
108 MagickULLConstant(0), /* initial throttle */
109 MagickULLConstant(0), /* initial time */
110 MagickULLConstant(3072)*1024*1024, /* area limit */
111 MagickULLConstant(1536)*1024*1024, /* memory limit */
112 MagickULLConstant(3072)*1024*1024, /* map limit */
113 MagickResourceInfinity, /* disk limit */
114 MagickULLConstant(768), /* file limit */
115 MagickULLConstant(1), /* thread limit */
116 MagickULLConstant(0), /* throttle limit */
117 MagickResourceInfinity /* time limit */
cristy3ed852e2009-09-05 21:47:34 +0000118 };
119
120static SemaphoreInfo
121 *resource_semaphore = (SemaphoreInfo *) NULL;
122
123static SplayTreeInfo
124 *temporary_resources = (SplayTreeInfo *) NULL;
125
126/*
127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128% %
129% %
130% %
131% A c q u i r e M a g i c k R e s o u r c e %
132% %
133% %
134% %
135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136%
137% AcquireMagickResource() acquires resources of the specified type.
138% MagickFalse is returned if the specified resource is exhausted otherwise
139% MagickTrue.
140%
141% The format of the AcquireMagickResource() method is:
142%
143% MagickBooleanType AcquireMagickResource(const ResourceType type,
144% const MagickSizeType size)
145%
146% A description of each parameter follows:
147%
148% o type: the type of resource.
149%
150% o size: the number of bytes needed from for this resource.
151%
152*/
153MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
154 const MagickSizeType size)
155{
156 char
157 resource_current[MaxTextExtent],
158 resource_limit[MaxTextExtent],
159 resource_request[MaxTextExtent];
160
161 MagickBooleanType
162 status;
163
164 MagickSizeType
165 limit;
166
167 status=MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000168 (void) FormatMagickSize(size,MagickFalse,resource_request);
cristy18b17442009-10-25 18:36:48 +0000169 if (resource_semaphore == (SemaphoreInfo *) NULL)
170 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000171 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000172 switch (type)
173 {
174 case AreaResource:
175 {
176 resource_info.area=(MagickOffsetType) size;
177 limit=resource_info.area_limit;
178 status=(resource_info.area_limit == MagickResourceInfinity) ||
179 (size < limit) ? MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000180 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000181 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000182 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
183 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000184 break;
185 }
186 case MemoryResource:
187 {
188 resource_info.memory+=size;
189 limit=resource_info.memory_limit;
190 status=(resource_info.memory_limit == MagickResourceInfinity) ||
cristya86d3612012-12-14 14:47:26 +0000191 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
192 MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000193 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000194 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000195 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000196 resource_limit);
197 break;
198 }
199 case MapResource:
200 {
201 resource_info.map+=size;
202 limit=resource_info.map_limit;
203 status=(resource_info.map_limit == MagickResourceInfinity) ||
cristya86d3612012-12-14 14:47:26 +0000204 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000205 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000206 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000207 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000208 resource_limit);
209 break;
210 }
211 case DiskResource:
212 {
213 resource_info.disk+=size;
214 limit=resource_info.disk_limit;
215 status=(resource_info.disk_limit == MagickResourceInfinity) ||
cristya86d3612012-12-14 14:47:26 +0000216 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
217 MagickFalse;
cristy518d13d2011-01-04 15:25:24 +0000218 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000219 resource_current);
cristy518d13d2011-01-04 15:25:24 +0000220 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
cristyb9080c92009-12-01 20:13:26 +0000221 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000222 break;
223 }
224 case FileResource:
225 {
226 resource_info.file+=size;
227 limit=resource_info.file_limit;
228 status=(resource_info.file_limit == MagickResourceInfinity) ||
229 ((MagickSizeType) resource_info.file < limit) ?
230 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000231 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000232 resource_current);
233 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
cristyb9080c92009-12-01 20:13:26 +0000234 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000235 break;
236 }
237 case ThreadResource:
238 {
cristy3ed852e2009-09-05 21:47:34 +0000239 limit=resource_info.thread_limit;
240 status=(resource_info.thread_limit == MagickResourceInfinity) ||
241 ((MagickSizeType) resource_info.thread < limit) ?
242 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000243 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000244 resource_current);
245 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
cristyb9080c92009-12-01 20:13:26 +0000246 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000247 break;
248 }
cristy7fc1b852013-01-27 16:47:26 +0000249 case ThrottleResource:
250 {
251 limit=resource_info.throttle_limit;
252 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
253 ((MagickSizeType) resource_info.throttle < limit) ?
254 MagickTrue : MagickFalse;
255 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
256 MagickFalse,resource_current);
257 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
258 MagickFalse,resource_limit);
259 break;
260 }
cristy3ed852e2009-09-05 21:47:34 +0000261 case TimeResource:
262 {
263 resource_info.time+=size;
264 limit=resource_info.time_limit;
265 status=(resource_info.time_limit == MagickResourceInfinity) ||
266 ((MagickSizeType) resource_info.time < limit) ?
267 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000268 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000269 resource_current);
270 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
cristyb9080c92009-12-01 20:13:26 +0000271 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000272 break;
273 }
274 default:
275 break;
276 }
cristyf84a1932010-01-03 18:00:18 +0000277 UnlockSemaphoreInfo(resource_semaphore);
cristy9bfdd582010-10-23 01:27:25 +0000278 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
cristy042ee782011-04-22 18:48:30 +0000279 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
cristya21afde2010-07-02 00:45:40 +0000280 resource_request,resource_current,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000281 return(status);
282}
283
284/*
285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286% %
287% %
288% %
cristycfffdac2010-09-30 03:05:09 +0000289+ A s y n c h r o n o u s R e s o u r c e C o m p o n e n t T e r m i n u s %
cristy3ed852e2009-09-05 21:47:34 +0000290% %
291% %
292% %
293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294%
cristyf34a1452009-10-24 22:29:27 +0000295% AsynchronousResourceComponentTerminus() destroys the resource environment.
296% It differs from ResourceComponentTerminus() in that it can be called from a
cristy3ed852e2009-09-05 21:47:34 +0000297% asynchronous signal handler.
298%
cristyf34a1452009-10-24 22:29:27 +0000299% The format of the ResourceComponentTerminus() method is:
cristy3ed852e2009-09-05 21:47:34 +0000300%
cristyf34a1452009-10-24 22:29:27 +0000301% ResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000302%
303*/
cristy0a4d92f2011-08-31 19:25:00 +0000304MagickPrivate void AsynchronousResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000305{
306 const char
307 *path;
308
309 if (temporary_resources == (SplayTreeInfo *) NULL)
310 return;
311 /*
312 Remove any lingering temporary files.
313 */
314 ResetSplayTreeIterator(temporary_resources);
315 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
316 while (path != (const char *) NULL)
317 {
cristy59864562013-04-18 11:47:41 +0000318 (void) ShredFile(path);
cristy3ed852e2009-09-05 21:47:34 +0000319 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
320 }
321}
322
323/*
324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325% %
326% %
327% %
328% A c q u i r e U n i q u e F i l e R e s o u r c e %
329% %
330% %
331% %
332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333%
334% AcquireUniqueFileResource() returns a unique file name, and returns a file
335% descriptor for the file open for reading and writing.
336%
337% The format of the AcquireUniqueFileResource() method is:
338%
339% int AcquireUniqueFileResource(char *path)
340%
341% A description of each parameter follows:
342%
343% o path: Specifies a pointer to an array of characters. The unique path
344% name is returned in this array.
345%
346*/
347
348static void *DestroyTemporaryResources(void *temporary_resource)
349{
cristy59864562013-04-18 11:47:41 +0000350 (void) ShredFile((char *) temporary_resource);
cristycfbec6a2010-09-28 18:27:51 +0000351 temporary_resource=DestroyString((char *) temporary_resource);
cristy3ed852e2009-09-05 21:47:34 +0000352 return((void *) NULL);
353}
354
glennrp4084cda2012-12-11 14:13:35 +0000355MagickExport MagickBooleanType GetPathTemplate(char *path)
cristy3ed852e2009-09-05 21:47:34 +0000356{
357 char
cristy86c8d8a2012-11-28 12:50:22 +0000358 *directory,
359 *value;
cristy3ed852e2009-09-05 21:47:34 +0000360
361 ExceptionInfo
362 *exception;
363
364 MagickBooleanType
365 status;
366
367 register char
368 *p;
369
370 struct stat
371 attributes;
372
cristy65a933a2012-10-18 11:58:05 +0000373 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
cristy3080b912012-10-17 13:23:44 +0000374 (double) getpid());
cristy3ed852e2009-09-05 21:47:34 +0000375 exception=AcquireExceptionInfo();
376 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
377 exception);
378 exception=DestroyExceptionInfo(exception);
379 if (directory == (char *) NULL)
380 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
381 if (directory == (char *) NULL)
382 directory=GetEnvironmentValue("MAGICK_TMPDIR");
383 if (directory == (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000384 directory=GetEnvironmentValue("TMPDIR");
cristy0157aea2010-04-24 21:12:18 +0000385#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +0000386 if (directory == (char *) NULL)
387 directory=GetEnvironmentValue("TMP");
388 if (directory == (char *) NULL)
389 directory=GetEnvironmentValue("TEMP");
390#endif
391#if defined(__VMS)
392 if (directory == (char *) NULL)
393 directory=GetEnvironmentValue("MTMPDIR");
394#endif
395#if defined(P_tmpdir)
396 if (directory == (char *) NULL)
397 directory=ConstantString(P_tmpdir);
398#endif
399 if (directory == (char *) NULL)
400 return(MagickTrue);
cristy86c8d8a2012-11-28 12:50:22 +0000401 value=GetPolicyValue("temporary-path");
402 if (value != (char *) NULL)
403 (void) CloneString(&directory,value);
cristycdb573d2012-10-18 11:55:05 +0000404 if (strlen(directory) > (MaxTextExtent-25))
cristy3ed852e2009-09-05 21:47:34 +0000405 {
406 directory=DestroyString(directory);
cristy86c8d8a2012-11-28 12:50:22 +0000407 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000408 }
409 status=GetPathAttributes(directory,&attributes);
410 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
411 {
412 directory=DestroyString(directory);
cristy86c8d8a2012-11-28 12:50:22 +0000413 return(MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000414 }
415 if (directory[strlen(directory)-1] == *DirectorySeparator)
cristy65a933a2012-10-18 11:58:05 +0000416 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
cristy3080b912012-10-17 13:23:44 +0000417 directory,(double) getpid());
cristy3ed852e2009-09-05 21:47:34 +0000418 else
cristy65a933a2012-10-18 11:58:05 +0000419 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-%.20gXXXXXXXXXXXX",
420 directory,DirectorySeparator,(double) getpid());
cristy3ed852e2009-09-05 21:47:34 +0000421 directory=DestroyString(directory);
422 if (*DirectorySeparator != '/')
423 for (p=path; *p != '\0'; p++)
424 if (*p == *DirectorySeparator)
425 *p='/';
426 return(MagickTrue);
427}
428
429MagickExport int AcquireUniqueFileResource(char *path)
430{
431#if !defined(O_NOFOLLOW)
432#define O_NOFOLLOW 0
433#endif
434#if !defined(TMP_MAX)
435# define TMP_MAX 238328
436#endif
437
cristy3ed852e2009-09-05 21:47:34 +0000438 int
439 c,
440 file;
441
442 register char
443 *p;
444
cristybb503372010-05-27 20:51:26 +0000445 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000446 i;
447
448 static const char
449 portable_filename[65] =
450 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
451
452 StringInfo
453 *key;
454
455 unsigned char
456 *datum;
457
458 assert(path != (char *) NULL);
459 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
460 if (random_info == (RandomInfo *) NULL)
461 random_info=AcquireRandomInfo();
462 file=(-1);
cristycee97112010-05-28 00:44:52 +0000463 for (i=0; i < (ssize_t) TMP_MAX; i++)
cristy3ed852e2009-09-05 21:47:34 +0000464 {
465 /*
466 Get temporary pathname.
467 */
468 (void) GetPathTemplate(path);
cristycb8cea72012-10-18 12:06:29 +0000469 key=GetRandomKey(random_info,6);
cristycdb573d2012-10-18 11:55:05 +0000470 p=path+strlen(path)-12;
cristy59ca45d2011-02-03 14:54:57 +0000471 datum=GetStringInfoDatum(key);
472 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
473 {
474 c=(int) (datum[i] & 0x3f);
475 *p++=portable_filename[c];
476 }
477 key=DestroyStringInfo(key);
cristy3ed852e2009-09-05 21:47:34 +0000478#if defined(MAGICKCORE_HAVE_MKSTEMP)
479 file=mkstemp(path);
480#if defined(__OS2__)
481 setmode(file,O_BINARY);
482#endif
483 if (file != -1)
484 break;
485#endif
cristycdb573d2012-10-18 11:55:05 +0000486 key=GetRandomKey(random_info,12);
487 p=path+strlen(path)-12;
cristy3ed852e2009-09-05 21:47:34 +0000488 datum=GetStringInfoDatum(key);
cristy59ca45d2011-02-03 14:54:57 +0000489 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
cristy3ed852e2009-09-05 21:47:34 +0000490 {
491 c=(int) (datum[i] & 0x3f);
492 *p++=portable_filename[c];
493 }
494 key=DestroyStringInfo(key);
cristycdb573d2012-10-18 11:55:05 +0000495 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
496 S_MODE);
cristy59ca45d2011-02-03 14:54:57 +0000497 if ((file >= 0) || (errno != EEXIST))
cristy3ed852e2009-09-05 21:47:34 +0000498 break;
499 }
500 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
501 if (file == -1)
502 return(file);
cristy18b17442009-10-25 18:36:48 +0000503 if (resource_semaphore == (SemaphoreInfo *) NULL)
504 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000505 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000506 if (temporary_resources == (SplayTreeInfo *) NULL)
507 temporary_resources=NewSplayTree(CompareSplayTreeString,
cristyf77fa462010-09-28 18:35:53 +0000508 DestroyTemporaryResources,(void *(*)(void *)) NULL);
cristyf84a1932010-01-03 18:00:18 +0000509 UnlockSemaphoreInfo(resource_semaphore);
cristycfbec6a2010-09-28 18:27:51 +0000510 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
cristyf77fa462010-09-28 18:35:53 +0000511 (const void *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000512 return(file);
513}
514
515/*
516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517% %
518% %
519% %
cristy3ed852e2009-09-05 21:47:34 +0000520% G e t M a g i c k R e s o u r c e %
521% %
522% %
523% %
524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525%
526% GetMagickResource() returns the specified resource.
527%
528% The format of the GetMagickResource() method is:
529%
530% MagickSizeType GetMagickResource(const ResourceType type)
531%
532% A description of each parameter follows:
533%
534% o type: the type of resource.
535%
536*/
537MagickExport MagickSizeType GetMagickResource(const ResourceType type)
538{
539 MagickSizeType
540 resource;
541
542 resource=0;
cristyf84a1932010-01-03 18:00:18 +0000543 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000544 switch (type)
545 {
546 case AreaResource:
547 {
548 resource=(MagickSizeType) resource_info.area;
549 break;
550 }
551 case MemoryResource:
552 {
553 resource=(MagickSizeType) resource_info.memory;
554 break;
555 }
556 case MapResource:
557 {
558 resource=(MagickSizeType) resource_info.map;
559 break;
560 }
561 case DiskResource:
562 {
563 resource=(MagickSizeType) resource_info.disk;
564 break;
565 }
566 case FileResource:
567 {
568 resource=(MagickSizeType) resource_info.file;
569 break;
570 }
571 case ThreadResource:
572 {
573 resource=(MagickSizeType) resource_info.thread;
574 break;
575 }
cristy7fc1b852013-01-27 16:47:26 +0000576 case ThrottleResource:
577 {
578 resource=(MagickSizeType) resource_info.throttle;
579 break;
580 }
cristy3ed852e2009-09-05 21:47:34 +0000581 case TimeResource:
582 {
583 resource=(MagickSizeType) resource_info.time;
584 break;
585 }
586 default:
587 break;
588 }
cristyf84a1932010-01-03 18:00:18 +0000589 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000590 return(resource);
591}
592
593/*
594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595% %
596% %
597% %
598% G e t M a g i c k R e s o u r c e L i m i t %
599% %
600% %
601% %
602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603%
cristy7a40ba82011-01-08 20:31:18 +0000604% GetMagickResourceLimit() returns the specified resource limit.
cristy3ed852e2009-09-05 21:47:34 +0000605%
606% The format of the GetMagickResourceLimit() method is:
607%
cristy50a10922010-02-15 18:35:25 +0000608% MagickSizeType GetMagickResourceLimit(const ResourceType type)
cristy3ed852e2009-09-05 21:47:34 +0000609%
610% A description of each parameter follows:
611%
612% o type: the type of resource.
613%
614*/
615MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
616{
617 MagickSizeType
618 resource;
619
620 resource=0;
cristy18b17442009-10-25 18:36:48 +0000621 if (resource_semaphore == (SemaphoreInfo *) NULL)
622 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000623 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000624 switch (type)
625 {
626 case AreaResource:
627 {
628 resource=resource_info.area_limit;
629 break;
630 }
631 case MemoryResource:
632 {
633 resource=resource_info.memory_limit;
634 break;
635 }
636 case MapResource:
637 {
638 resource=resource_info.map_limit;
639 break;
640 }
641 case DiskResource:
642 {
643 resource=resource_info.disk_limit;
644 break;
645 }
646 case FileResource:
647 {
648 resource=resource_info.file_limit;
649 break;
650 }
651 case ThreadResource:
652 {
653 resource=resource_info.thread_limit;
654 break;
655 }
cristy7fc1b852013-01-27 16:47:26 +0000656 case ThrottleResource:
657 {
658 resource=resource_info.throttle_limit;
659 break;
660 }
cristy3ed852e2009-09-05 21:47:34 +0000661 case TimeResource:
662 {
663 resource=resource_info.time_limit;
664 break;
665 }
666 default:
667 break;
668 }
cristyf84a1932010-01-03 18:00:18 +0000669 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000670 return(resource);
671}
672
673/*
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675% %
676% %
677% %
cristy3ed852e2009-09-05 21:47:34 +0000678% L i s t M a g i c k R e s o u r c e I n f o %
679% %
680% %
681% %
682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683%
684% ListMagickResourceInfo() lists the resource info to a file.
685%
686% The format of the ListMagickResourceInfo method is:
687%
688% MagickBooleanType ListMagickResourceInfo(FILE *file,
689% ExceptionInfo *exception)
690%
691% A description of each parameter follows.
692%
693% o file: An pointer to a FILE.
694%
695% o exception: return any errors or warnings in this structure.
696%
697*/
698MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
699 ExceptionInfo *magick_unused(exception))
700{
701 char
702 area_limit[MaxTextExtent],
703 disk_limit[MaxTextExtent],
704 map_limit[MaxTextExtent],
705 memory_limit[MaxTextExtent],
706 time_limit[MaxTextExtent];
707
708 if (file == (const FILE *) NULL)
709 file=stdout;
cristy18b17442009-10-25 18:36:48 +0000710 if (resource_semaphore == (SemaphoreInfo *) NULL)
711 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000712 LockSemaphoreInfo(resource_semaphore);
cristyb9080c92009-12-01 20:13:26 +0000713 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
714 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
715 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
cristy9bfdd582010-10-23 01:27:25 +0000716 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
717 if (resource_info.disk_limit != MagickResourceInfinity)
cristy518d13d2011-01-04 15:25:24 +0000718 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
cristy3ed852e2009-09-05 21:47:34 +0000719 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
720 if (resource_info.time_limit != MagickResourceInfinity)
cristyb51dff52011-05-19 16:55:47 +0000721 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
cristy54ea5732011-06-10 12:39:53 +0000722 ((MagickOffsetType) resource_info.time_limit));
cristy7fc1b852013-01-27 16:47:26 +0000723 (void) FormatLocaleFile(file," File Area Memory Map"
724 " Disk Thread Throttle Time\n");
cristy1e604812011-05-19 18:07:50 +0000725 (void) FormatLocaleFile(file,
726 "--------------------------------------------------------"
cristy7fc1b852013-01-27 16:47:26 +0000727 "------------------------\n");
728 (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %8g %8g %10s\n",
cristy54ea5732011-06-10 12:39:53 +0000729 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
730 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
cristy7fc1b852013-01-27 16:47:26 +0000731 resource_info.thread_limit),(double) ((MagickOffsetType)
732 resource_info.throttle_limit),time_limit);
cristy3ed852e2009-09-05 21:47:34 +0000733 (void) fflush(file);
cristyf84a1932010-01-03 18:00:18 +0000734 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000735 return(MagickTrue);
736}
737
738/*
739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
740% %
741% %
742% %
743% R e l i n q u i s h M a g i c k R e s o u r c e %
744% %
745% %
746% %
747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748%
749% RelinquishMagickResource() relinquishes resources of the specified type.
750%
751% The format of the RelinquishMagickResource() method is:
752%
753% void RelinquishMagickResource(const ResourceType type,
754% const MagickSizeType size)
755%
756% A description of each parameter follows:
757%
758% o type: the type of resource.
759%
760% o size: the size of the resource.
761%
762*/
763MagickExport void RelinquishMagickResource(const ResourceType type,
764 const MagickSizeType size)
765{
766 char
767 resource_current[MaxTextExtent],
768 resource_limit[MaxTextExtent],
769 resource_request[MaxTextExtent];
770
cristyb9080c92009-12-01 20:13:26 +0000771 (void) FormatMagickSize(size,MagickFalse,resource_request);
cristy18b17442009-10-25 18:36:48 +0000772 if (resource_semaphore == (SemaphoreInfo *) NULL)
773 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000774 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000775 switch (type)
776 {
777 case AreaResource:
778 {
779 resource_info.area=(MagickOffsetType) size;
cristyb9080c92009-12-01 20:13:26 +0000780 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000781 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000782 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
783 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000784 break;
785 }
786 case MemoryResource:
787 {
788 resource_info.memory-=size;
789 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
cristyb9080c92009-12-01 20:13:26 +0000790 MagickTrue,resource_current);
791 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
792 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000793 break;
794 }
795 case MapResource:
796 {
797 resource_info.map-=size;
cristyb9080c92009-12-01 20:13:26 +0000798 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000799 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000800 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
801 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000802 break;
803 }
804 case DiskResource:
805 {
806 resource_info.disk-=size;
cristy518d13d2011-01-04 15:25:24 +0000807 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000808 resource_current);
cristy518d13d2011-01-04 15:25:24 +0000809 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
cristyb9080c92009-12-01 20:13:26 +0000810 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000811 break;
812 }
813 case FileResource:
814 {
815 resource_info.file-=size;
cristyb9080c92009-12-01 20:13:26 +0000816 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000817 resource_current);
818 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
cristyb9080c92009-12-01 20:13:26 +0000819 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000820 break;
821 }
822 case ThreadResource:
823 {
cristyb9080c92009-12-01 20:13:26 +0000824 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000825 resource_current);
826 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
cristyb9080c92009-12-01 20:13:26 +0000827 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000828 break;
829 }
cristy7fc1b852013-01-27 16:47:26 +0000830 case ThrottleResource:
831 {
832 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
833 MagickFalse,resource_current);
834 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
835 MagickFalse,resource_limit);
836 break;
837 }
cristy3ed852e2009-09-05 21:47:34 +0000838 case TimeResource:
839 {
840 resource_info.time-=size;
cristyb9080c92009-12-01 20:13:26 +0000841 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000842 resource_current);
843 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
cristyb9080c92009-12-01 20:13:26 +0000844 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000845 break;
846 }
847 default:
848 break;
849 }
cristyf84a1932010-01-03 18:00:18 +0000850 UnlockSemaphoreInfo(resource_semaphore);
cristy9bfdd582010-10-23 01:27:25 +0000851 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
cristy042ee782011-04-22 18:48:30 +0000852 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
cristya21afde2010-07-02 00:45:40 +0000853 resource_request,resource_current,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000854}
855
856/*
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858% %
859% %
860% %
861% R e l i n q u i s h U n i q u e F i l e R e s o u r c e %
862% %
863% %
864% %
865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866%
867% RelinquishUniqueFileResource() relinquishes a unique file resource.
868%
869% The format of the RelinquishUniqueFileResource() method is:
870%
871% MagickBooleanType RelinquishUniqueFileResource(const char *path)
872%
873% A description of each parameter follows:
874%
875% o name: the name of the temporary resource.
876%
877*/
878MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
879{
880 char
881 cache_path[MaxTextExtent];
882
883 assert(path != (const char *) NULL);
884 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
885 if (temporary_resources != (SplayTreeInfo *) NULL)
886 {
887 register char
888 *p;
889
890 ResetSplayTreeIterator(temporary_resources);
891 p=(char *) GetNextKeyInSplayTree(temporary_resources);
892 while (p != (char *) NULL)
893 {
894 if (LocaleCompare(p,path) == 0)
895 break;
896 p=(char *) GetNextKeyInSplayTree(temporary_resources);
897 }
898 if (p != (char *) NULL)
899 (void) DeleteNodeFromSplayTree(temporary_resources,p);
900 }
901 (void) CopyMagickString(cache_path,path,MaxTextExtent);
902 AppendImageFormat("cache",cache_path);
cristy59864562013-04-18 11:47:41 +0000903 (void) ShredFile(cache_path);
904 return(ShredFile(path));
cristy3ed852e2009-09-05 21:47:34 +0000905}
906
907/*
908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909% %
910% %
911% %
cristyf34a1452009-10-24 22:29:27 +0000912+ R e s o u r c e C o m p o n e n t G e n e s i s %
913% %
914% %
915% %
916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917%
918% ResourceComponentGenesis() instantiates the resource component.
919%
920% The format of the ResourceComponentGenesis method is:
921%
922% MagickBooleanType ResourceComponentGenesis(void)
923%
924*/
925
cristy652316c2010-11-23 13:49:46 +0000926static inline size_t MagickMax(const size_t x,const size_t y)
cristyf34a1452009-10-24 22:29:27 +0000927{
928 if (x > y)
929 return(x);
930 return(y);
931}
932
933static inline MagickSizeType StringToSizeType(const char *string,
934 const double interval)
935{
936 double
937 value;
938
cristy9b34e302011-11-05 02:15:45 +0000939 value=SiPrefixToDoubleInterval(string,interval);
cristyf34a1452009-10-24 22:29:27 +0000940 if (value >= (double) MagickULLConstant(~0))
941 return(MagickULLConstant(~0));
942 return((MagickSizeType) value);
943}
944
cristy5ff4eaf2011-09-03 01:38:02 +0000945MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000946{
947 char
948 *limit;
949
cristy9d314ff2011-03-09 01:30:28 +0000950 MagickSizeType
951 memory;
952
cristybb503372010-05-27 20:51:26 +0000953 ssize_t
cristyf34a1452009-10-24 22:29:27 +0000954 files,
955 pages,
956 pagesize;
957
cristyf34a1452009-10-24 22:29:27 +0000958 /*
959 Set Magick resource limits.
960 */
cristy165b6092009-10-26 13:52:10 +0000961 AcquireSemaphoreInfo(&resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000962 pagesize=GetMagickPageSize();
963 pages=(-1);
964#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
cristycee97112010-05-28 00:44:52 +0000965 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
cristyf34a1452009-10-24 22:29:27 +0000966#endif
967 memory=(MagickSizeType) pages*pagesize;
968 if ((pagesize <= 0) || (pages <= 0))
969 memory=2048UL*1024UL*1024UL;
970#if defined(PixelCacheThreshold)
971 memory=PixelCacheThreshold;
972#endif
cristy2b97bd22011-10-04 18:12:42 +0000973 (void) SetMagickResourceLimit(AreaResource,2*memory);
cristyf34a1452009-10-24 22:29:27 +0000974 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
cristyf34a1452009-10-24 22:29:27 +0000975 if (limit != (char *) NULL)
976 {
977 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
978 limit=DestroyString(limit);
979 }
cristy7fc1b852013-01-27 16:47:26 +0000980 (void) SetMagickResourceLimit(MemoryResource,memory);
cristyf34a1452009-10-24 22:29:27 +0000981 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
cristyf34a1452009-10-24 22:29:27 +0000982 if (limit != (char *) NULL)
983 {
984 (void) SetMagickResourceLimit(MemoryResource,
985 StringToSizeType(limit,100.0));
986 limit=DestroyString(limit);
987 }
cristy7fc1b852013-01-27 16:47:26 +0000988 (void) SetMagickResourceLimit(MapResource,2*memory);
cristyf34a1452009-10-24 22:29:27 +0000989 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
cristyf34a1452009-10-24 22:29:27 +0000990 if (limit != (char *) NULL)
991 {
992 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
993 limit=DestroyString(limit);
994 }
cristy7fc1b852013-01-27 16:47:26 +0000995 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
cristyf34a1452009-10-24 22:29:27 +0000996 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
cristyf34a1452009-10-24 22:29:27 +0000997 if (limit != (char *) NULL)
998 {
999 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1000 limit=DestroyString(limit);
1001 }
1002 files=(-1);
1003#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
cristycee97112010-05-28 00:44:52 +00001004 files=(ssize_t) sysconf(_SC_OPEN_MAX);
cristyf34a1452009-10-24 22:29:27 +00001005#endif
1006#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1007 if (files < 0)
1008 {
1009 struct rlimit
1010 resources;
1011
1012 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
cristybb503372010-05-27 20:51:26 +00001013 files=(ssize_t) resources.rlim_cur;
cristyf34a1452009-10-24 22:29:27 +00001014 }
1015#endif
1016#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1017 if (files < 0)
cristy6d0ee3e2010-09-28 18:36:50 +00001018 files=(ssize_t) getdtablesize();
cristyf34a1452009-10-24 22:29:27 +00001019#endif
1020 if (files < 0)
1021 files=64;
cristybb503372010-05-27 20:51:26 +00001022 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
cristyddacdd12012-05-07 23:08:14 +00001023 (3*files/4),64));
cristyf34a1452009-10-24 22:29:27 +00001024 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
cristyf34a1452009-10-24 22:29:27 +00001025 if (limit != (char *) NULL)
1026 {
cristycfce4c92011-12-11 17:28:48 +00001027 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1028 100.0));
cristyf34a1452009-10-24 22:29:27 +00001029 limit=DestroyString(limit);
1030 }
1031 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
cristyd3200452012-12-30 00:33:28 +00001032 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
cristyf34a1452009-10-24 22:29:27 +00001033 if (limit != (char *) NULL)
1034 {
cristyf34a1452009-10-24 22:29:27 +00001035 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1036 100.0));
1037 limit=DestroyString(limit);
1038 }
cristy7fc1b852013-01-27 16:47:26 +00001039 (void) SetMagickResourceLimit(ThrottleResource,0);
1040 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1041 if (limit != (char *) NULL)
1042 {
1043 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1044 100.0));
1045 limit=DestroyString(limit);
1046 }
1047 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
cristyf34a1452009-10-24 22:29:27 +00001048 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
cristyf34a1452009-10-24 22:29:27 +00001049 if (limit != (char *) NULL)
1050 {
1051 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1052 limit=DestroyString(limit);
1053 }
1054 return(MagickTrue);
1055}
1056
1057/*
1058%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059% %
1060% %
1061% %
1062+ R e s o u r c e C o m p o n e n t T e r m i n u s %
1063% %
1064% %
1065% %
1066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067%
1068% ResourceComponentTerminus() destroys the resource component.
1069%
1070% The format of the ResourceComponentTerminus() method is:
1071%
1072% ResourceComponentTerminus(void)
1073%
1074*/
cristy5ff4eaf2011-09-03 01:38:02 +00001075MagickPrivate void ResourceComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001076{
cristy18b17442009-10-25 18:36:48 +00001077 if (resource_semaphore == (SemaphoreInfo *) NULL)
1078 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001079 LockSemaphoreInfo(resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001080 if (temporary_resources != (SplayTreeInfo *) NULL)
1081 temporary_resources=DestroySplayTree(temporary_resources);
1082 if (random_info != (RandomInfo *) NULL)
1083 random_info=DestroyRandomInfo(random_info);
cristyf84a1932010-01-03 18:00:18 +00001084 UnlockSemaphoreInfo(resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001085 DestroySemaphoreInfo(&resource_semaphore);
1086}
1087
1088/*
1089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1090% %
1091% %
1092% %
cristy3ed852e2009-09-05 21:47:34 +00001093% S e t M a g i c k R e s o u r c e L i m i t %
1094% %
1095% %
1096% %
1097%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098%
1099% SetMagickResourceLimit() sets the limit for a particular resource.
1100%
1101% The format of the SetMagickResourceLimit() method is:
1102%
1103% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1104% const MagickSizeType limit)
1105%
1106% A description of each parameter follows:
1107%
1108% o type: the type of resource.
1109%
1110% o limit: the maximum limit for the resource.
1111%
1112*/
cristy652316c2010-11-23 13:49:46 +00001113
cristy55a91cd2010-12-01 00:57:40 +00001114static inline MagickSizeType MagickMin(const MagickSizeType x,
1115 const MagickSizeType y)
cristy652316c2010-11-23 13:49:46 +00001116{
1117 if (x < y)
1118 return(x);
1119 return(y);
1120}
1121
cristy3ed852e2009-09-05 21:47:34 +00001122MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1123 const MagickSizeType limit)
1124{
cristy652316c2010-11-23 13:49:46 +00001125 char
1126 *value;
1127
cristy18b17442009-10-25 18:36:48 +00001128 if (resource_semaphore == (SemaphoreInfo *) NULL)
1129 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001130 LockSemaphoreInfo(resource_semaphore);
cristye2837ed2011-09-06 01:49:42 +00001131 value=(char *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00001132 switch (type)
1133 {
1134 case AreaResource:
1135 {
1136 resource_info.area_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001137 value=GetPolicyValue("area");
1138 if (value != (char *) NULL)
1139 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001140 break;
1141 }
1142 case MemoryResource:
1143 {
1144 resource_info.memory_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001145 value=GetPolicyValue("memory");
1146 if (value != (char *) NULL)
1147 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1148 100.0));
cristy3ed852e2009-09-05 21:47:34 +00001149 break;
1150 }
1151 case MapResource:
1152 {
1153 resource_info.map_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001154 value=GetPolicyValue("map");
1155 if (value != (char *) NULL)
1156 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001157 break;
1158 }
1159 case DiskResource:
1160 {
1161 resource_info.disk_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001162 value=GetPolicyValue("disk");
1163 if (value != (char *) NULL)
1164 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001165 break;
1166 }
1167 case FileResource:
1168 {
1169 resource_info.file_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001170 value=GetPolicyValue("file");
1171 if (value != (char *) NULL)
1172 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001173 break;
1174 }
1175 case ThreadResource:
1176 {
cristy01e36dc2010-10-21 17:26:42 +00001177 resource_info.thread_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001178 value=GetPolicyValue("thread");
1179 if (value != (char *) NULL)
1180 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1181 100.0));
cristyfeeb98d2012-05-09 16:32:12 +00001182 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1183 resource_info.thread_limit=GetOpenMPMaximumThreads();
cristy3ed852e2009-09-05 21:47:34 +00001184 break;
1185 }
cristy7fc1b852013-01-27 16:47:26 +00001186 case ThrottleResource:
1187 {
1188 resource_info.throttle_limit=limit;
1189 value=GetPolicyValue("throttle");
1190 if (value != (char *) NULL)
1191 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1192 100.0));
1193 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1194 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1195 break;
1196 }
cristy3ed852e2009-09-05 21:47:34 +00001197 case TimeResource:
1198 {
1199 resource_info.time_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001200 value=GetPolicyValue("time");
1201 if (value != (char *) NULL)
1202 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001203 break;
1204 }
1205 default:
1206 break;
1207 }
cristye2837ed2011-09-06 01:49:42 +00001208 if (value != (char *) NULL)
1209 value=DestroyString(value);
cristyf84a1932010-01-03 18:00:18 +00001210 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001211 return(MagickTrue);
1212}