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-2013 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/option.h"
52 #include "MagickCore/policy.h"
53 #include "MagickCore/random_.h"
54 #include "MagickCore/registry.h"
55 #include "MagickCore/resource_.h"
56 #include "MagickCore/resource-private.h"
57 #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"
65 #include "MagickCore/utility-private.h"
70 typedef struct _ResourceInfo
97 *random_info = (RandomInfo *) NULL;
102 MagickULLConstant(0),
103 MagickULLConstant(0),
104 MagickULLConstant(0),
105 MagickULLConstant(0),
106 MagickULLConstant(0),
107 MagickULLConstant(0),
108 MagickULLConstant(0),
109 MagickULLConstant(3072)*1024*1024,
110 MagickULLConstant(1536)*1024*1024,
111 MagickULLConstant(3072)*1024*1024,
112 MagickResourceInfinity,
113 MagickULLConstant(768),
114 MagickULLConstant(1),
115 MagickULLConstant(0),
116 MagickResourceInfinity
120 *resource_semaphore = (SemaphoreInfo *) NULL;
123 *temporary_resources = (SplayTreeInfo *) NULL;
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 % A c q u i r e M a g i c k R e s o u r c e %
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 % AcquireMagickResource() acquires resources of the specified type.
137 % MagickFalse is returned if the specified resource is exhausted otherwise
140 % The format of the AcquireMagickResource() method is:
142 % MagickBooleanType AcquireMagickResource(const ResourceType type,
143 % const MagickSizeType size)
145 % A description of each parameter follows:
147 % o type: the type of resource.
149 % o size: the number of bytes needed from for this resource.
152 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
153 const MagickSizeType size)
156 resource_current[MaxTextExtent],
157 resource_limit[MaxTextExtent],
158 resource_request[MaxTextExtent];
167 (void) FormatMagickSize(size,MagickFalse,resource_request);
168 if (resource_semaphore == (SemaphoreInfo *) NULL)
169 AcquireSemaphoreInfo(&resource_semaphore);
170 LockSemaphoreInfo(resource_semaphore);
175 resource_info.area=(MagickOffsetType) size;
176 limit=resource_info.area_limit;
177 status=(resource_info.area_limit == MagickResourceInfinity) ||
178 (size < limit) ? MagickTrue : MagickFalse;
179 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
181 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
187 resource_info.memory+=size;
188 limit=resource_info.memory_limit;
189 status=(resource_info.memory_limit == MagickResourceInfinity) ||
190 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
192 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
194 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
200 resource_info.map+=size;
201 limit=resource_info.map_limit;
202 status=(resource_info.map_limit == MagickResourceInfinity) ||
203 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
204 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
206 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
212 resource_info.disk+=size;
213 limit=resource_info.disk_limit;
214 status=(resource_info.disk_limit == MagickResourceInfinity) ||
215 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
217 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
219 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
225 resource_info.file+=size;
226 limit=resource_info.file_limit;
227 status=(resource_info.file_limit == MagickResourceInfinity) ||
228 ((MagickSizeType) resource_info.file < limit) ?
229 MagickTrue : MagickFalse;
230 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
232 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
233 MagickFalse,resource_limit);
238 limit=resource_info.thread_limit;
239 status=(resource_info.thread_limit == MagickResourceInfinity) ||
240 ((MagickSizeType) resource_info.thread < limit) ?
241 MagickTrue : MagickFalse;
242 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
244 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
245 MagickFalse,resource_limit);
248 case ThrottleResource:
250 limit=resource_info.throttle_limit;
251 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
252 ((MagickSizeType) resource_info.throttle < limit) ?
253 MagickTrue : MagickFalse;
254 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
255 MagickFalse,resource_current);
256 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
257 MagickFalse,resource_limit);
262 resource_info.time+=size;
263 limit=resource_info.time_limit;
264 status=(resource_info.time_limit == MagickResourceInfinity) ||
265 ((MagickSizeType) resource_info.time < limit) ?
266 MagickTrue : MagickFalse;
267 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
269 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
270 MagickFalse,resource_limit);
276 UnlockSemaphoreInfo(resource_semaphore);
277 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
278 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
279 resource_request,resource_current,resource_limit);
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 + 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 %
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294 % AsynchronousResourceComponentTerminus() destroys the resource environment.
295 % It differs from ResourceComponentTerminus() in that it can be called from a
296 % asynchronous signal handler.
298 % The format of the ResourceComponentTerminus() method is:
300 % ResourceComponentTerminus(void)
303 MagickPrivate void AsynchronousResourceComponentTerminus(void)
308 if (temporary_resources == (SplayTreeInfo *) NULL)
311 Remove any lingering temporary files.
313 ResetSplayTreeIterator(temporary_resources);
314 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
315 while (path != (const char *) NULL)
317 (void) remove_utf8(path);
318 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 % 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 %
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % AcquireUniqueFileResource() returns a unique file name, and returns a file
334 % descriptor for the file open for reading and writing.
336 % The format of the AcquireUniqueFileResource() method is:
338 % int AcquireUniqueFileResource(char *path)
340 % A description of each parameter follows:
342 % o path: Specifies a pointer to an array of characters. The unique path
343 % name is returned in this array.
347 static void *DestroyTemporaryResources(void *temporary_resource)
349 (void) remove_utf8((char *) temporary_resource);
350 temporary_resource=DestroyString((char *) temporary_resource);
351 return((void *) NULL);
354 MagickExport MagickBooleanType GetPathTemplate(char *path)
372 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
374 exception=AcquireExceptionInfo();
375 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
377 exception=DestroyExceptionInfo(exception);
378 if (directory == (char *) NULL)
379 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
380 if (directory == (char *) NULL)
381 directory=GetEnvironmentValue("MAGICK_TMPDIR");
382 if (directory == (char *) NULL)
383 directory=GetEnvironmentValue("TMPDIR");
384 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
385 if (directory == (char *) NULL)
386 directory=GetEnvironmentValue("TMP");
387 if (directory == (char *) NULL)
388 directory=GetEnvironmentValue("TEMP");
391 if (directory == (char *) NULL)
392 directory=GetEnvironmentValue("MTMPDIR");
394 #if defined(P_tmpdir)
395 if (directory == (char *) NULL)
396 directory=ConstantString(P_tmpdir);
398 if (directory == (char *) NULL)
400 value=GetPolicyValue("temporary-path");
401 if (value != (char *) NULL)
402 (void) CloneString(&directory,value);
403 if (strlen(directory) > (MaxTextExtent-25))
405 directory=DestroyString(directory);
408 status=GetPathAttributes(directory,&attributes);
409 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
411 directory=DestroyString(directory);
414 if (directory[strlen(directory)-1] == *DirectorySeparator)
415 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
416 directory,(double) getpid());
418 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-%.20gXXXXXXXXXXXX",
419 directory,DirectorySeparator,(double) getpid());
420 directory=DestroyString(directory);
421 if (*DirectorySeparator != '/')
422 for (p=path; *p != '\0'; p++)
423 if (*p == *DirectorySeparator)
428 MagickExport int AcquireUniqueFileResource(char *path)
430 #if !defined(O_NOFOLLOW)
433 #if !defined(TMP_MAX)
434 # define TMP_MAX 238328
448 portable_filename[65] =
449 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
457 assert(path != (char *) NULL);
458 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
459 if (random_info == (RandomInfo *) NULL)
460 random_info=AcquireRandomInfo();
462 for (i=0; i < (ssize_t) TMP_MAX; i++)
465 Get temporary pathname.
467 (void) GetPathTemplate(path);
468 key=GetRandomKey(random_info,6);
469 p=path+strlen(path)-12;
470 datum=GetStringInfoDatum(key);
471 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
473 c=(int) (datum[i] & 0x3f);
474 *p++=portable_filename[c];
476 key=DestroyStringInfo(key);
477 #if defined(MAGICKCORE_HAVE_MKSTEMP)
480 setmode(file,O_BINARY);
485 key=GetRandomKey(random_info,12);
486 p=path+strlen(path)-12;
487 datum=GetStringInfoDatum(key);
488 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
490 c=(int) (datum[i] & 0x3f);
491 *p++=portable_filename[c];
493 key=DestroyStringInfo(key);
494 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
496 if ((file >= 0) || (errno != EEXIST))
499 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
502 if (resource_semaphore == (SemaphoreInfo *) NULL)
503 AcquireSemaphoreInfo(&resource_semaphore);
504 LockSemaphoreInfo(resource_semaphore);
505 if (temporary_resources == (SplayTreeInfo *) NULL)
506 temporary_resources=NewSplayTree(CompareSplayTreeString,
507 DestroyTemporaryResources,(void *(*)(void *)) NULL);
508 UnlockSemaphoreInfo(resource_semaphore);
509 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
510 (const void *) NULL);
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 % G e t M a g i c k R e s o u r c e %
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525 % GetMagickResource() returns the specified resource.
527 % The format of the GetMagickResource() method is:
529 % MagickSizeType GetMagickResource(const ResourceType type)
531 % A description of each parameter follows:
533 % o type: the type of resource.
536 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
542 LockSemaphoreInfo(resource_semaphore);
547 resource=(MagickSizeType) resource_info.area;
552 resource=(MagickSizeType) resource_info.memory;
557 resource=(MagickSizeType) resource_info.map;
562 resource=(MagickSizeType) resource_info.disk;
567 resource=(MagickSizeType) resource_info.file;
572 resource=(MagickSizeType) resource_info.thread;
575 case ThrottleResource:
577 resource=(MagickSizeType) resource_info.throttle;
582 resource=(MagickSizeType) resource_info.time;
588 UnlockSemaphoreInfo(resource_semaphore);
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 % G e t M a g i c k R e s o u r c e L i m i t %
601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 % GetMagickResourceLimit() returns the specified resource limit.
605 % The format of the GetMagickResourceLimit() method is:
607 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
609 % A description of each parameter follows:
611 % o type: the type of resource.
614 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
620 if (resource_semaphore == (SemaphoreInfo *) NULL)
621 AcquireSemaphoreInfo(&resource_semaphore);
622 LockSemaphoreInfo(resource_semaphore);
627 resource=resource_info.area_limit;
632 resource=resource_info.memory_limit;
637 resource=resource_info.map_limit;
642 resource=resource_info.disk_limit;
647 resource=resource_info.file_limit;
652 resource=resource_info.thread_limit;
655 case ThrottleResource:
657 resource=resource_info.throttle_limit;
662 resource=resource_info.time_limit;
668 UnlockSemaphoreInfo(resource_semaphore);
673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677 % L i s t M a g i c k R e s o u r c e I n f o %
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 % ListMagickResourceInfo() lists the resource info to a file.
685 % The format of the ListMagickResourceInfo method is:
687 % MagickBooleanType ListMagickResourceInfo(FILE *file,
688 % ExceptionInfo *exception)
690 % A description of each parameter follows.
692 % o file: An pointer to a FILE.
694 % o exception: return any errors or warnings in this structure.
697 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
698 ExceptionInfo *magick_unused(exception))
701 area_limit[MaxTextExtent],
702 disk_limit[MaxTextExtent],
703 map_limit[MaxTextExtent],
704 memory_limit[MaxTextExtent],
705 time_limit[MaxTextExtent];
707 if (file == (const FILE *) NULL)
709 if (resource_semaphore == (SemaphoreInfo *) NULL)
710 AcquireSemaphoreInfo(&resource_semaphore);
711 LockSemaphoreInfo(resource_semaphore);
712 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
713 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
714 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
715 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
716 if (resource_info.disk_limit != MagickResourceInfinity)
717 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
718 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
719 if (resource_info.time_limit != MagickResourceInfinity)
720 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
721 ((MagickOffsetType) resource_info.time_limit));
722 (void) FormatLocaleFile(file," File Area Memory Map"
723 " Disk Thread Throttle Time\n");
724 (void) FormatLocaleFile(file,
725 "--------------------------------------------------------"
726 "------------------------\n");
727 (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %8g %8g %10s\n",
728 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
729 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
730 resource_info.thread_limit),(double) ((MagickOffsetType)
731 resource_info.throttle_limit),time_limit);
733 UnlockSemaphoreInfo(resource_semaphore);
738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
742 % R e l i n q u i s h M a g i c k R e s o u r c e %
746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
748 % RelinquishMagickResource() relinquishes resources of the specified type.
750 % The format of the RelinquishMagickResource() method is:
752 % void RelinquishMagickResource(const ResourceType type,
753 % const MagickSizeType size)
755 % A description of each parameter follows:
757 % o type: the type of resource.
759 % o size: the size of the resource.
762 MagickExport void RelinquishMagickResource(const ResourceType type,
763 const MagickSizeType size)
766 resource_current[MaxTextExtent],
767 resource_limit[MaxTextExtent],
768 resource_request[MaxTextExtent];
770 (void) FormatMagickSize(size,MagickFalse,resource_request);
771 if (resource_semaphore == (SemaphoreInfo *) NULL)
772 AcquireSemaphoreInfo(&resource_semaphore);
773 LockSemaphoreInfo(resource_semaphore);
778 resource_info.area=(MagickOffsetType) size;
779 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
781 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
787 resource_info.memory-=size;
788 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
789 MagickTrue,resource_current);
790 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
796 resource_info.map-=size;
797 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
799 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
805 resource_info.disk-=size;
806 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
808 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
814 resource_info.file-=size;
815 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
817 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
818 MagickFalse,resource_limit);
823 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
825 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
826 MagickFalse,resource_limit);
829 case ThrottleResource:
831 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
832 MagickFalse,resource_current);
833 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
834 MagickFalse,resource_limit);
839 resource_info.time-=size;
840 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
842 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
843 MagickFalse,resource_limit);
849 UnlockSemaphoreInfo(resource_semaphore);
850 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
851 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
852 resource_request,resource_current,resource_limit);
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860 % 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 %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 % RelinquishUniqueFileResource() relinquishes a unique file resource.
868 % The format of the RelinquishUniqueFileResource() method is:
870 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
872 % A description of each parameter follows:
874 % o name: the name of the temporary resource.
877 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
880 cache_path[MaxTextExtent];
882 assert(path != (const char *) NULL);
883 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
884 if (temporary_resources != (SplayTreeInfo *) NULL)
889 ResetSplayTreeIterator(temporary_resources);
890 p=(char *) GetNextKeyInSplayTree(temporary_resources);
891 while (p != (char *) NULL)
893 if (LocaleCompare(p,path) == 0)
895 p=(char *) GetNextKeyInSplayTree(temporary_resources);
897 if (p != (char *) NULL)
898 (void) DeleteNodeFromSplayTree(temporary_resources,p);
900 (void) CopyMagickString(cache_path,path,MaxTextExtent);
901 AppendImageFormat("cache",cache_path);
902 (void) remove_utf8(cache_path);
903 return(remove_utf8(path) == 0 ? MagickTrue : MagickFalse);
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911 + R e s o u r c e C o m p o n e n t G e n e s i s %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 % ResourceComponentGenesis() instantiates the resource component.
919 % The format of the ResourceComponentGenesis method is:
921 % MagickBooleanType ResourceComponentGenesis(void)
925 static inline size_t MagickMax(const size_t x,const size_t y)
932 static inline MagickSizeType StringToSizeType(const char *string,
933 const double interval)
938 value=SiPrefixToDoubleInterval(string,interval);
939 if (value >= (double) MagickULLConstant(~0))
940 return(MagickULLConstant(~0));
941 return((MagickSizeType) value);
944 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
958 Set Magick resource limits.
960 AcquireSemaphoreInfo(&resource_semaphore);
961 pagesize=GetMagickPageSize();
963 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
964 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
966 memory=(MagickSizeType) pages*pagesize;
967 if ((pagesize <= 0) || (pages <= 0))
968 memory=2048UL*1024UL*1024UL;
969 #if defined(PixelCacheThreshold)
970 memory=PixelCacheThreshold;
972 (void) SetMagickResourceLimit(AreaResource,2*memory);
973 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
974 if (limit != (char *) NULL)
976 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
977 limit=DestroyString(limit);
979 (void) SetMagickResourceLimit(MemoryResource,memory);
980 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
981 if (limit != (char *) NULL)
983 (void) SetMagickResourceLimit(MemoryResource,
984 StringToSizeType(limit,100.0));
985 limit=DestroyString(limit);
987 (void) SetMagickResourceLimit(MapResource,2*memory);
988 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
989 if (limit != (char *) NULL)
991 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
992 limit=DestroyString(limit);
994 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
995 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
996 if (limit != (char *) NULL)
998 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
999 limit=DestroyString(limit);
1002 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1003 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1005 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1011 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1012 files=(ssize_t) resources.rlim_cur;
1015 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1017 files=(ssize_t) getdtablesize();
1021 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1023 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1024 if (limit != (char *) NULL)
1026 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1028 limit=DestroyString(limit);
1030 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1031 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1032 if (limit != (char *) NULL)
1034 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1036 limit=DestroyString(limit);
1038 (void) SetMagickResourceLimit(ThrottleResource,0);
1039 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1040 if (limit != (char *) NULL)
1042 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1044 limit=DestroyString(limit);
1046 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1047 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1048 if (limit != (char *) NULL)
1050 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1051 limit=DestroyString(limit);
1057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 + 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 %
1065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067 % ResourceComponentTerminus() destroys the resource component.
1069 % The format of the ResourceComponentTerminus() method is:
1071 % ResourceComponentTerminus(void)
1074 MagickPrivate void ResourceComponentTerminus(void)
1076 if (resource_semaphore == (SemaphoreInfo *) NULL)
1077 AcquireSemaphoreInfo(&resource_semaphore);
1078 LockSemaphoreInfo(resource_semaphore);
1079 if (temporary_resources != (SplayTreeInfo *) NULL)
1080 temporary_resources=DestroySplayTree(temporary_resources);
1081 if (random_info != (RandomInfo *) NULL)
1082 random_info=DestroyRandomInfo(random_info);
1083 UnlockSemaphoreInfo(resource_semaphore);
1084 DestroySemaphoreInfo(&resource_semaphore);
1088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092 % S e t M a g i c k R e s o u r c e L i m i t %
1096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 % SetMagickResourceLimit() sets the limit for a particular resource.
1100 % The format of the SetMagickResourceLimit() method is:
1102 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1103 % const MagickSizeType limit)
1105 % A description of each parameter follows:
1107 % o type: the type of resource.
1109 % o limit: the maximum limit for the resource.
1113 static inline MagickSizeType MagickMin(const MagickSizeType x,
1114 const MagickSizeType y)
1121 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1122 const MagickSizeType limit)
1127 if (resource_semaphore == (SemaphoreInfo *) NULL)
1128 AcquireSemaphoreInfo(&resource_semaphore);
1129 LockSemaphoreInfo(resource_semaphore);
1130 value=(char *) NULL;
1135 resource_info.area_limit=limit;
1136 value=GetPolicyValue("area");
1137 if (value != (char *) NULL)
1138 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1141 case MemoryResource:
1143 resource_info.memory_limit=limit;
1144 value=GetPolicyValue("memory");
1145 if (value != (char *) NULL)
1146 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1152 resource_info.map_limit=limit;
1153 value=GetPolicyValue("map");
1154 if (value != (char *) NULL)
1155 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1160 resource_info.disk_limit=limit;
1161 value=GetPolicyValue("disk");
1162 if (value != (char *) NULL)
1163 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1168 resource_info.file_limit=limit;
1169 value=GetPolicyValue("file");
1170 if (value != (char *) NULL)
1171 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1174 case ThreadResource:
1176 resource_info.thread_limit=limit;
1177 value=GetPolicyValue("thread");
1178 if (value != (char *) NULL)
1179 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1181 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1182 resource_info.thread_limit=GetOpenMPMaximumThreads();
1185 case ThrottleResource:
1187 resource_info.throttle_limit=limit;
1188 value=GetPolicyValue("throttle");
1189 if (value != (char *) NULL)
1190 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1192 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1193 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1198 resource_info.time_limit=limit;
1199 value=GetPolicyValue("time");
1200 if (value != (char *) NULL)
1201 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1207 if (value != (char *) NULL)
1208 value=DestroyString(value);
1209 UnlockSemaphoreInfo(resource_semaphore);