2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % Get/Set MagickCore Resources %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #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/nt-base-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/policy.h"
54 #include "MagickCore/random_.h"
55 #include "MagickCore/registry.h"
56 #include "MagickCore/resource_.h"
57 #include "MagickCore/resource-private.h"
58 #include "MagickCore/semaphore.h"
59 #include "MagickCore/signature-private.h"
60 #include "MagickCore/string_.h"
61 #include "MagickCore/string-private.h"
62 #include "MagickCore/splay-tree.h"
63 #include "MagickCore/thread-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
71 typedef struct _ResourceInfo
98 *random_info = (RandomInfo *) NULL;
103 MagickULLConstant(0), /* initial area */
104 MagickULLConstant(0), /* initial memory */
105 MagickULLConstant(0), /* initial map */
106 MagickULLConstant(0), /* initial disk */
107 MagickULLConstant(0), /* initial file */
108 MagickULLConstant(0), /* initial thread */
109 MagickULLConstant(0), /* initial throttle */
110 MagickULLConstant(0), /* initial time */
111 MagickULLConstant(3072)*1024*1024, /* area limit */
112 MagickULLConstant(1536)*1024*1024, /* memory limit */
113 MagickULLConstant(3072)*1024*1024, /* map limit */
114 MagickResourceInfinity, /* disk limit */
115 MagickULLConstant(768), /* file limit */
116 MagickULLConstant(1), /* thread limit */
117 MagickULLConstant(0), /* throttle limit */
118 MagickResourceInfinity /* time limit */
122 *resource_semaphore = (SemaphoreInfo *) NULL;
125 *temporary_resources = (SplayTreeInfo *) NULL;
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132 % A c q u i r e M a g i c k R e s o u r c e %
136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 % AcquireMagickResource() acquires resources of the specified type.
139 % MagickFalse is returned if the specified resource is exhausted otherwise
142 % The format of the AcquireMagickResource() method is:
144 % MagickBooleanType AcquireMagickResource(const ResourceType type,
145 % const MagickSizeType size)
147 % A description of each parameter follows:
149 % o type: the type of resource.
151 % o size: the number of bytes needed from for this resource.
154 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
155 const MagickSizeType size)
158 resource_current[MaxTextExtent],
159 resource_limit[MaxTextExtent],
160 resource_request[MaxTextExtent];
169 (void) FormatMagickSize(size,MagickFalse,resource_request);
170 if (resource_semaphore == (SemaphoreInfo *) NULL)
171 ActivateSemaphoreInfo(&resource_semaphore);
172 LockSemaphoreInfo(resource_semaphore);
177 resource_info.area=(MagickOffsetType) size;
178 limit=resource_info.area_limit;
179 status=(resource_info.area_limit == MagickResourceInfinity) ||
180 (size < limit) ? MagickTrue : MagickFalse;
181 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
183 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
189 resource_info.memory+=size;
190 limit=resource_info.memory_limit;
191 status=(resource_info.memory_limit == MagickResourceInfinity) ||
192 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
194 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
196 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
202 resource_info.map+=size;
203 limit=resource_info.map_limit;
204 status=(resource_info.map_limit == MagickResourceInfinity) ||
205 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
206 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
208 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
214 resource_info.disk+=size;
215 limit=resource_info.disk_limit;
216 status=(resource_info.disk_limit == MagickResourceInfinity) ||
217 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
219 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
221 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
227 resource_info.file+=size;
228 limit=resource_info.file_limit;
229 status=(resource_info.file_limit == MagickResourceInfinity) ||
230 ((MagickSizeType) resource_info.file < limit) ?
231 MagickTrue : MagickFalse;
232 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
234 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
235 MagickFalse,resource_limit);
240 limit=resource_info.thread_limit;
241 status=(resource_info.thread_limit == MagickResourceInfinity) ||
242 ((MagickSizeType) resource_info.thread < limit) ?
243 MagickTrue : MagickFalse;
244 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
246 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
247 MagickFalse,resource_limit);
250 case ThrottleResource:
252 limit=resource_info.throttle_limit;
253 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
254 ((MagickSizeType) resource_info.throttle < limit) ?
255 MagickTrue : MagickFalse;
256 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
257 MagickFalse,resource_current);
258 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
259 MagickFalse,resource_limit);
264 resource_info.time+=size;
265 limit=resource_info.time_limit;
266 status=(resource_info.time_limit == MagickResourceInfinity) ||
267 ((MagickSizeType) resource_info.time < limit) ?
268 MagickTrue : MagickFalse;
269 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
271 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
272 MagickFalse,resource_limit);
278 UnlockSemaphoreInfo(resource_semaphore);
279 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
280 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
281 resource_request,resource_current,resource_limit);
286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 + 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 %
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % AsynchronousResourceComponentTerminus() destroys the resource environment.
297 % It differs from ResourceComponentTerminus() in that it can be called from a
298 % asynchronous signal handler.
300 % The format of the ResourceComponentTerminus() method is:
302 % ResourceComponentTerminus(void)
305 MagickPrivate void AsynchronousResourceComponentTerminus(void)
310 if (temporary_resources == (SplayTreeInfo *) NULL)
313 Remove any lingering temporary files.
315 ResetSplayTreeIterator(temporary_resources);
316 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
317 while (path != (const char *) NULL)
319 (void) ShredFile(path);
320 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 % 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 %
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 % AcquireUniqueFileResource() returns a unique file name, and returns a file
336 % descriptor for the file open for reading and writing.
338 % The format of the AcquireUniqueFileResource() method is:
340 % int AcquireUniqueFileResource(char *path)
342 % A description of each parameter follows:
344 % o path: Specifies a pointer to an array of characters. The unique path
345 % name is returned in this array.
349 static void *DestroyTemporaryResources(void *temporary_resource)
351 (void) ShredFile((char *) temporary_resource);
352 temporary_resource=DestroyString((char *) temporary_resource);
353 return((void *) NULL);
356 MagickExport MagickBooleanType GetPathTemplate(char *path)
371 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
373 exception=AcquireExceptionInfo();
374 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
376 exception=DestroyExceptionInfo(exception);
377 if (directory == (char *) NULL)
378 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
379 if (directory == (char *) NULL)
380 directory=GetEnvironmentValue("MAGICK_TMPDIR");
381 if (directory == (char *) NULL)
382 directory=GetEnvironmentValue("TMPDIR");
383 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
384 if (directory == (char *) NULL)
385 directory=GetEnvironmentValue("TMP");
386 if (directory == (char *) NULL)
387 directory=GetEnvironmentValue("TEMP");
390 if (directory == (char *) NULL)
391 directory=GetEnvironmentValue("MTMPDIR");
393 #if defined(P_tmpdir)
394 if (directory == (char *) NULL)
395 directory=ConstantString(P_tmpdir);
397 if (directory == (char *) NULL)
399 value=GetPolicyValue("temporary-path");
400 if (value != (char *) NULL)
401 (void) CloneString(&directory,value);
402 if (strlen(directory) > (MaxTextExtent-25))
404 directory=DestroyString(directory);
407 status=GetPathAttributes(directory,&attributes);
408 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
410 directory=DestroyString(directory);
413 if (directory[strlen(directory)-1] == *DirectorySeparator)
414 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
415 directory,(double) getpid());
417 (void) FormatLocaleString(path,MaxTextExtent,
418 "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,
420 directory=DestroyString(directory);
421 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
427 Ghostscript does not like backslashes so we need to replace them. The
428 forward slash also works under Windows.
430 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
431 if (*p == *DirectorySeparator)
438 MagickExport int AcquireUniqueFileResource(char *path)
440 #if !defined(O_NOFOLLOW)
443 #if !defined(TMP_MAX)
444 # define TMP_MAX 238328
458 portable_filename[65] =
459 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
467 assert(path != (char *) NULL);
468 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
469 if (random_info == (RandomInfo *) NULL)
470 random_info=AcquireRandomInfo();
472 for (i=0; i < (ssize_t) TMP_MAX; i++)
475 Get temporary pathname.
477 (void) GetPathTemplate(path);
478 key=GetRandomKey(random_info,6);
479 p=path+strlen(path)-12;
480 datum=GetStringInfoDatum(key);
481 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
483 c=(int) (datum[i] & 0x3f);
484 *p++=portable_filename[c];
486 key=DestroyStringInfo(key);
487 #if defined(MAGICKCORE_HAVE_MKSTEMP)
490 setmode(file,O_BINARY);
495 key=GetRandomKey(random_info,12);
496 p=path+strlen(path)-12;
497 datum=GetStringInfoDatum(key);
498 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
500 c=(int) (datum[i] & 0x3f);
501 *p++=portable_filename[c];
503 key=DestroyStringInfo(key);
504 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
506 if ((file >= 0) || (errno != EEXIST))
509 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
512 if (resource_semaphore == (SemaphoreInfo *) NULL)
513 ActivateSemaphoreInfo(&resource_semaphore);
514 LockSemaphoreInfo(resource_semaphore);
515 if (temporary_resources == (SplayTreeInfo *) NULL)
516 temporary_resources=NewSplayTree(CompareSplayTreeString,
517 DestroyTemporaryResources,(void *(*)(void *)) NULL);
518 UnlockSemaphoreInfo(resource_semaphore);
519 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
520 (const void *) NULL);
525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
529 % G e t M a g i c k R e s o u r c e %
533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535 % GetMagickResource() returns the specified resource.
537 % The format of the GetMagickResource() method is:
539 % MagickSizeType GetMagickResource(const ResourceType type)
541 % A description of each parameter follows:
543 % o type: the type of resource.
546 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
552 LockSemaphoreInfo(resource_semaphore);
557 resource=(MagickSizeType) resource_info.area;
562 resource=(MagickSizeType) resource_info.memory;
567 resource=(MagickSizeType) resource_info.map;
572 resource=(MagickSizeType) resource_info.disk;
577 resource=(MagickSizeType) resource_info.file;
582 resource=(MagickSizeType) resource_info.thread;
585 case ThrottleResource:
587 resource=(MagickSizeType) resource_info.throttle;
592 resource=(MagickSizeType) resource_info.time;
598 UnlockSemaphoreInfo(resource_semaphore);
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 % G e t M a g i c k R e s o u r c e L i m i t %
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 % GetMagickResourceLimit() returns the specified resource limit.
615 % The format of the GetMagickResourceLimit() method is:
617 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
619 % A description of each parameter follows:
621 % o type: the type of resource.
624 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
630 if (resource_semaphore == (SemaphoreInfo *) NULL)
631 ActivateSemaphoreInfo(&resource_semaphore);
632 LockSemaphoreInfo(resource_semaphore);
637 resource=resource_info.area_limit;
642 resource=resource_info.memory_limit;
647 resource=resource_info.map_limit;
652 resource=resource_info.disk_limit;
657 resource=resource_info.file_limit;
662 resource=resource_info.thread_limit;
665 case ThrottleResource:
667 resource=resource_info.throttle_limit;
672 resource=resource_info.time_limit;
678 UnlockSemaphoreInfo(resource_semaphore);
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 % L i s t M a g i c k R e s o u r c e I n f o %
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 % ListMagickResourceInfo() lists the resource info to a file.
695 % The format of the ListMagickResourceInfo method is:
697 % MagickBooleanType ListMagickResourceInfo(FILE *file,
698 % ExceptionInfo *exception)
700 % A description of each parameter follows.
702 % o file: An pointer to a FILE.
704 % o exception: return any errors or warnings in this structure.
707 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
708 ExceptionInfo *magick_unused(exception))
711 area_limit[MaxTextExtent],
712 disk_limit[MaxTextExtent],
713 map_limit[MaxTextExtent],
714 memory_limit[MaxTextExtent],
715 time_limit[MaxTextExtent];
717 if (file == (const FILE *) NULL)
719 if (resource_semaphore == (SemaphoreInfo *) NULL)
720 ActivateSemaphoreInfo(&resource_semaphore);
721 LockSemaphoreInfo(resource_semaphore);
722 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
723 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
724 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
725 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
726 if (resource_info.disk_limit != MagickResourceInfinity)
727 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
728 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
729 if (resource_info.time_limit != MagickResourceInfinity)
730 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
731 ((MagickOffsetType) resource_info.time_limit));
732 (void) FormatLocaleFile(file," File Area Memory Map"
733 " Disk Thread Throttle Time\n");
734 (void) FormatLocaleFile(file,
735 "--------------------------------------------------------"
736 "------------------------\n");
737 (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %8g %8g %10s\n",
738 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
739 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
740 resource_info.thread_limit),(double) ((MagickOffsetType)
741 resource_info.throttle_limit),time_limit);
743 UnlockSemaphoreInfo(resource_semaphore);
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752 % R e l i n q u i s h M a g i c k R e s o u r c e %
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758 % RelinquishMagickResource() relinquishes resources of the specified type.
760 % The format of the RelinquishMagickResource() method is:
762 % void RelinquishMagickResource(const ResourceType type,
763 % const MagickSizeType size)
765 % A description of each parameter follows:
767 % o type: the type of resource.
769 % o size: the size of the resource.
772 MagickExport void RelinquishMagickResource(const ResourceType type,
773 const MagickSizeType size)
776 resource_current[MaxTextExtent],
777 resource_limit[MaxTextExtent],
778 resource_request[MaxTextExtent];
780 (void) FormatMagickSize(size,MagickFalse,resource_request);
781 if (resource_semaphore == (SemaphoreInfo *) NULL)
782 ActivateSemaphoreInfo(&resource_semaphore);
783 LockSemaphoreInfo(resource_semaphore);
788 resource_info.area=(MagickOffsetType) size;
789 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
791 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
797 resource_info.memory-=size;
798 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
799 MagickTrue,resource_current);
800 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
806 resource_info.map-=size;
807 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
809 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
815 resource_info.disk-=size;
816 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
818 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
824 resource_info.file-=size;
825 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
827 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
828 MagickFalse,resource_limit);
833 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
835 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
836 MagickFalse,resource_limit);
839 case ThrottleResource:
841 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
842 MagickFalse,resource_current);
843 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
844 MagickFalse,resource_limit);
849 resource_info.time-=size;
850 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
852 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
853 MagickFalse,resource_limit);
859 UnlockSemaphoreInfo(resource_semaphore);
860 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
861 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
862 resource_request,resource_current,resource_limit);
866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870 % 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 %
874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 % RelinquishUniqueFileResource() relinquishes a unique file resource.
878 % The format of the RelinquishUniqueFileResource() method is:
880 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
882 % A description of each parameter follows:
884 % o name: the name of the temporary resource.
887 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
890 cache_path[MaxTextExtent];
892 assert(path != (const char *) NULL);
893 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
894 if (temporary_resources != (SplayTreeInfo *) NULL)
899 ResetSplayTreeIterator(temporary_resources);
900 p=(char *) GetNextKeyInSplayTree(temporary_resources);
901 while (p != (char *) NULL)
903 if (LocaleCompare(p,path) == 0)
905 p=(char *) GetNextKeyInSplayTree(temporary_resources);
907 if (p != (char *) NULL)
908 (void) DeleteNodeFromSplayTree(temporary_resources,p);
910 (void) CopyMagickString(cache_path,path,MaxTextExtent);
911 AppendImageFormat("cache",cache_path);
912 (void) ShredFile(cache_path);
913 return(ShredFile(path));
917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
921 + R e s o u r c e C o m p o n e n t G e n e s i s %
925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927 % ResourceComponentGenesis() instantiates the resource component.
929 % The format of the ResourceComponentGenesis method is:
931 % MagickBooleanType ResourceComponentGenesis(void)
935 static inline size_t MagickMax(const size_t x,const size_t y)
942 static inline MagickSizeType StringToSizeType(const char *string,
943 const double interval)
948 value=SiPrefixToDoubleInterval(string,interval);
949 if (value >= (double) MagickULLConstant(~0))
950 return(MagickULLConstant(~0));
951 return((MagickSizeType) value);
954 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
968 Set Magick resource limits.
970 if (resource_semaphore == (SemaphoreInfo *) NULL)
971 resource_semaphore=AcquireSemaphoreInfo();
972 pagesize=GetMagickPageSize();
974 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
975 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
977 memory=(MagickSizeType) pages*pagesize;
978 if ((pagesize <= 0) || (pages <= 0))
979 memory=2048UL*1024UL*1024UL;
980 #if defined(PixelCacheThreshold)
981 memory=PixelCacheThreshold;
983 (void) SetMagickResourceLimit(AreaResource,2*memory);
984 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
985 if (limit != (char *) NULL)
987 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
988 limit=DestroyString(limit);
990 (void) SetMagickResourceLimit(MemoryResource,memory);
991 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
992 if (limit != (char *) NULL)
994 (void) SetMagickResourceLimit(MemoryResource,
995 StringToSizeType(limit,100.0));
996 limit=DestroyString(limit);
998 (void) SetMagickResourceLimit(MapResource,2*memory);
999 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1000 if (limit != (char *) NULL)
1002 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1003 limit=DestroyString(limit);
1005 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1006 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1007 if (limit != (char *) NULL)
1009 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1010 limit=DestroyString(limit);
1013 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1014 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1016 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1022 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1023 files=(ssize_t) resources.rlim_cur;
1026 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1028 files=(ssize_t) getdtablesize();
1032 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1034 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1035 if (limit != (char *) NULL)
1037 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1039 limit=DestroyString(limit);
1041 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1042 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1043 if (limit != (char *) NULL)
1045 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1047 limit=DestroyString(limit);
1049 (void) SetMagickResourceLimit(ThrottleResource,0);
1050 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1051 if (limit != (char *) NULL)
1053 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1055 limit=DestroyString(limit);
1057 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1058 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1059 if (limit != (char *) NULL)
1061 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1062 limit=DestroyString(limit);
1068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1072 + 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 %
1076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 % ResourceComponentTerminus() destroys the resource component.
1080 % The format of the ResourceComponentTerminus() method is:
1082 % ResourceComponentTerminus(void)
1085 MagickPrivate void ResourceComponentTerminus(void)
1087 if (resource_semaphore == (SemaphoreInfo *) NULL)
1088 resource_semaphore=AcquireSemaphoreInfo();
1089 LockSemaphoreInfo(resource_semaphore);
1090 if (temporary_resources != (SplayTreeInfo *) NULL)
1091 temporary_resources=DestroySplayTree(temporary_resources);
1092 if (random_info != (RandomInfo *) NULL)
1093 random_info=DestroyRandomInfo(random_info);
1094 UnlockSemaphoreInfo(resource_semaphore);
1095 RelinquishSemaphoreInfo(&resource_semaphore);
1099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103 % S e t M a g i c k R e s o u r c e L i m i t %
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % SetMagickResourceLimit() sets the limit for a particular resource.
1111 % The format of the SetMagickResourceLimit() method is:
1113 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1114 % const MagickSizeType limit)
1116 % A description of each parameter follows:
1118 % o type: the type of resource.
1120 % o limit: the maximum limit for the resource.
1124 static inline MagickSizeType MagickMin(const MagickSizeType x,
1125 const MagickSizeType y)
1132 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1133 const MagickSizeType limit)
1138 if (resource_semaphore == (SemaphoreInfo *) NULL)
1139 resource_semaphore=AcquireSemaphoreInfo();
1140 LockSemaphoreInfo(resource_semaphore);
1141 value=(char *) NULL;
1146 resource_info.area_limit=limit;
1147 value=GetPolicyValue("area");
1148 if (value != (char *) NULL)
1149 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1152 case MemoryResource:
1154 resource_info.memory_limit=limit;
1155 value=GetPolicyValue("memory");
1156 if (value != (char *) NULL)
1157 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1163 resource_info.map_limit=limit;
1164 value=GetPolicyValue("map");
1165 if (value != (char *) NULL)
1166 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1171 resource_info.disk_limit=limit;
1172 value=GetPolicyValue("disk");
1173 if (value != (char *) NULL)
1174 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1179 resource_info.file_limit=limit;
1180 value=GetPolicyValue("file");
1181 if (value != (char *) NULL)
1182 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1185 case ThreadResource:
1187 resource_info.thread_limit=limit;
1188 value=GetPolicyValue("thread");
1189 if (value != (char *) NULL)
1190 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1192 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1193 resource_info.thread_limit=GetOpenMPMaximumThreads();
1196 case ThrottleResource:
1198 resource_info.throttle_limit=limit;
1199 value=GetPolicyValue("throttle");
1200 if (value != (char *) NULL)
1201 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1203 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1204 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1209 resource_info.time_limit=limit;
1210 value=GetPolicyValue("time");
1211 if (value != (char *) NULL)
1212 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1218 if (value != (char *) NULL)
1219 value=DestroyString(value);
1220 UnlockSemaphoreInfo(resource_semaphore);