blob: 1d25b5b7d44df2efc1fe152cbebbc1abdb0d2dbc [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% %
268+ A s y n c h r o n o u s D e s t r o y M a g i c k R e s o u r c e s %
269% %
270% %
271% %
272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273%
274% AsynchronousDestroyMagickResources() destroys the resource environment.
275% It differs from DestroyMagickResources() in that it can be called from a
276% asynchronous signal handler.
277%
278% The format of the DestroyMagickResources() method is:
279%
280% DestroyMagickResources(void)
281%
282*/
283MagickExport void AsynchronousDestroyMagickResources(void)
284{
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% %
485+ D e s t r o y M a g i c k R e s o u r c e s %
486% %
487% %
488% %
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%
491% DestroyMagickResources() destroys the resource environment.
492%
493% The format of the DestroyMagickResources() method is:
494%
495% DestroyMagickResources(void)
496%
497*/
498MagickExport void DestroyMagickResources(void)
499{
500 AcquireSemaphoreInfo(&resource_semaphore);
501 if (temporary_resources != (SplayTreeInfo *) NULL)
502 temporary_resources=DestroySplayTree(temporary_resources);
503 if (random_info != (RandomInfo *) NULL)
504 random_info=DestroyRandomInfo(random_info);
505 RelinquishSemaphoreInfo(resource_semaphore);
506 DestroySemaphoreInfo(&resource_semaphore);
507}
508
509/*
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511% %
512% %
513% %
514% G e t M a g i c k R e s o u r c e %
515% %
516% %
517% %
518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519%
520% GetMagickResource() returns the specified resource.
521%
522% The format of the GetMagickResource() method is:
523%
524% MagickSizeType GetMagickResource(const ResourceType type)
525%
526% A description of each parameter follows:
527%
528% o type: the type of resource.
529%
530*/
531MagickExport MagickSizeType GetMagickResource(const ResourceType type)
532{
533 MagickSizeType
534 resource;
535
536 resource=0;
537 AcquireSemaphoreInfo(&resource_semaphore);
538 switch (type)
539 {
540 case AreaResource:
541 {
542 resource=(MagickSizeType) resource_info.area;
543 break;
544 }
545 case MemoryResource:
546 {
547 resource=(MagickSizeType) resource_info.memory;
548 break;
549 }
550 case MapResource:
551 {
552 resource=(MagickSizeType) resource_info.map;
553 break;
554 }
555 case DiskResource:
556 {
557 resource=(MagickSizeType) resource_info.disk;
558 break;
559 }
560 case FileResource:
561 {
562 resource=(MagickSizeType) resource_info.file;
563 break;
564 }
565 case ThreadResource:
566 {
567 resource=(MagickSizeType) resource_info.thread;
568 break;
569 }
570 case TimeResource:
571 {
572 resource=(MagickSizeType) resource_info.time;
573 break;
574 }
575 default:
576 break;
577 }
578 RelinquishSemaphoreInfo(resource_semaphore);
579 return(resource);
580}
581
582/*
583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584% %
585% %
586% %
587% G e t M a g i c k R e s o u r c e L i m i t %
588% %
589% %
590% %
591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592%
593% GetMagickResource() returns the specified resource limit.
594%
595% The format of the GetMagickResourceLimit() method is:
596%
597% unsigned long GetMagickResourceLimit(const ResourceType type)
598%
599% A description of each parameter follows:
600%
601% o type: the type of resource.
602%
603*/
604MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
605{
606 MagickSizeType
607 resource;
608
609 resource=0;
610 AcquireSemaphoreInfo(&resource_semaphore);
611 switch (type)
612 {
613 case AreaResource:
614 {
615 resource=resource_info.area_limit;
616 break;
617 }
618 case MemoryResource:
619 {
620 resource=resource_info.memory_limit;
621 break;
622 }
623 case MapResource:
624 {
625 resource=resource_info.map_limit;
626 break;
627 }
628 case DiskResource:
629 {
630 resource=resource_info.disk_limit;
631 break;
632 }
633 case FileResource:
634 {
635 resource=resource_info.file_limit;
636 break;
637 }
638 case ThreadResource:
639 {
640 resource=resource_info.thread_limit;
641 break;
642 }
643 case TimeResource:
644 {
645 resource=resource_info.time_limit;
646 break;
647 }
648 default:
649 break;
650 }
651 RelinquishSemaphoreInfo(resource_semaphore);
652 return(resource);
653}
654
655/*
656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657% %
658% %
659% %
660+ I n i t i a l i z e M a g i c k R e s o u r c e s %
661% %
662% %
663% %
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%
666% InitializeMagickResources() initializes the resource environment.
667%
668% The format of the InitializeMagickResources() method is:
669%
670% InitializeMagickResources(void)
671%
672*/
673
674static inline unsigned long MagickMax(const unsigned long x,
675 const unsigned long y)
676{
677 if (x > y)
678 return(x);
679 return(y);
680}
681
682static inline MagickSizeType StringToSizeType(const char *string,
683 const double interval)
684{
685 double
686 value;
687
688 value=StringToDouble(string,interval);
689 if (value >= (double) MagickULLConstant(~0))
690 return(MagickULLConstant(~0));
691 return((MagickSizeType) value);
692}
693
694MagickExport void InitializeMagickResources(void)
695{
696 char
697 *limit;
698
699 long
700 files,
701 pages,
702 pagesize;
703
704 MagickSizeType
705 memory;
706
707 /*
708 Set Magick resource limits.
709 */
cristy688f07b2009-09-27 15:19:13 +0000710 pagesize=GetMagickPageSize();
cristy3ed852e2009-09-05 21:47:34 +0000711 pages=(-1);
712#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
713 pages=sysconf(_SC_PHYS_PAGES);
714#endif
715 memory=(MagickSizeType) pages*pagesize;
716 if ((pagesize <= 0) || (pages <= 0))
717 memory=2048UL*1024UL*1024UL;
718#if defined(PixelCacheThreshold)
719 memory=PixelCacheThreshold;
720#endif
721 (void) SetMagickResourceLimit(AreaResource,2UL*memory);
722 (void) SetMagickResourceLimit(MemoryResource,3UL*memory/2UL);
723 (void) SetMagickResourceLimit(MapResource,4UL*memory);
724 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
725 if (limit == (char *) NULL)
726 limit=GetPolicyValue("area");
727 if (limit != (char *) NULL)
728 {
729 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
730 limit=DestroyString(limit);
731 }
732 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
733 if (limit == (char *) NULL)
734 limit=GetPolicyValue("memory");
735 if (limit != (char *) NULL)
736 {
737 (void) SetMagickResourceLimit(MemoryResource,
738 StringToSizeType(limit,100.0));
739 limit=DestroyString(limit);
740 }
741 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
742 if (limit == (char *) NULL)
743 limit=GetPolicyValue("map");
744 if (limit != (char *) NULL)
745 {
746 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
747 limit=DestroyString(limit);
748 }
749 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
750 if (limit == (char *) NULL)
751 limit=GetPolicyValue("disk");
752 if (limit != (char *) NULL)
753 {
754 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
755 limit=DestroyString(limit);
756 }
757 files=(-1);
758#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
759 files=sysconf(_SC_OPEN_MAX);
cristy3ed852e2009-09-05 21:47:34 +0000760#endif
cristy56489a52009-09-09 03:13:52 +0000761#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
762 if (files < 0)
763 {
764 struct rlimit
765 resources;
766
767 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
768 files=resources.rlim_cur;
769 }
770#endif
771#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
772 if (files < 0)
773 files=getdtablesize();
774#endif
775 if (files < 0)
776 files=64;
cristy3ed852e2009-09-05 21:47:34 +0000777 (void) SetMagickResourceLimit(FileResource,MagickMax((unsigned long)
778 (3*files/4),64));
779 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
780 if (limit == (char *) NULL)
781 limit=GetPolicyValue("file");
782 if (limit != (char *) NULL)
783 {
784 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
785 limit=DestroyString(limit);
786 }
787 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
788 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
789 if (limit == (char *) NULL)
790 limit=GetPolicyValue("thread");
791 if (limit != (char *) NULL)
792 {
793 SetOpenMPMaximumThreads((unsigned long) atol(limit));
794 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
795 100.0));
796 limit=DestroyString(limit);
797 }
798 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
799 if (limit == (char *) NULL)
800 limit=GetPolicyValue("time");
801 if (limit != (char *) NULL)
802 {
803 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
804 limit=DestroyString(limit);
805 }
806}
807
808/*
809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
810% %
811% %
812% %
813% L i s t M a g i c k R e s o u r c e I n f o %
814% %
815% %
816% %
817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
818%
819% ListMagickResourceInfo() lists the resource info to a file.
820%
821% The format of the ListMagickResourceInfo method is:
822%
823% MagickBooleanType ListMagickResourceInfo(FILE *file,
824% ExceptionInfo *exception)
825%
826% A description of each parameter follows.
827%
828% o file: An pointer to a FILE.
829%
830% o exception: return any errors or warnings in this structure.
831%
832*/
833MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
834 ExceptionInfo *magick_unused(exception))
835{
836 char
837 area_limit[MaxTextExtent],
838 disk_limit[MaxTextExtent],
839 map_limit[MaxTextExtent],
840 memory_limit[MaxTextExtent],
841 time_limit[MaxTextExtent];
842
843 if (file == (const FILE *) NULL)
844 file=stdout;
845 AcquireSemaphoreInfo(&resource_semaphore);
846 (void) FormatMagickSize(resource_info.area_limit,area_limit);
847 (void) FormatMagickSize(resource_info.memory_limit,memory_limit);
848 (void) FormatMagickSize(resource_info.map_limit,map_limit);
849 (void) FormatMagickSize(resource_info.disk_limit,disk_limit);
850 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
851 if (resource_info.time_limit != MagickResourceInfinity)
852 (void) FormatMagickString(time_limit,MaxTextExtent,"%lu",(unsigned long)
853 resource_info.time_limit);
cristy9bf9da32009-09-27 16:48:34 +0000854 (void) fprintf(file,"File Area Memory Map"
855 " Disk Thread Time\n");
856 (void) fprintf(file,"------------------------------------------------------"
857 "------------------\n");
858 (void) fprintf(file,"%4lu %10s %10s %10s %10s %6lu %10s\n",
859 (unsigned long) resource_info.file_limit,area_limit,memory_limit,map_limit,
860 disk_limit,(unsigned long) resource_info.thread_limit,time_limit);
cristy3ed852e2009-09-05 21:47:34 +0000861 (void) fflush(file);
862 RelinquishSemaphoreInfo(resource_semaphore);
863 return(MagickTrue);
864}
865
866/*
867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868% %
869% %
870% %
871% R e l i n q u i s h M a g i c k R e s o u r c e %
872% %
873% %
874% %
875%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876%
877% RelinquishMagickResource() relinquishes resources of the specified type.
878%
879% The format of the RelinquishMagickResource() method is:
880%
881% void RelinquishMagickResource(const ResourceType type,
882% const MagickSizeType size)
883%
884% A description of each parameter follows:
885%
886% o type: the type of resource.
887%
888% o size: the size of the resource.
889%
890*/
891MagickExport void RelinquishMagickResource(const ResourceType type,
892 const MagickSizeType size)
893{
894 char
895 resource_current[MaxTextExtent],
896 resource_limit[MaxTextExtent],
897 resource_request[MaxTextExtent];
898
899 (void) FormatMagickSize(size,resource_request);
900 AcquireSemaphoreInfo(&resource_semaphore);
901 switch (type)
902 {
903 case AreaResource:
904 {
905 resource_info.area=(MagickOffsetType) size;
906 (void) FormatMagickSize((MagickSizeType) resource_info.area,
907 resource_current);
908 (void) FormatMagickSize(resource_info.area_limit,resource_limit);
909 break;
910 }
911 case MemoryResource:
912 {
913 resource_info.memory-=size;
914 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
915 resource_current);
916 (void) FormatMagickSize(resource_info.memory_limit,resource_limit);
917 break;
918 }
919 case MapResource:
920 {
921 resource_info.map-=size;
922 (void) FormatMagickSize((MagickSizeType) resource_info.map,
923 resource_current);
924 (void) FormatMagickSize(resource_info.map_limit,resource_limit);
925 break;
926 }
927 case DiskResource:
928 {
929 resource_info.disk-=size;
930 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
931 resource_current);
932 (void) FormatMagickSize(resource_info.disk_limit,resource_limit);
933 break;
934 }
935 case FileResource:
936 {
937 resource_info.file-=size;
938 (void) FormatMagickSize((MagickSizeType) resource_info.file,
939 resource_current);
940 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
941 resource_limit);
942 break;
943 }
944 case ThreadResource:
945 {
946 resource_info.thread-=size;
947 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
948 resource_current);
949 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
950 resource_limit);
951 break;
952 }
953 case TimeResource:
954 {
955 resource_info.time-=size;
956 (void) FormatMagickSize((MagickSizeType) resource_info.time,
957 resource_current);
958 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
959 resource_limit);
960 break;
961 }
962 default:
963 break;
964 }
965 RelinquishSemaphoreInfo(resource_semaphore);
966 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
967 MagickOptionToMnemonic(MagickResourceOptions,(long) type),resource_request,
968 resource_current,resource_limit);
969}
970
971/*
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973% %
974% %
975% %
976% 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 %
977% %
978% %
979% %
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981%
982% RelinquishUniqueFileResource() relinquishes a unique file resource.
983%
984% The format of the RelinquishUniqueFileResource() method is:
985%
986% MagickBooleanType RelinquishUniqueFileResource(const char *path)
987%
988% A description of each parameter follows:
989%
990% o name: the name of the temporary resource.
991%
992*/
993MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
994{
995 char
996 cache_path[MaxTextExtent];
997
998 assert(path != (const char *) NULL);
999 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1000 if (temporary_resources != (SplayTreeInfo *) NULL)
1001 {
1002 register char
1003 *p;
1004
1005 ResetSplayTreeIterator(temporary_resources);
1006 p=(char *) GetNextKeyInSplayTree(temporary_resources);
1007 while (p != (char *) NULL)
1008 {
1009 if (LocaleCompare(p,path) == 0)
1010 break;
1011 p=(char *) GetNextKeyInSplayTree(temporary_resources);
1012 }
1013 if (p != (char *) NULL)
1014 (void) DeleteNodeFromSplayTree(temporary_resources,p);
1015 }
1016 (void) CopyMagickString(cache_path,path,MaxTextExtent);
1017 AppendImageFormat("cache",cache_path);
1018 (void) remove(cache_path);
1019 return(remove(path) == 0 ? MagickTrue : MagickFalse);
1020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024% %
1025% %
1026% %
1027% S e t M a g i c k R e s o u r c e L i m i t %
1028% %
1029% %
1030% %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033% SetMagickResourceLimit() sets the limit for a particular resource.
1034%
1035% The format of the SetMagickResourceLimit() method is:
1036%
1037% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1038% const MagickSizeType limit)
1039%
1040% A description of each parameter follows:
1041%
1042% o type: the type of resource.
1043%
1044% o limit: the maximum limit for the resource.
1045%
1046*/
1047MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1048 const MagickSizeType limit)
1049{
1050 AcquireSemaphoreInfo(&resource_semaphore);
1051 switch (type)
1052 {
1053 case AreaResource:
1054 {
1055 resource_info.area_limit=limit;
1056 break;
1057 }
1058 case MemoryResource:
1059 {
1060 resource_info.memory_limit=limit;
1061 break;
1062 }
1063 case MapResource:
1064 {
1065 resource_info.map_limit=limit;
1066 break;
1067 }
1068 case DiskResource:
1069 {
1070 resource_info.disk_limit=limit;
1071 break;
1072 }
1073 case FileResource:
1074 {
1075 resource_info.file_limit=limit;
1076 break;
1077 }
1078 case ThreadResource:
1079 {
1080 SetOpenMPMaximumThreads((unsigned long) limit);
1081 resource_info.thread_limit=GetOpenMPMaximumThreads();
1082 break;
1083 }
1084 case TimeResource:
1085 {
1086 resource_info.time_limit=limit;
1087 break;
1088 }
1089 default:
1090 break;
1091 }
1092 RelinquishSemaphoreInfo(resource_semaphore);
1093 return(MagickTrue);
1094}