blob: 727283d947edf26a9668fe5f06d34f1a7a9df1a6 [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% %
20% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
21% 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*/
42#include "magick/studio.h"
43#include "magick/cache.h"
44#include "magick/configure.h"
45#include "magick/exception.h"
46#include "magick/exception-private.h"
47#include "magick/hashmap.h"
48#include "magick/log.h"
49#include "magick/image.h"
50#include "magick/memory_.h"
51#include "magick/option.h"
52#include "magick/policy.h"
53#include "magick/random_.h"
54#include "magick/registry.h"
55#include "magick/resource_.h"
56#include "magick/semaphore.h"
57#include "magick/signature-private.h"
58#include "magick/string_.h"
59#include "magick/splay-tree.h"
60#include "magick/thread-private.h"
61#include "magick/token.h"
62#include "magick/utility.h"
63
64/*
65 Typedef declarations.
66*/
67typedef struct _ResourceInfo
68{
69 MagickOffsetType
70 area,
71 memory,
72 map,
73 disk,
74 file,
75 thread,
76 time;
77
78 MagickSizeType
79 area_limit,
80 memory_limit,
81 map_limit,
82 disk_limit,
83 file_limit,
84 thread_limit,
85 time_limit;
86} ResourceInfo;
87
88/*
89 Global declarations.
90*/
91static RandomInfo
92 *random_info = (RandomInfo *) NULL;
93
94static ResourceInfo
95 resource_info =
96 {
97 MagickULLConstant(0),
98 MagickULLConstant(0),
99 MagickULLConstant(0),
100 MagickULLConstant(0),
101 MagickULLConstant(0),
102 MagickULLConstant(0),
103 MagickULLConstant(0),
104 MagickULLConstant(2048)*1024*1024,
105 MagickULLConstant(1536)*1024*1024,
106 MagickULLConstant(8192)*1024*1024,
107 MagickResourceInfinity,
108 MagickULLConstant(768),
109 MagickULLConstant(8),
110 MagickResourceInfinity
111 };
112
113static SemaphoreInfo
114 *resource_semaphore = (SemaphoreInfo *) NULL;
115
116static SplayTreeInfo
117 *temporary_resources = (SplayTreeInfo *) NULL;
118
119/*
120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121% %
122% %
123% %
124% A c q u i r e M a g i c k R e s o u r c e %
125% %
126% %
127% %
128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129%
130% AcquireMagickResource() acquires resources of the specified type.
131% MagickFalse is returned if the specified resource is exhausted otherwise
132% MagickTrue.
133%
134% The format of the AcquireMagickResource() method is:
135%
136% MagickBooleanType AcquireMagickResource(const ResourceType type,
137% const MagickSizeType size)
138%
139% A description of each parameter follows:
140%
141% o type: the type of resource.
142%
143% o size: the number of bytes needed from for this resource.
144%
145*/
146MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
147 const MagickSizeType size)
148{
149 char
150 resource_current[MaxTextExtent],
151 resource_limit[MaxTextExtent],
152 resource_request[MaxTextExtent];
153
154 MagickBooleanType
155 status;
156
157 MagickSizeType
158 limit;
159
160 status=MagickFalse;
161 (void) FormatMagickSize(size,resource_request);
162 AcquireSemaphoreInfo(&resource_semaphore);
163 switch (type)
164 {
165 case AreaResource:
166 {
167 resource_info.area=(MagickOffsetType) size;
168 limit=resource_info.area_limit;
169 status=(resource_info.area_limit == MagickResourceInfinity) ||
170 (size < limit) ? MagickTrue : MagickFalse;
171 (void) FormatMagickSize((MagickSizeType) resource_info.area,
172 resource_current);
173 (void) FormatMagickSize(resource_info.area_limit,resource_limit);
174 break;
175 }
176 case MemoryResource:
177 {
178 resource_info.memory+=size;
179 limit=resource_info.memory_limit;
180 status=(resource_info.memory_limit == MagickResourceInfinity) ||
181 ((MagickSizeType) resource_info.memory < limit) ?
182 MagickTrue : MagickFalse;
183 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
184 resource_current);
185 (void) FormatMagickSize(resource_info.memory_limit,
186 resource_limit);
187 break;
188 }
189 case MapResource:
190 {
191 resource_info.map+=size;
192 limit=resource_info.map_limit;
193 status=(resource_info.map_limit == MagickResourceInfinity) ||
194 ((MagickSizeType) resource_info.map < limit) ?
195 MagickTrue : MagickFalse;
196 (void) FormatMagickSize((MagickSizeType) resource_info.map,
197 resource_current);
198 (void) FormatMagickSize(resource_info.map_limit,
199 resource_limit);
200 break;
201 }
202 case DiskResource:
203 {
204 resource_info.disk+=size;
205 limit=resource_info.disk_limit;
206 status=(resource_info.disk_limit == MagickResourceInfinity) ||
207 ((MagickSizeType) resource_info.disk < limit) ?
208 MagickTrue : MagickFalse;
209 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
210 resource_current);
211 (void) FormatMagickSize(resource_info.disk_limit,resource_limit);
212 break;
213 }
214 case FileResource:
215 {
216 resource_info.file+=size;
217 limit=resource_info.file_limit;
218 status=(resource_info.file_limit == MagickResourceInfinity) ||
219 ((MagickSizeType) resource_info.file < limit) ?
220 MagickTrue : MagickFalse;
221 (void) FormatMagickSize((MagickSizeType) resource_info.file,
222 resource_current);
223 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
224 resource_limit);
225 break;
226 }
227 case ThreadResource:
228 {
229 resource_info.thread+=size;
230 limit=resource_info.thread_limit;
231 status=(resource_info.thread_limit == MagickResourceInfinity) ||
232 ((MagickSizeType) resource_info.thread < limit) ?
233 MagickTrue : MagickFalse;
234 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
235 resource_current);
236 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
237 resource_limit);
238 break;
239 }
240 case TimeResource:
241 {
242 resource_info.time+=size;
243 limit=resource_info.time_limit;
244 status=(resource_info.time_limit == MagickResourceInfinity) ||
245 ((MagickSizeType) resource_info.time < limit) ?
246 MagickTrue : MagickFalse;
247 (void) FormatMagickSize((MagickSizeType) resource_info.time,
248 resource_current);
249 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
250 resource_limit);
251 break;
252 }
253 default:
254 break;
255 }
256 RelinquishSemaphoreInfo(resource_semaphore);
257 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
258 MagickOptionToMnemonic(MagickResourceOptions,(long) type),resource_request,
259 resource_current,resource_limit);
260 return(status);
261}
262
263/*
264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265% %
266% %
267% %
cristyf34a1452009-10-24 22:29:27 +0000268+ 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 +0000269% %
270% %
271% %
272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273%
cristyf34a1452009-10-24 22:29:27 +0000274% AsynchronousResourceComponentTerminus() destroys the resource environment.
275% It differs from ResourceComponentTerminus() in that it can be called from a
cristy3ed852e2009-09-05 21:47:34 +0000276% asynchronous signal handler.
277%
cristyf34a1452009-10-24 22:29:27 +0000278% The format of the ResourceComponentTerminus() method is:
cristy3ed852e2009-09-05 21:47:34 +0000279%
cristyf34a1452009-10-24 22:29:27 +0000280% ResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000281%
282*/
cristyf34a1452009-10-24 22:29:27 +0000283MagickExport void AsynchronousResourceComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000284{
285 const char
286 *path;
287
288 if (temporary_resources == (SplayTreeInfo *) NULL)
289 return;
290 /*
291 Remove any lingering temporary files.
292 */
293 ResetSplayTreeIterator(temporary_resources);
294 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
295 while (path != (const char *) NULL)
296 {
297 (void) remove(path);
298 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
299 }
300}
301
302/*
303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304% %
305% %
306% %
307% 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 %
308% %
309% %
310% %
311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312%
313% AcquireUniqueFileResource() returns a unique file name, and returns a file
314% descriptor for the file open for reading and writing.
315%
316% The format of the AcquireUniqueFileResource() method is:
317%
318% int AcquireUniqueFileResource(char *path)
319%
320% A description of each parameter follows:
321%
322% o path: Specifies a pointer to an array of characters. The unique path
323% name is returned in this array.
324%
325*/
326
327static void *DestroyTemporaryResources(void *temporary_resource)
328{
329 (void) remove((char *) temporary_resource);
330 return((void *) NULL);
331}
332
333static MagickBooleanType GetPathTemplate(char *path)
334{
335 char
336 *directory;
337
338 ExceptionInfo
339 *exception;
340
341 MagickBooleanType
342 status;
343
344 register char
345 *p;
346
347 struct stat
348 attributes;
349
350 (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent);
351 exception=AcquireExceptionInfo();
352 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
353 exception);
354 exception=DestroyExceptionInfo(exception);
355 if (directory == (char *) NULL)
356 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
357 if (directory == (char *) NULL)
358 directory=GetEnvironmentValue("MAGICK_TMPDIR");
359 if (directory == (char *) NULL)
360 directory=GetPolicyValue("temporary-path");
361 if (directory == (char *) NULL)
362 directory=GetEnvironmentValue("TMPDIR");
363#if defined(__WINDOWS__) || defined(__OS2__)
364 if (directory == (char *) NULL)
365 directory=GetEnvironmentValue("TMP");
366 if (directory == (char *) NULL)
367 directory=GetEnvironmentValue("TEMP");
368#endif
369#if defined(__VMS)
370 if (directory == (char *) NULL)
371 directory=GetEnvironmentValue("MTMPDIR");
372#endif
373#if defined(P_tmpdir)
374 if (directory == (char *) NULL)
375 directory=ConstantString(P_tmpdir);
376#endif
377 if (directory == (char *) NULL)
378 return(MagickTrue);
379 if (strlen(directory) > (MaxTextExtent-15))
380 {
381 directory=DestroyString(directory);
382 return(MagickTrue);
383 }
384 status=GetPathAttributes(directory,&attributes);
385 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
386 {
387 directory=DestroyString(directory);
388 return(MagickTrue);
389 }
390 if (directory[strlen(directory)-1] == *DirectorySeparator)
391 (void) FormatMagickString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory);
392 else
393 (void) FormatMagickString(path,MaxTextExtent,"%s%smagick-XXXXXXXX",
394 directory,DirectorySeparator);
395 directory=DestroyString(directory);
396 if (*DirectorySeparator != '/')
397 for (p=path; *p != '\0'; p++)
398 if (*p == *DirectorySeparator)
399 *p='/';
400 return(MagickTrue);
401}
402
403MagickExport int AcquireUniqueFileResource(char *path)
404{
405#if !defined(O_NOFOLLOW)
406#define O_NOFOLLOW 0
407#endif
408#if !defined(TMP_MAX)
409# define TMP_MAX 238328
410#endif
411
412 char
413 *resource;
414
415 int
416 c,
417 file;
418
419 register char
420 *p;
421
422 register long
423 i;
424
425 static const char
426 portable_filename[65] =
427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
428
429 StringInfo
430 *key;
431
432 unsigned char
433 *datum;
434
435 assert(path != (char *) NULL);
436 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
437 if (random_info == (RandomInfo *) NULL)
438 random_info=AcquireRandomInfo();
439 file=(-1);
440 for (i=0; i < TMP_MAX; i++)
441 {
442 /*
443 Get temporary pathname.
444 */
445 (void) GetPathTemplate(path);
446#if defined(MAGICKCORE_HAVE_MKSTEMP)
447 file=mkstemp(path);
448#if defined(__OS2__)
449 setmode(file,O_BINARY);
450#endif
451 if (file != -1)
452 break;
453#endif
454 key=GetRandomKey(random_info,8);
455 p=path+strlen(path)-8;
456 datum=GetStringInfoDatum(key);
457 for (i=0; i < 8; i++)
458 {
459 c=(int) (datum[i] & 0x3f);
460 *p++=portable_filename[c];
461 }
462 key=DestroyStringInfo(key);
463 file=open(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE);
464 if ((file > 0) || (errno != EEXIST))
465 break;
466 }
467 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
468 if (file == -1)
469 return(file);
470 AcquireSemaphoreInfo(&resource_semaphore);
471 if (temporary_resources == (SplayTreeInfo *) NULL)
472 temporary_resources=NewSplayTree(CompareSplayTreeString,
473 RelinquishMagickMemory,DestroyTemporaryResources);
474 RelinquishSemaphoreInfo(resource_semaphore);
475 resource=ConstantString(path);
476 (void) AddValueToSplayTree(temporary_resources,resource,resource);
477 return(file);
478}
479
480/*
481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482% %
483% %
484% %
cristy3ed852e2009-09-05 21:47:34 +0000485% G e t M a g i c k R e s o u r c e %
486% %
487% %
488% %
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%
491% GetMagickResource() returns the specified resource.
492%
493% The format of the GetMagickResource() method is:
494%
495% MagickSizeType GetMagickResource(const ResourceType type)
496%
497% A description of each parameter follows:
498%
499% o type: the type of resource.
500%
501*/
502MagickExport MagickSizeType GetMagickResource(const ResourceType type)
503{
504 MagickSizeType
505 resource;
506
507 resource=0;
508 AcquireSemaphoreInfo(&resource_semaphore);
509 switch (type)
510 {
511 case AreaResource:
512 {
513 resource=(MagickSizeType) resource_info.area;
514 break;
515 }
516 case MemoryResource:
517 {
518 resource=(MagickSizeType) resource_info.memory;
519 break;
520 }
521 case MapResource:
522 {
523 resource=(MagickSizeType) resource_info.map;
524 break;
525 }
526 case DiskResource:
527 {
528 resource=(MagickSizeType) resource_info.disk;
529 break;
530 }
531 case FileResource:
532 {
533 resource=(MagickSizeType) resource_info.file;
534 break;
535 }
536 case ThreadResource:
537 {
538 resource=(MagickSizeType) resource_info.thread;
539 break;
540 }
541 case TimeResource:
542 {
543 resource=(MagickSizeType) resource_info.time;
544 break;
545 }
546 default:
547 break;
548 }
549 RelinquishSemaphoreInfo(resource_semaphore);
550 return(resource);
551}
552
553/*
554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555% %
556% %
557% %
558% G e t M a g i c k R e s o u r c e L i m i t %
559% %
560% %
561% %
562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563%
564% GetMagickResource() returns the specified resource limit.
565%
566% The format of the GetMagickResourceLimit() method is:
567%
568% unsigned long GetMagickResourceLimit(const ResourceType type)
569%
570% A description of each parameter follows:
571%
572% o type: the type of resource.
573%
574*/
575MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
576{
577 MagickSizeType
578 resource;
579
580 resource=0;
581 AcquireSemaphoreInfo(&resource_semaphore);
582 switch (type)
583 {
584 case AreaResource:
585 {
586 resource=resource_info.area_limit;
587 break;
588 }
589 case MemoryResource:
590 {
591 resource=resource_info.memory_limit;
592 break;
593 }
594 case MapResource:
595 {
596 resource=resource_info.map_limit;
597 break;
598 }
599 case DiskResource:
600 {
601 resource=resource_info.disk_limit;
602 break;
603 }
604 case FileResource:
605 {
606 resource=resource_info.file_limit;
607 break;
608 }
609 case ThreadResource:
610 {
611 resource=resource_info.thread_limit;
612 break;
613 }
614 case TimeResource:
615 {
616 resource=resource_info.time_limit;
617 break;
618 }
619 default:
620 break;
621 }
622 RelinquishSemaphoreInfo(resource_semaphore);
623 return(resource);
624}
625
626/*
627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628% %
629% %
630% %
cristy3ed852e2009-09-05 21:47:34 +0000631% L i s t M a g i c k R e s o u r c e I n f o %
632% %
633% %
634% %
635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636%
637% ListMagickResourceInfo() lists the resource info to a file.
638%
639% The format of the ListMagickResourceInfo method is:
640%
641% MagickBooleanType ListMagickResourceInfo(FILE *file,
642% ExceptionInfo *exception)
643%
644% A description of each parameter follows.
645%
646% o file: An pointer to a FILE.
647%
648% o exception: return any errors or warnings in this structure.
649%
650*/
651MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
652 ExceptionInfo *magick_unused(exception))
653{
654 char
655 area_limit[MaxTextExtent],
656 disk_limit[MaxTextExtent],
657 map_limit[MaxTextExtent],
658 memory_limit[MaxTextExtent],
659 time_limit[MaxTextExtent];
660
661 if (file == (const FILE *) NULL)
662 file=stdout;
663 AcquireSemaphoreInfo(&resource_semaphore);
664 (void) FormatMagickSize(resource_info.area_limit,area_limit);
665 (void) FormatMagickSize(resource_info.memory_limit,memory_limit);
666 (void) FormatMagickSize(resource_info.map_limit,map_limit);
667 (void) FormatMagickSize(resource_info.disk_limit,disk_limit);
668 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
669 if (resource_info.time_limit != MagickResourceInfinity)
670 (void) FormatMagickString(time_limit,MaxTextExtent,"%lu",(unsigned long)
671 resource_info.time_limit);
cristy9bf9da32009-09-27 16:48:34 +0000672 (void) fprintf(file,"File Area Memory Map"
673 " Disk Thread Time\n");
674 (void) fprintf(file,"------------------------------------------------------"
675 "------------------\n");
676 (void) fprintf(file,"%4lu %10s %10s %10s %10s %6lu %10s\n",
677 (unsigned long) resource_info.file_limit,area_limit,memory_limit,map_limit,
678 disk_limit,(unsigned long) resource_info.thread_limit,time_limit);
cristy3ed852e2009-09-05 21:47:34 +0000679 (void) fflush(file);
680 RelinquishSemaphoreInfo(resource_semaphore);
681 return(MagickTrue);
682}
683
684/*
685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686% %
687% %
688% %
689% R e l i n q u i s h M a g i c k R e s o u r c e %
690% %
691% %
692% %
693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694%
695% RelinquishMagickResource() relinquishes resources of the specified type.
696%
697% The format of the RelinquishMagickResource() method is:
698%
699% void RelinquishMagickResource(const ResourceType type,
700% const MagickSizeType size)
701%
702% A description of each parameter follows:
703%
704% o type: the type of resource.
705%
706% o size: the size of the resource.
707%
708*/
709MagickExport void RelinquishMagickResource(const ResourceType type,
710 const MagickSizeType size)
711{
712 char
713 resource_current[MaxTextExtent],
714 resource_limit[MaxTextExtent],
715 resource_request[MaxTextExtent];
716
717 (void) FormatMagickSize(size,resource_request);
718 AcquireSemaphoreInfo(&resource_semaphore);
719 switch (type)
720 {
721 case AreaResource:
722 {
723 resource_info.area=(MagickOffsetType) size;
724 (void) FormatMagickSize((MagickSizeType) resource_info.area,
725 resource_current);
726 (void) FormatMagickSize(resource_info.area_limit,resource_limit);
727 break;
728 }
729 case MemoryResource:
730 {
731 resource_info.memory-=size;
732 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
733 resource_current);
734 (void) FormatMagickSize(resource_info.memory_limit,resource_limit);
735 break;
736 }
737 case MapResource:
738 {
739 resource_info.map-=size;
740 (void) FormatMagickSize((MagickSizeType) resource_info.map,
741 resource_current);
742 (void) FormatMagickSize(resource_info.map_limit,resource_limit);
743 break;
744 }
745 case DiskResource:
746 {
747 resource_info.disk-=size;
748 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
749 resource_current);
750 (void) FormatMagickSize(resource_info.disk_limit,resource_limit);
751 break;
752 }
753 case FileResource:
754 {
755 resource_info.file-=size;
756 (void) FormatMagickSize((MagickSizeType) resource_info.file,
757 resource_current);
758 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
759 resource_limit);
760 break;
761 }
762 case ThreadResource:
763 {
764 resource_info.thread-=size;
765 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
766 resource_current);
767 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
768 resource_limit);
769 break;
770 }
771 case TimeResource:
772 {
773 resource_info.time-=size;
774 (void) FormatMagickSize((MagickSizeType) resource_info.time,
775 resource_current);
776 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
777 resource_limit);
778 break;
779 }
780 default:
781 break;
782 }
783 RelinquishSemaphoreInfo(resource_semaphore);
784 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
785 MagickOptionToMnemonic(MagickResourceOptions,(long) type),resource_request,
786 resource_current,resource_limit);
787}
788
789/*
790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791% %
792% %
793% %
794% 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 %
795% %
796% %
797% %
798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799%
800% RelinquishUniqueFileResource() relinquishes a unique file resource.
801%
802% The format of the RelinquishUniqueFileResource() method is:
803%
804% MagickBooleanType RelinquishUniqueFileResource(const char *path)
805%
806% A description of each parameter follows:
807%
808% o name: the name of the temporary resource.
809%
810*/
811MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
812{
813 char
814 cache_path[MaxTextExtent];
815
816 assert(path != (const char *) NULL);
817 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
818 if (temporary_resources != (SplayTreeInfo *) NULL)
819 {
820 register char
821 *p;
822
823 ResetSplayTreeIterator(temporary_resources);
824 p=(char *) GetNextKeyInSplayTree(temporary_resources);
825 while (p != (char *) NULL)
826 {
827 if (LocaleCompare(p,path) == 0)
828 break;
829 p=(char *) GetNextKeyInSplayTree(temporary_resources);
830 }
831 if (p != (char *) NULL)
832 (void) DeleteNodeFromSplayTree(temporary_resources,p);
833 }
834 (void) CopyMagickString(cache_path,path,MaxTextExtent);
835 AppendImageFormat("cache",cache_path);
836 (void) remove(cache_path);
837 return(remove(path) == 0 ? MagickTrue : MagickFalse);
838}
839
840/*
841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842% %
843% %
844% %
cristyf34a1452009-10-24 22:29:27 +0000845+ R e s o u r c e C o m p o n e n t G e n e s i s %
846% %
847% %
848% %
849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850%
851% ResourceComponentGenesis() instantiates the resource component.
852%
853% The format of the ResourceComponentGenesis method is:
854%
855% MagickBooleanType ResourceComponentGenesis(void)
856%
857*/
858
859static inline unsigned long MagickMax(const unsigned long x,
860 const unsigned long y)
861{
862 if (x > y)
863 return(x);
864 return(y);
865}
866
867static inline MagickSizeType StringToSizeType(const char *string,
868 const double interval)
869{
870 double
871 value;
872
873 value=StringToDouble(string,interval);
874 if (value >= (double) MagickULLConstant(~0))
875 return(MagickULLConstant(~0));
876 return((MagickSizeType) value);
877}
878
879MagickExport MagickBooleanType ResourceComponentGenesis(void)
880{
881 char
882 *limit;
883
884 long
885 files,
886 pages,
887 pagesize;
888
889 MagickSizeType
890 memory;
891
892 /*
893 Set Magick resource limits.
894 */
895 AcquireSemaphoreInfo(&resource_semaphore);
896 RelinquishSemaphoreInfo(resource_semaphore);
897 pagesize=GetMagickPageSize();
898 pages=(-1);
899#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
900 pages=sysconf(_SC_PHYS_PAGES);
901#endif
902 memory=(MagickSizeType) pages*pagesize;
903 if ((pagesize <= 0) || (pages <= 0))
904 memory=2048UL*1024UL*1024UL;
905#if defined(PixelCacheThreshold)
906 memory=PixelCacheThreshold;
907#endif
908 (void) SetMagickResourceLimit(AreaResource,2UL*memory);
909 (void) SetMagickResourceLimit(MemoryResource,3UL*memory/2UL);
910 (void) SetMagickResourceLimit(MapResource,4UL*memory);
911 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
912 if (limit == (char *) NULL)
913 limit=GetPolicyValue("area");
914 if (limit != (char *) NULL)
915 {
916 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
917 limit=DestroyString(limit);
918 }
919 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
920 if (limit == (char *) NULL)
921 limit=GetPolicyValue("memory");
922 if (limit != (char *) NULL)
923 {
924 (void) SetMagickResourceLimit(MemoryResource,
925 StringToSizeType(limit,100.0));
926 limit=DestroyString(limit);
927 }
928 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
929 if (limit == (char *) NULL)
930 limit=GetPolicyValue("map");
931 if (limit != (char *) NULL)
932 {
933 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
934 limit=DestroyString(limit);
935 }
936 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
937 if (limit == (char *) NULL)
938 limit=GetPolicyValue("disk");
939 if (limit != (char *) NULL)
940 {
941 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
942 limit=DestroyString(limit);
943 }
944 files=(-1);
945#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
946 files=sysconf(_SC_OPEN_MAX);
947#endif
948#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
949 if (files < 0)
950 {
951 struct rlimit
952 resources;
953
954 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
955 files=resources.rlim_cur;
956 }
957#endif
958#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
959 if (files < 0)
960 files=getdtablesize();
961#endif
962 if (files < 0)
963 files=64;
964 (void) SetMagickResourceLimit(FileResource,MagickMax((unsigned long)
965 (3*files/4),64));
966 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
967 if (limit == (char *) NULL)
968 limit=GetPolicyValue("file");
969 if (limit != (char *) NULL)
970 {
971 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
972 limit=DestroyString(limit);
973 }
974 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
975 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
976 if (limit == (char *) NULL)
977 limit=GetPolicyValue("thread");
978 if (limit != (char *) NULL)
979 {
980 SetOpenMPMaximumThreads((unsigned long) atol(limit));
981 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
982 100.0));
983 limit=DestroyString(limit);
984 }
985 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
986 if (limit == (char *) NULL)
987 limit=GetPolicyValue("time");
988 if (limit != (char *) NULL)
989 {
990 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
991 limit=DestroyString(limit);
992 }
993 return(MagickTrue);
994}
995
996/*
997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998% %
999% %
1000% %
1001+ 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 %
1002% %
1003% %
1004% %
1005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006%
1007% ResourceComponentTerminus() destroys the resource component.
1008%
1009% The format of the ResourceComponentTerminus() method is:
1010%
1011% ResourceComponentTerminus(void)
1012%
1013*/
1014MagickExport void ResourceComponentTerminus(void)
1015{
1016 AcquireSemaphoreInfo(&resource_semaphore);
1017 if (temporary_resources != (SplayTreeInfo *) NULL)
1018 temporary_resources=DestroySplayTree(temporary_resources);
1019 if (random_info != (RandomInfo *) NULL)
1020 random_info=DestroyRandomInfo(random_info);
1021 RelinquishSemaphoreInfo(resource_semaphore);
1022 DestroySemaphoreInfo(&resource_semaphore);
1023}
1024
1025/*
1026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1027% %
1028% %
1029% %
cristy3ed852e2009-09-05 21:47:34 +00001030% S e t M a g i c k R e s o u r c e L i m i t %
1031% %
1032% %
1033% %
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035%
1036% SetMagickResourceLimit() sets the limit for a particular resource.
1037%
1038% The format of the SetMagickResourceLimit() method is:
1039%
1040% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1041% const MagickSizeType limit)
1042%
1043% A description of each parameter follows:
1044%
1045% o type: the type of resource.
1046%
1047% o limit: the maximum limit for the resource.
1048%
1049*/
1050MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1051 const MagickSizeType limit)
1052{
1053 AcquireSemaphoreInfo(&resource_semaphore);
1054 switch (type)
1055 {
1056 case AreaResource:
1057 {
1058 resource_info.area_limit=limit;
1059 break;
1060 }
1061 case MemoryResource:
1062 {
1063 resource_info.memory_limit=limit;
1064 break;
1065 }
1066 case MapResource:
1067 {
1068 resource_info.map_limit=limit;
1069 break;
1070 }
1071 case DiskResource:
1072 {
1073 resource_info.disk_limit=limit;
1074 break;
1075 }
1076 case FileResource:
1077 {
1078 resource_info.file_limit=limit;
1079 break;
1080 }
1081 case ThreadResource:
1082 {
1083 SetOpenMPMaximumThreads((unsigned long) limit);
1084 resource_info.thread_limit=GetOpenMPMaximumThreads();
1085 break;
1086 }
1087 case TimeResource:
1088 {
1089 resource_info.time_limit=limit;
1090 break;
1091 }
1092 default:
1093 break;
1094 }
1095 RelinquishSemaphoreInfo(resource_semaphore);
1096 return(MagickTrue);
1097}