blob: 176dfe81a59a15c265379502dd9ff8d8b150737b [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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,
79 time;
80
81 MagickSizeType
82 area_limit,
83 memory_limit,
84 map_limit,
85 disk_limit,
86 file_limit,
87 thread_limit,
88 time_limit;
89} ResourceInfo;
90
91/*
92 Global declarations.
93*/
94static RandomInfo
95 *random_info = (RandomInfo *) NULL;
96
97static ResourceInfo
98 resource_info =
99 {
100 MagickULLConstant(0),
101 MagickULLConstant(0),
102 MagickULLConstant(0),
103 MagickULLConstant(0),
104 MagickULLConstant(0),
105 MagickULLConstant(0),
106 MagickULLConstant(0),
cristy2b97bd22011-10-04 18:12:42 +0000107 MagickULLConstant(3072)*1024*1024,
cristy3ed852e2009-09-05 21:47:34 +0000108 MagickULLConstant(1536)*1024*1024,
cristy9bfdd582010-10-23 01:27:25 +0000109 MagickULLConstant(3072)*1024*1024,
cristy3ed852e2009-09-05 21:47:34 +0000110 MagickResourceInfinity,
111 MagickULLConstant(768),
cristyc6e273e2012-09-10 22:49:21 +0000112 MagickULLConstant(1),
cristy3ed852e2009-09-05 21:47:34 +0000113 MagickResourceInfinity
114 };
115
116static SemaphoreInfo
117 *resource_semaphore = (SemaphoreInfo *) NULL;
118
119static SplayTreeInfo
120 *temporary_resources = (SplayTreeInfo *) NULL;
121
122/*
123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124% %
125% %
126% %
127% A c q u i r e M a g i c k R e s o u r c e %
128% %
129% %
130% %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
133% AcquireMagickResource() acquires resources of the specified type.
134% MagickFalse is returned if the specified resource is exhausted otherwise
135% MagickTrue.
136%
137% The format of the AcquireMagickResource() method is:
138%
139% MagickBooleanType AcquireMagickResource(const ResourceType type,
140% const MagickSizeType size)
141%
142% A description of each parameter follows:
143%
144% o type: the type of resource.
145%
146% o size: the number of bytes needed from for this resource.
147%
148*/
149MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
150 const MagickSizeType size)
151{
152 char
153 resource_current[MaxTextExtent],
154 resource_limit[MaxTextExtent],
155 resource_request[MaxTextExtent];
156
157 MagickBooleanType
158 status;
159
160 MagickSizeType
161 limit;
162
163 status=MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000164 (void) FormatMagickSize(size,MagickFalse,resource_request);
cristy18b17442009-10-25 18:36:48 +0000165 if (resource_semaphore == (SemaphoreInfo *) NULL)
166 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000167 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000168 switch (type)
169 {
170 case AreaResource:
171 {
172 resource_info.area=(MagickOffsetType) size;
173 limit=resource_info.area_limit;
174 status=(resource_info.area_limit == MagickResourceInfinity) ||
175 (size < limit) ? MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000176 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000177 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000178 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
179 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000180 break;
181 }
182 case MemoryResource:
183 {
184 resource_info.memory+=size;
185 limit=resource_info.memory_limit;
186 status=(resource_info.memory_limit == MagickResourceInfinity) ||
187 ((MagickSizeType) resource_info.memory < limit) ?
188 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000189 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000190 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000191 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000192 resource_limit);
193 break;
194 }
195 case MapResource:
196 {
197 resource_info.map+=size;
198 limit=resource_info.map_limit;
199 status=(resource_info.map_limit == MagickResourceInfinity) ||
200 ((MagickSizeType) resource_info.map < limit) ?
201 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000202 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000203 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000204 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000205 resource_limit);
206 break;
207 }
208 case DiskResource:
209 {
210 resource_info.disk+=size;
211 limit=resource_info.disk_limit;
212 status=(resource_info.disk_limit == MagickResourceInfinity) ||
213 ((MagickSizeType) resource_info.disk < limit) ?
214 MagickTrue : MagickFalse;
cristy518d13d2011-01-04 15:25:24 +0000215 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000216 resource_current);
cristy518d13d2011-01-04 15:25:24 +0000217 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
cristyb9080c92009-12-01 20:13:26 +0000218 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000219 break;
220 }
221 case FileResource:
222 {
223 resource_info.file+=size;
224 limit=resource_info.file_limit;
225 status=(resource_info.file_limit == MagickResourceInfinity) ||
226 ((MagickSizeType) resource_info.file < limit) ?
227 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000228 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000229 resource_current);
230 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
cristyb9080c92009-12-01 20:13:26 +0000231 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000232 break;
233 }
234 case ThreadResource:
235 {
cristy3ed852e2009-09-05 21:47:34 +0000236 limit=resource_info.thread_limit;
237 status=(resource_info.thread_limit == MagickResourceInfinity) ||
238 ((MagickSizeType) resource_info.thread < limit) ?
239 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000240 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000241 resource_current);
242 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
cristyb9080c92009-12-01 20:13:26 +0000243 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000244 break;
245 }
246 case TimeResource:
247 {
248 resource_info.time+=size;
249 limit=resource_info.time_limit;
250 status=(resource_info.time_limit == MagickResourceInfinity) ||
251 ((MagickSizeType) resource_info.time < limit) ?
252 MagickTrue : MagickFalse;
cristyb9080c92009-12-01 20:13:26 +0000253 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000254 resource_current);
255 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
cristyb9080c92009-12-01 20:13:26 +0000256 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000257 break;
258 }
259 default:
260 break;
261 }
cristyf84a1932010-01-03 18:00:18 +0000262 UnlockSemaphoreInfo(resource_semaphore);
cristy9bfdd582010-10-23 01:27:25 +0000263 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
cristy042ee782011-04-22 18:48:30 +0000264 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
cristya21afde2010-07-02 00:45:40 +0000265 resource_request,resource_current,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000266 return(status);
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
cristycfffdac2010-09-30 03:05:09 +0000274+ 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 +0000275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
cristyf34a1452009-10-24 22:29:27 +0000280% AsynchronousResourceComponentTerminus() destroys the resource environment.
281% It differs from ResourceComponentTerminus() in that it can be called from a
cristy3ed852e2009-09-05 21:47:34 +0000282% asynchronous signal handler.
283%
cristyf34a1452009-10-24 22:29:27 +0000284% The format of the ResourceComponentTerminus() method is:
cristy3ed852e2009-09-05 21:47:34 +0000285%
cristyf34a1452009-10-24 22:29:27 +0000286% ResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000287%
288*/
cristy0a4d92f2011-08-31 19:25:00 +0000289MagickPrivate void AsynchronousResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000290{
291 const char
292 *path;
293
294 if (temporary_resources == (SplayTreeInfo *) NULL)
295 return;
296 /*
297 Remove any lingering temporary files.
298 */
299 ResetSplayTreeIterator(temporary_resources);
300 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
301 while (path != (const char *) NULL)
302 {
cristy18c6c272011-09-23 14:40:37 +0000303 (void) remove_utf8(path);
cristy3ed852e2009-09-05 21:47:34 +0000304 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
305 }
306}
307
308/*
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310% %
311% %
312% %
313% 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 %
314% %
315% %
316% %
317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318%
319% AcquireUniqueFileResource() returns a unique file name, and returns a file
320% descriptor for the file open for reading and writing.
321%
322% The format of the AcquireUniqueFileResource() method is:
323%
324% int AcquireUniqueFileResource(char *path)
325%
326% A description of each parameter follows:
327%
328% o path: Specifies a pointer to an array of characters. The unique path
329% name is returned in this array.
330%
331*/
332
333static void *DestroyTemporaryResources(void *temporary_resource)
334{
cristy18c6c272011-09-23 14:40:37 +0000335 (void) remove_utf8((char *) temporary_resource);
cristycfbec6a2010-09-28 18:27:51 +0000336 temporary_resource=DestroyString((char *) temporary_resource);
cristy3ed852e2009-09-05 21:47:34 +0000337 return((void *) NULL);
338}
339
340static MagickBooleanType GetPathTemplate(char *path)
341{
342 char
343 *directory;
344
345 ExceptionInfo
346 *exception;
347
348 MagickBooleanType
349 status;
350
351 register char
352 *p;
353
354 struct stat
355 attributes;
356
357 (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent);
358 exception=AcquireExceptionInfo();
359 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
360 exception);
361 exception=DestroyExceptionInfo(exception);
362 if (directory == (char *) NULL)
363 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
364 if (directory == (char *) NULL)
365 directory=GetEnvironmentValue("MAGICK_TMPDIR");
366 if (directory == (char *) NULL)
367 directory=GetPolicyValue("temporary-path");
368 if (directory == (char *) NULL)
369 directory=GetEnvironmentValue("TMPDIR");
cristy0157aea2010-04-24 21:12:18 +0000370#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
cristy3ed852e2009-09-05 21:47:34 +0000371 if (directory == (char *) NULL)
372 directory=GetEnvironmentValue("TMP");
373 if (directory == (char *) NULL)
374 directory=GetEnvironmentValue("TEMP");
375#endif
376#if defined(__VMS)
377 if (directory == (char *) NULL)
378 directory=GetEnvironmentValue("MTMPDIR");
379#endif
380#if defined(P_tmpdir)
381 if (directory == (char *) NULL)
382 directory=ConstantString(P_tmpdir);
383#endif
384 if (directory == (char *) NULL)
385 return(MagickTrue);
386 if (strlen(directory) > (MaxTextExtent-15))
387 {
388 directory=DestroyString(directory);
389 return(MagickTrue);
390 }
391 status=GetPathAttributes(directory,&attributes);
392 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
393 {
394 directory=DestroyString(directory);
395 return(MagickTrue);
396 }
397 if (directory[strlen(directory)-1] == *DirectorySeparator)
cristyb51dff52011-05-19 16:55:47 +0000398 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory);
cristy3ed852e2009-09-05 21:47:34 +0000399 else
cristyb51dff52011-05-19 16:55:47 +0000400 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-XXXXXXXX",
cristy3ed852e2009-09-05 21:47:34 +0000401 directory,DirectorySeparator);
402 directory=DestroyString(directory);
403 if (*DirectorySeparator != '/')
404 for (p=path; *p != '\0'; p++)
405 if (*p == *DirectorySeparator)
406 *p='/';
407 return(MagickTrue);
408}
409
410MagickExport int AcquireUniqueFileResource(char *path)
411{
412#if !defined(O_NOFOLLOW)
413#define O_NOFOLLOW 0
414#endif
415#if !defined(TMP_MAX)
416# define TMP_MAX 238328
417#endif
418
cristy3ed852e2009-09-05 21:47:34 +0000419 int
420 c,
421 file;
422
423 register char
424 *p;
425
cristybb503372010-05-27 20:51:26 +0000426 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000427 i;
428
429 static const char
430 portable_filename[65] =
431 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
432
433 StringInfo
434 *key;
435
436 unsigned char
437 *datum;
438
439 assert(path != (char *) NULL);
440 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
441 if (random_info == (RandomInfo *) NULL)
442 random_info=AcquireRandomInfo();
443 file=(-1);
cristycee97112010-05-28 00:44:52 +0000444 for (i=0; i < (ssize_t) TMP_MAX; i++)
cristy3ed852e2009-09-05 21:47:34 +0000445 {
446 /*
447 Get temporary pathname.
448 */
449 (void) GetPathTemplate(path);
cristy59ca45d2011-02-03 14:54:57 +0000450 key=GetRandomKey(random_info,2);
451 p=path+strlen(path)-8;
452 datum=GetStringInfoDatum(key);
453 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
454 {
455 c=(int) (datum[i] & 0x3f);
456 *p++=portable_filename[c];
457 }
458 key=DestroyStringInfo(key);
cristy3ed852e2009-09-05 21:47:34 +0000459#if defined(MAGICKCORE_HAVE_MKSTEMP)
460 file=mkstemp(path);
461#if defined(__OS2__)
462 setmode(file,O_BINARY);
463#endif
464 if (file != -1)
465 break;
466#endif
cristy59ca45d2011-02-03 14:54:57 +0000467 key=GetRandomKey(random_info,6);
468 p=path+strlen(path)-6;
cristy3ed852e2009-09-05 21:47:34 +0000469 datum=GetStringInfoDatum(key);
cristy59ca45d2011-02-03 14:54:57 +0000470 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
cristy3ed852e2009-09-05 21:47:34 +0000471 {
472 c=(int) (datum[i] & 0x3f);
473 *p++=portable_filename[c];
474 }
475 key=DestroyStringInfo(key);
cristy18c6c272011-09-23 14:40:37 +0000476 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE);
cristy59ca45d2011-02-03 14:54:57 +0000477 if ((file >= 0) || (errno != EEXIST))
cristy3ed852e2009-09-05 21:47:34 +0000478 break;
479 }
480 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
481 if (file == -1)
482 return(file);
cristy18b17442009-10-25 18:36:48 +0000483 if (resource_semaphore == (SemaphoreInfo *) NULL)
484 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000485 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000486 if (temporary_resources == (SplayTreeInfo *) NULL)
487 temporary_resources=NewSplayTree(CompareSplayTreeString,
cristyf77fa462010-09-28 18:35:53 +0000488 DestroyTemporaryResources,(void *(*)(void *)) NULL);
cristyf84a1932010-01-03 18:00:18 +0000489 UnlockSemaphoreInfo(resource_semaphore);
cristycfbec6a2010-09-28 18:27:51 +0000490 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
cristyf77fa462010-09-28 18:35:53 +0000491 (const void *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000492 return(file);
493}
494
495/*
496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497% %
498% %
499% %
cristy3ed852e2009-09-05 21:47:34 +0000500% G e t M a g i c k R e s o u r c e %
501% %
502% %
503% %
504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505%
506% GetMagickResource() returns the specified resource.
507%
508% The format of the GetMagickResource() method is:
509%
510% MagickSizeType GetMagickResource(const ResourceType type)
511%
512% A description of each parameter follows:
513%
514% o type: the type of resource.
515%
516*/
517MagickExport MagickSizeType GetMagickResource(const ResourceType type)
518{
519 MagickSizeType
520 resource;
521
522 resource=0;
cristyf84a1932010-01-03 18:00:18 +0000523 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000524 switch (type)
525 {
526 case AreaResource:
527 {
528 resource=(MagickSizeType) resource_info.area;
529 break;
530 }
531 case MemoryResource:
532 {
533 resource=(MagickSizeType) resource_info.memory;
534 break;
535 }
536 case MapResource:
537 {
538 resource=(MagickSizeType) resource_info.map;
539 break;
540 }
541 case DiskResource:
542 {
543 resource=(MagickSizeType) resource_info.disk;
544 break;
545 }
546 case FileResource:
547 {
548 resource=(MagickSizeType) resource_info.file;
549 break;
550 }
551 case ThreadResource:
552 {
553 resource=(MagickSizeType) resource_info.thread;
554 break;
555 }
556 case TimeResource:
557 {
558 resource=(MagickSizeType) resource_info.time;
559 break;
560 }
561 default:
562 break;
563 }
cristyf84a1932010-01-03 18:00:18 +0000564 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000565 return(resource);
566}
567
568/*
569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570% %
571% %
572% %
573% G e t M a g i c k R e s o u r c e L i m i t %
574% %
575% %
576% %
577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578%
cristy7a40ba82011-01-08 20:31:18 +0000579% GetMagickResourceLimit() returns the specified resource limit.
cristy3ed852e2009-09-05 21:47:34 +0000580%
581% The format of the GetMagickResourceLimit() method is:
582%
cristy50a10922010-02-15 18:35:25 +0000583% MagickSizeType GetMagickResourceLimit(const ResourceType type)
cristy3ed852e2009-09-05 21:47:34 +0000584%
585% A description of each parameter follows:
586%
587% o type: the type of resource.
588%
589*/
590MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
591{
592 MagickSizeType
593 resource;
594
595 resource=0;
cristy18b17442009-10-25 18:36:48 +0000596 if (resource_semaphore == (SemaphoreInfo *) NULL)
597 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000598 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000599 switch (type)
600 {
601 case AreaResource:
602 {
603 resource=resource_info.area_limit;
604 break;
605 }
606 case MemoryResource:
607 {
608 resource=resource_info.memory_limit;
609 break;
610 }
611 case MapResource:
612 {
613 resource=resource_info.map_limit;
614 break;
615 }
616 case DiskResource:
617 {
618 resource=resource_info.disk_limit;
619 break;
620 }
621 case FileResource:
622 {
623 resource=resource_info.file_limit;
624 break;
625 }
626 case ThreadResource:
627 {
628 resource=resource_info.thread_limit;
629 break;
630 }
631 case TimeResource:
632 {
633 resource=resource_info.time_limit;
634 break;
635 }
636 default:
637 break;
638 }
cristyf84a1932010-01-03 18:00:18 +0000639 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000640 return(resource);
641}
642
643/*
644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645% %
646% %
647% %
cristy3ed852e2009-09-05 21:47:34 +0000648% L i s t M a g i c k R e s o u r c e I n f o %
649% %
650% %
651% %
652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653%
654% ListMagickResourceInfo() lists the resource info to a file.
655%
656% The format of the ListMagickResourceInfo method is:
657%
658% MagickBooleanType ListMagickResourceInfo(FILE *file,
659% ExceptionInfo *exception)
660%
661% A description of each parameter follows.
662%
663% o file: An pointer to a FILE.
664%
665% o exception: return any errors or warnings in this structure.
666%
667*/
668MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
669 ExceptionInfo *magick_unused(exception))
670{
671 char
672 area_limit[MaxTextExtent],
673 disk_limit[MaxTextExtent],
674 map_limit[MaxTextExtent],
675 memory_limit[MaxTextExtent],
676 time_limit[MaxTextExtent];
677
678 if (file == (const FILE *) NULL)
679 file=stdout;
cristy18b17442009-10-25 18:36:48 +0000680 if (resource_semaphore == (SemaphoreInfo *) NULL)
681 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000682 LockSemaphoreInfo(resource_semaphore);
cristyb9080c92009-12-01 20:13:26 +0000683 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
684 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
685 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
cristy9bfdd582010-10-23 01:27:25 +0000686 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
687 if (resource_info.disk_limit != MagickResourceInfinity)
cristy518d13d2011-01-04 15:25:24 +0000688 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
cristy3ed852e2009-09-05 21:47:34 +0000689 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
690 if (resource_info.time_limit != MagickResourceInfinity)
cristyb51dff52011-05-19 16:55:47 +0000691 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
cristy54ea5732011-06-10 12:39:53 +0000692 ((MagickOffsetType) resource_info.time_limit));
cristyb51dff52011-05-19 16:55:47 +0000693 (void) FormatLocaleFile(file,"File Area Memory Map"
cristyf0bfc582009-12-05 15:09:34 +0000694 " Disk Thread Time\n");
cristy1e604812011-05-19 18:07:50 +0000695 (void) FormatLocaleFile(file,
696 "--------------------------------------------------------"
cristyb9080c92009-12-01 20:13:26 +0000697 "-----------------------\n");
cristy1e604812011-05-19 18:07:50 +0000698 (void) FormatLocaleFile(file,"%4g %10s %10s %10s %10s %6g %11s\n",
cristy54ea5732011-06-10 12:39:53 +0000699 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
700 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
701 resource_info.thread_limit),time_limit);
cristy3ed852e2009-09-05 21:47:34 +0000702 (void) fflush(file);
cristyf84a1932010-01-03 18:00:18 +0000703 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000704 return(MagickTrue);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
712% R e l i n q u i s h M a g i c k R e s o u r c e %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% RelinquishMagickResource() relinquishes resources of the specified type.
719%
720% The format of the RelinquishMagickResource() method is:
721%
722% void RelinquishMagickResource(const ResourceType type,
723% const MagickSizeType size)
724%
725% A description of each parameter follows:
726%
727% o type: the type of resource.
728%
729% o size: the size of the resource.
730%
731*/
732MagickExport void RelinquishMagickResource(const ResourceType type,
733 const MagickSizeType size)
734{
735 char
736 resource_current[MaxTextExtent],
737 resource_limit[MaxTextExtent],
738 resource_request[MaxTextExtent];
739
cristyb9080c92009-12-01 20:13:26 +0000740 (void) FormatMagickSize(size,MagickFalse,resource_request);
cristy18b17442009-10-25 18:36:48 +0000741 if (resource_semaphore == (SemaphoreInfo *) NULL)
742 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000743 LockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000744 switch (type)
745 {
746 case AreaResource:
747 {
748 resource_info.area=(MagickOffsetType) size;
cristyb9080c92009-12-01 20:13:26 +0000749 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000750 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000751 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
752 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000753 break;
754 }
755 case MemoryResource:
756 {
757 resource_info.memory-=size;
758 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
cristyb9080c92009-12-01 20:13:26 +0000759 MagickTrue,resource_current);
760 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
761 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000762 break;
763 }
764 case MapResource:
765 {
766 resource_info.map-=size;
cristyb9080c92009-12-01 20:13:26 +0000767 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000768 resource_current);
cristyb9080c92009-12-01 20:13:26 +0000769 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
770 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000771 break;
772 }
773 case DiskResource:
774 {
775 resource_info.disk-=size;
cristy518d13d2011-01-04 15:25:24 +0000776 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
cristy3ed852e2009-09-05 21:47:34 +0000777 resource_current);
cristy518d13d2011-01-04 15:25:24 +0000778 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
cristyb9080c92009-12-01 20:13:26 +0000779 resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000780 break;
781 }
782 case FileResource:
783 {
784 resource_info.file-=size;
cristyb9080c92009-12-01 20:13:26 +0000785 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000786 resource_current);
787 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
cristyb9080c92009-12-01 20:13:26 +0000788 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000789 break;
790 }
791 case ThreadResource:
792 {
cristyb9080c92009-12-01 20:13:26 +0000793 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000794 resource_current);
795 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
cristyb9080c92009-12-01 20:13:26 +0000796 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000797 break;
798 }
799 case TimeResource:
800 {
801 resource_info.time-=size;
cristyb9080c92009-12-01 20:13:26 +0000802 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
cristy3ed852e2009-09-05 21:47:34 +0000803 resource_current);
804 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
cristyb9080c92009-12-01 20:13:26 +0000805 MagickFalse,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000806 break;
807 }
808 default:
809 break;
810 }
cristyf84a1932010-01-03 18:00:18 +0000811 UnlockSemaphoreInfo(resource_semaphore);
cristy9bfdd582010-10-23 01:27:25 +0000812 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
cristy042ee782011-04-22 18:48:30 +0000813 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
cristya21afde2010-07-02 00:45:40 +0000814 resource_request,resource_current,resource_limit);
cristy3ed852e2009-09-05 21:47:34 +0000815}
816
817/*
818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819% %
820% %
821% %
822% 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 %
823% %
824% %
825% %
826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827%
828% RelinquishUniqueFileResource() relinquishes a unique file resource.
829%
830% The format of the RelinquishUniqueFileResource() method is:
831%
832% MagickBooleanType RelinquishUniqueFileResource(const char *path)
833%
834% A description of each parameter follows:
835%
836% o name: the name of the temporary resource.
837%
838*/
839MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
840{
841 char
842 cache_path[MaxTextExtent];
843
844 assert(path != (const char *) NULL);
845 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
846 if (temporary_resources != (SplayTreeInfo *) NULL)
847 {
848 register char
849 *p;
850
851 ResetSplayTreeIterator(temporary_resources);
852 p=(char *) GetNextKeyInSplayTree(temporary_resources);
853 while (p != (char *) NULL)
854 {
855 if (LocaleCompare(p,path) == 0)
856 break;
857 p=(char *) GetNextKeyInSplayTree(temporary_resources);
858 }
859 if (p != (char *) NULL)
860 (void) DeleteNodeFromSplayTree(temporary_resources,p);
861 }
862 (void) CopyMagickString(cache_path,path,MaxTextExtent);
863 AppendImageFormat("cache",cache_path);
cristy18c6c272011-09-23 14:40:37 +0000864 (void) remove_utf8(cache_path);
865 return(remove_utf8(path) == 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000866}
867
868/*
869%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870% %
871% %
872% %
cristyf34a1452009-10-24 22:29:27 +0000873+ R e s o u r c e C o m p o n e n t G e n e s i s %
874% %
875% %
876% %
877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878%
879% ResourceComponentGenesis() instantiates the resource component.
880%
881% The format of the ResourceComponentGenesis method is:
882%
883% MagickBooleanType ResourceComponentGenesis(void)
884%
885*/
886
cristy652316c2010-11-23 13:49:46 +0000887static inline size_t MagickMax(const size_t x,const size_t y)
cristyf34a1452009-10-24 22:29:27 +0000888{
889 if (x > y)
890 return(x);
891 return(y);
892}
893
894static inline MagickSizeType StringToSizeType(const char *string,
895 const double interval)
896{
897 double
898 value;
899
cristy9b34e302011-11-05 02:15:45 +0000900 value=SiPrefixToDoubleInterval(string,interval);
cristyf34a1452009-10-24 22:29:27 +0000901 if (value >= (double) MagickULLConstant(~0))
902 return(MagickULLConstant(~0));
903 return((MagickSizeType) value);
904}
905
cristy5ff4eaf2011-09-03 01:38:02 +0000906MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000907{
908 char
909 *limit;
910
cristy9d314ff2011-03-09 01:30:28 +0000911 MagickSizeType
912 memory;
913
cristybb503372010-05-27 20:51:26 +0000914 ssize_t
cristyf34a1452009-10-24 22:29:27 +0000915 files,
916 pages,
917 pagesize;
918
cristyf34a1452009-10-24 22:29:27 +0000919 /*
920 Set Magick resource limits.
921 */
cristy165b6092009-10-26 13:52:10 +0000922 AcquireSemaphoreInfo(&resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000923 pagesize=GetMagickPageSize();
924 pages=(-1);
925#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
cristycee97112010-05-28 00:44:52 +0000926 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
cristyf34a1452009-10-24 22:29:27 +0000927#endif
928 memory=(MagickSizeType) pages*pagesize;
929 if ((pagesize <= 0) || (pages <= 0))
930 memory=2048UL*1024UL*1024UL;
931#if defined(PixelCacheThreshold)
932 memory=PixelCacheThreshold;
933#endif
cristy2b97bd22011-10-04 18:12:42 +0000934 (void) SetMagickResourceLimit(AreaResource,2*memory);
cristyb0a27eb2010-10-23 23:34:32 +0000935 (void) SetMagickResourceLimit(MemoryResource,memory);
936 (void) SetMagickResourceLimit(MapResource,2*memory);
cristyf34a1452009-10-24 22:29:27 +0000937 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
938 if (limit == (char *) NULL)
939 limit=GetPolicyValue("area");
940 if (limit != (char *) NULL)
941 {
942 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
943 limit=DestroyString(limit);
944 }
945 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
946 if (limit == (char *) NULL)
947 limit=GetPolicyValue("memory");
948 if (limit != (char *) NULL)
949 {
950 (void) SetMagickResourceLimit(MemoryResource,
951 StringToSizeType(limit,100.0));
952 limit=DestroyString(limit);
953 }
954 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
955 if (limit == (char *) NULL)
956 limit=GetPolicyValue("map");
957 if (limit != (char *) NULL)
958 {
959 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
960 limit=DestroyString(limit);
961 }
962 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
963 if (limit == (char *) NULL)
964 limit=GetPolicyValue("disk");
965 if (limit != (char *) NULL)
966 {
967 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
968 limit=DestroyString(limit);
969 }
970 files=(-1);
971#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
cristycee97112010-05-28 00:44:52 +0000972 files=(ssize_t) sysconf(_SC_OPEN_MAX);
cristyf34a1452009-10-24 22:29:27 +0000973#endif
974#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
975 if (files < 0)
976 {
977 struct rlimit
978 resources;
979
980 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
cristybb503372010-05-27 20:51:26 +0000981 files=(ssize_t) resources.rlim_cur;
cristyf34a1452009-10-24 22:29:27 +0000982 }
983#endif
984#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
985 if (files < 0)
cristy6d0ee3e2010-09-28 18:36:50 +0000986 files=(ssize_t) getdtablesize();
cristyf34a1452009-10-24 22:29:27 +0000987#endif
988 if (files < 0)
989 files=64;
cristybb503372010-05-27 20:51:26 +0000990 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
cristyddacdd12012-05-07 23:08:14 +0000991 (3*files/4),64));
cristyf34a1452009-10-24 22:29:27 +0000992 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
993 if (limit == (char *) NULL)
994 limit=GetPolicyValue("file");
995 if (limit != (char *) NULL)
996 {
cristycfce4c92011-12-11 17:28:48 +0000997 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
998 100.0));
cristyf34a1452009-10-24 22:29:27 +0000999 limit=DestroyString(limit);
1000 }
1001 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1002 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1003 if (limit == (char *) NULL)
1004 limit=GetPolicyValue("thread");
1005 if (limit != (char *) NULL)
1006 {
cristyf34a1452009-10-24 22:29:27 +00001007 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1008 100.0));
1009 limit=DestroyString(limit);
1010 }
1011 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1012 if (limit == (char *) NULL)
1013 limit=GetPolicyValue("time");
1014 if (limit != (char *) NULL)
1015 {
1016 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1017 limit=DestroyString(limit);
1018 }
1019 return(MagickTrue);
1020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024% %
1025% %
1026% %
1027+ 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 %
1028% %
1029% %
1030% %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033% ResourceComponentTerminus() destroys the resource component.
1034%
1035% The format of the ResourceComponentTerminus() method is:
1036%
1037% ResourceComponentTerminus(void)
1038%
1039*/
cristy5ff4eaf2011-09-03 01:38:02 +00001040MagickPrivate void ResourceComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001041{
cristy18b17442009-10-25 18:36:48 +00001042 if (resource_semaphore == (SemaphoreInfo *) NULL)
1043 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001044 LockSemaphoreInfo(resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001045 if (temporary_resources != (SplayTreeInfo *) NULL)
1046 temporary_resources=DestroySplayTree(temporary_resources);
1047 if (random_info != (RandomInfo *) NULL)
1048 random_info=DestroyRandomInfo(random_info);
cristyf84a1932010-01-03 18:00:18 +00001049 UnlockSemaphoreInfo(resource_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001050 DestroySemaphoreInfo(&resource_semaphore);
1051}
1052
1053/*
1054%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1055% %
1056% %
1057% %
cristy3ed852e2009-09-05 21:47:34 +00001058% S e t M a g i c k R e s o u r c e L i m i t %
1059% %
1060% %
1061% %
1062%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063%
1064% SetMagickResourceLimit() sets the limit for a particular resource.
1065%
1066% The format of the SetMagickResourceLimit() method is:
1067%
1068% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1069% const MagickSizeType limit)
1070%
1071% A description of each parameter follows:
1072%
1073% o type: the type of resource.
1074%
1075% o limit: the maximum limit for the resource.
1076%
1077*/
cristy652316c2010-11-23 13:49:46 +00001078
cristy55a91cd2010-12-01 00:57:40 +00001079static inline MagickSizeType MagickMin(const MagickSizeType x,
1080 const MagickSizeType y)
cristy652316c2010-11-23 13:49:46 +00001081{
1082 if (x < y)
1083 return(x);
1084 return(y);
1085}
1086
cristy3ed852e2009-09-05 21:47:34 +00001087MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1088 const MagickSizeType limit)
1089{
cristy652316c2010-11-23 13:49:46 +00001090 char
1091 *value;
1092
cristy18b17442009-10-25 18:36:48 +00001093 if (resource_semaphore == (SemaphoreInfo *) NULL)
1094 AcquireSemaphoreInfo(&resource_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001095 LockSemaphoreInfo(resource_semaphore);
cristye2837ed2011-09-06 01:49:42 +00001096 value=(char *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00001097 switch (type)
1098 {
1099 case AreaResource:
1100 {
1101 resource_info.area_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001102 value=GetPolicyValue("area");
1103 if (value != (char *) NULL)
1104 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001105 break;
1106 }
1107 case MemoryResource:
1108 {
1109 resource_info.memory_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001110 value=GetPolicyValue("memory");
1111 if (value != (char *) NULL)
1112 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1113 100.0));
cristy3ed852e2009-09-05 21:47:34 +00001114 break;
1115 }
1116 case MapResource:
1117 {
1118 resource_info.map_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001119 value=GetPolicyValue("map");
1120 if (value != (char *) NULL)
1121 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001122 break;
1123 }
1124 case DiskResource:
1125 {
1126 resource_info.disk_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001127 value=GetPolicyValue("disk");
1128 if (value != (char *) NULL)
1129 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001130 break;
1131 }
1132 case FileResource:
1133 {
1134 resource_info.file_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001135 value=GetPolicyValue("file");
1136 if (value != (char *) NULL)
1137 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001138 break;
1139 }
1140 case ThreadResource:
1141 {
cristy01e36dc2010-10-21 17:26:42 +00001142 resource_info.thread_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001143 value=GetPolicyValue("thread");
1144 if (value != (char *) NULL)
1145 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1146 100.0));
cristyfeeb98d2012-05-09 16:32:12 +00001147 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1148 resource_info.thread_limit=GetOpenMPMaximumThreads();
cristy3ed852e2009-09-05 21:47:34 +00001149 break;
1150 }
1151 case TimeResource:
1152 {
1153 resource_info.time_limit=limit;
cristy652316c2010-11-23 13:49:46 +00001154 value=GetPolicyValue("time");
1155 if (value != (char *) NULL)
1156 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
cristy3ed852e2009-09-05 21:47:34 +00001157 break;
1158 }
1159 default:
1160 break;
1161 }
cristye2837ed2011-09-06 01:49:42 +00001162 if (value != (char *) NULL)
1163 value=DestroyString(value);
cristyf84a1932010-01-03 18:00:18 +00001164 UnlockSemaphoreInfo(resource_semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001165 return(MagickTrue);
1166}