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/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), /* initial area */
103 MagickULLConstant(0), /* initial memory */
104 MagickULLConstant(0), /* initial map */
105 MagickULLConstant(0), /* initial disk */
106 MagickULLConstant(0), /* initial file */
107 MagickULLConstant(0), /* initial thread */
108 MagickULLConstant(0), /* initial throttle */
109 MagickULLConstant(0), /* initial time */
110 MagickULLConstant(3072)*1024*1024, /* area limit */
111 MagickULLConstant(1536)*1024*1024, /* memory limit */
112 MagickULLConstant(3072)*1024*1024, /* map limit */
113 MagickResourceInfinity, /* disk limit */
114 MagickULLConstant(768), /* file limit */
115 MagickULLConstant(1), /* thread limit */
116 MagickULLConstant(0), /* throttle limit */
117 MagickResourceInfinity /* time limit */
121 *resource_semaphore = (SemaphoreInfo *) NULL;
124 *temporary_resources = (SplayTreeInfo *) NULL;
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 % A c q u i r e M a g i c k R e s o u r c e %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 % AcquireMagickResource() acquires resources of the specified type.
138 % MagickFalse is returned if the specified resource is exhausted otherwise
141 % The format of the AcquireMagickResource() method is:
143 % MagickBooleanType AcquireMagickResource(const ResourceType type,
144 % const MagickSizeType size)
146 % A description of each parameter follows:
148 % o type: the type of resource.
150 % o size: the number of bytes needed from for this resource.
153 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
154 const MagickSizeType size)
157 resource_current[MaxTextExtent],
158 resource_limit[MaxTextExtent],
159 resource_request[MaxTextExtent];
168 (void) FormatMagickSize(size,MagickFalse,resource_request);
169 if (resource_semaphore == (SemaphoreInfo *) NULL)
170 AcquireSemaphoreInfo(&resource_semaphore);
171 LockSemaphoreInfo(resource_semaphore);
176 resource_info.area=(MagickOffsetType) size;
177 limit=resource_info.area_limit;
178 status=(resource_info.area_limit == MagickResourceInfinity) ||
179 (size < limit) ? MagickTrue : MagickFalse;
180 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
182 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
188 resource_info.memory+=size;
189 limit=resource_info.memory_limit;
190 status=(resource_info.memory_limit == MagickResourceInfinity) ||
191 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
193 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
195 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
201 resource_info.map+=size;
202 limit=resource_info.map_limit;
203 status=(resource_info.map_limit == MagickResourceInfinity) ||
204 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
205 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
207 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
213 resource_info.disk+=size;
214 limit=resource_info.disk_limit;
215 status=(resource_info.disk_limit == MagickResourceInfinity) ||
216 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
218 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
220 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
226 resource_info.file+=size;
227 limit=resource_info.file_limit;
228 status=(resource_info.file_limit == MagickResourceInfinity) ||
229 ((MagickSizeType) resource_info.file < limit) ?
230 MagickTrue : MagickFalse;
231 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
233 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
234 MagickFalse,resource_limit);
239 limit=resource_info.thread_limit;
240 status=(resource_info.thread_limit == MagickResourceInfinity) ||
241 ((MagickSizeType) resource_info.thread < limit) ?
242 MagickTrue : MagickFalse;
243 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
245 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
246 MagickFalse,resource_limit);
249 case ThrottleResource:
251 limit=resource_info.throttle_limit;
252 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
253 ((MagickSizeType) resource_info.throttle < limit) ?
254 MagickTrue : MagickFalse;
255 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
256 MagickFalse,resource_current);
257 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
258 MagickFalse,resource_limit);
263 resource_info.time+=size;
264 limit=resource_info.time_limit;
265 status=(resource_info.time_limit == MagickResourceInfinity) ||
266 ((MagickSizeType) resource_info.time < limit) ?
267 MagickTrue : MagickFalse;
268 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
270 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
271 MagickFalse,resource_limit);
277 UnlockSemaphoreInfo(resource_semaphore);
278 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
279 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
280 resource_request,resource_current,resource_limit);
285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 + 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 %
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295 % AsynchronousResourceComponentTerminus() destroys the resource environment.
296 % It differs from ResourceComponentTerminus() in that it can be called from a
297 % asynchronous signal handler.
299 % The format of the ResourceComponentTerminus() method is:
301 % ResourceComponentTerminus(void)
304 MagickPrivate void AsynchronousResourceComponentTerminus(void)
309 if (temporary_resources == (SplayTreeInfo *) NULL)
312 Remove any lingering temporary files.
314 ResetSplayTreeIterator(temporary_resources);
315 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
316 while (path != (const char *) NULL)
318 (void) ShredFile(path);
319 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 % 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 %
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % AcquireUniqueFileResource() returns a unique file name, and returns a file
335 % descriptor for the file open for reading and writing.
337 % The format of the AcquireUniqueFileResource() method is:
339 % int AcquireUniqueFileResource(char *path)
341 % A description of each parameter follows:
343 % o path: Specifies a pointer to an array of characters. The unique path
344 % name is returned in this array.
348 static void *DestroyTemporaryResources(void *temporary_resource)
350 (void) ShredFile((char *) temporary_resource);
351 temporary_resource=DestroyString((char *) temporary_resource);
352 return((void *) NULL);
355 MagickExport MagickBooleanType GetPathTemplate(char *path)
373 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
375 exception=AcquireExceptionInfo();
376 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
378 exception=DestroyExceptionInfo(exception);
379 if (directory == (char *) NULL)
380 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
381 if (directory == (char *) NULL)
382 directory=GetEnvironmentValue("MAGICK_TMPDIR");
383 if (directory == (char *) NULL)
384 directory=GetEnvironmentValue("TMPDIR");
385 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
386 if (directory == (char *) NULL)
387 directory=GetEnvironmentValue("TMP");
388 if (directory == (char *) NULL)
389 directory=GetEnvironmentValue("TEMP");
392 if (directory == (char *) NULL)
393 directory=GetEnvironmentValue("MTMPDIR");
395 #if defined(P_tmpdir)
396 if (directory == (char *) NULL)
397 directory=ConstantString(P_tmpdir);
399 if (directory == (char *) NULL)
401 value=GetPolicyValue("temporary-path");
402 if (value != (char *) NULL)
403 (void) CloneString(&directory,value);
404 if (strlen(directory) > (MaxTextExtent-25))
406 directory=DestroyString(directory);
409 status=GetPathAttributes(directory,&attributes);
410 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
412 directory=DestroyString(directory);
415 if (directory[strlen(directory)-1] == *DirectorySeparator)
416 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
417 directory,(double) getpid());
419 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-%.20gXXXXXXXXXXXX",
420 directory,DirectorySeparator,(double) getpid());
421 directory=DestroyString(directory);
422 if (*DirectorySeparator != '/')
423 for (p=path; *p != '\0'; p++)
424 if (*p == *DirectorySeparator)
429 MagickExport int AcquireUniqueFileResource(char *path)
431 #if !defined(O_NOFOLLOW)
434 #if !defined(TMP_MAX)
435 # define TMP_MAX 238328
449 portable_filename[65] =
450 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
458 assert(path != (char *) NULL);
459 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
460 if (random_info == (RandomInfo *) NULL)
461 random_info=AcquireRandomInfo();
463 for (i=0; i < (ssize_t) TMP_MAX; i++)
466 Get temporary pathname.
468 (void) GetPathTemplate(path);
469 key=GetRandomKey(random_info,6);
470 p=path+strlen(path)-12;
471 datum=GetStringInfoDatum(key);
472 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
474 c=(int) (datum[i] & 0x3f);
475 *p++=portable_filename[c];
477 key=DestroyStringInfo(key);
478 #if defined(MAGICKCORE_HAVE_MKSTEMP)
481 setmode(file,O_BINARY);
486 key=GetRandomKey(random_info,12);
487 p=path+strlen(path)-12;
488 datum=GetStringInfoDatum(key);
489 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
491 c=(int) (datum[i] & 0x3f);
492 *p++=portable_filename[c];
494 key=DestroyStringInfo(key);
495 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
497 if ((file >= 0) || (errno != EEXIST))
500 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
503 if (resource_semaphore == (SemaphoreInfo *) NULL)
504 AcquireSemaphoreInfo(&resource_semaphore);
505 LockSemaphoreInfo(resource_semaphore);
506 if (temporary_resources == (SplayTreeInfo *) NULL)
507 temporary_resources=NewSplayTree(CompareSplayTreeString,
508 DestroyTemporaryResources,(void *(*)(void *)) NULL);
509 UnlockSemaphoreInfo(resource_semaphore);
510 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
511 (const void *) NULL);
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 % G e t M a g i c k R e s o u r c e %
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 % GetMagickResource() returns the specified resource.
528 % The format of the GetMagickResource() method is:
530 % MagickSizeType GetMagickResource(const ResourceType type)
532 % A description of each parameter follows:
534 % o type: the type of resource.
537 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
543 LockSemaphoreInfo(resource_semaphore);
548 resource=(MagickSizeType) resource_info.area;
553 resource=(MagickSizeType) resource_info.memory;
558 resource=(MagickSizeType) resource_info.map;
563 resource=(MagickSizeType) resource_info.disk;
568 resource=(MagickSizeType) resource_info.file;
573 resource=(MagickSizeType) resource_info.thread;
576 case ThrottleResource:
578 resource=(MagickSizeType) resource_info.throttle;
583 resource=(MagickSizeType) resource_info.time;
589 UnlockSemaphoreInfo(resource_semaphore);
594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 % G e t M a g i c k R e s o u r c e L i m i t %
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 % GetMagickResourceLimit() returns the specified resource limit.
606 % The format of the GetMagickResourceLimit() method is:
608 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
610 % A description of each parameter follows:
612 % o type: the type of resource.
615 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
621 if (resource_semaphore == (SemaphoreInfo *) NULL)
622 AcquireSemaphoreInfo(&resource_semaphore);
623 LockSemaphoreInfo(resource_semaphore);
628 resource=resource_info.area_limit;
633 resource=resource_info.memory_limit;
638 resource=resource_info.map_limit;
643 resource=resource_info.disk_limit;
648 resource=resource_info.file_limit;
653 resource=resource_info.thread_limit;
656 case ThrottleResource:
658 resource=resource_info.throttle_limit;
663 resource=resource_info.time_limit;
669 UnlockSemaphoreInfo(resource_semaphore);
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 % L i s t M a g i c k R e s o u r c e I n f o %
682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 % ListMagickResourceInfo() lists the resource info to a file.
686 % The format of the ListMagickResourceInfo method is:
688 % MagickBooleanType ListMagickResourceInfo(FILE *file,
689 % ExceptionInfo *exception)
691 % A description of each parameter follows.
693 % o file: An pointer to a FILE.
695 % o exception: return any errors or warnings in this structure.
698 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
699 ExceptionInfo *magick_unused(exception))
702 area_limit[MaxTextExtent],
703 disk_limit[MaxTextExtent],
704 map_limit[MaxTextExtent],
705 memory_limit[MaxTextExtent],
706 time_limit[MaxTextExtent];
708 if (file == (const FILE *) NULL)
710 if (resource_semaphore == (SemaphoreInfo *) NULL)
711 AcquireSemaphoreInfo(&resource_semaphore);
712 LockSemaphoreInfo(resource_semaphore);
713 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
714 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
715 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
716 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
717 if (resource_info.disk_limit != MagickResourceInfinity)
718 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
719 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
720 if (resource_info.time_limit != MagickResourceInfinity)
721 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
722 ((MagickOffsetType) resource_info.time_limit));
723 (void) FormatLocaleFile(file," File Area Memory Map"
724 " Disk Thread Throttle Time\n");
725 (void) FormatLocaleFile(file,
726 "--------------------------------------------------------"
727 "------------------------\n");
728 (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %8g %8g %10s\n",
729 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
730 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
731 resource_info.thread_limit),(double) ((MagickOffsetType)
732 resource_info.throttle_limit),time_limit);
734 UnlockSemaphoreInfo(resource_semaphore);
739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
743 % R e l i n q u i s h M a g i c k R e s o u r c e %
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 % RelinquishMagickResource() relinquishes resources of the specified type.
751 % The format of the RelinquishMagickResource() method is:
753 % void RelinquishMagickResource(const ResourceType type,
754 % const MagickSizeType size)
756 % A description of each parameter follows:
758 % o type: the type of resource.
760 % o size: the size of the resource.
763 MagickExport void RelinquishMagickResource(const ResourceType type,
764 const MagickSizeType size)
767 resource_current[MaxTextExtent],
768 resource_limit[MaxTextExtent],
769 resource_request[MaxTextExtent];
771 (void) FormatMagickSize(size,MagickFalse,resource_request);
772 if (resource_semaphore == (SemaphoreInfo *) NULL)
773 AcquireSemaphoreInfo(&resource_semaphore);
774 LockSemaphoreInfo(resource_semaphore);
779 resource_info.area=(MagickOffsetType) size;
780 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
782 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
788 resource_info.memory-=size;
789 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
790 MagickTrue,resource_current);
791 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
797 resource_info.map-=size;
798 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
800 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
806 resource_info.disk-=size;
807 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
809 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
815 resource_info.file-=size;
816 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
818 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
819 MagickFalse,resource_limit);
824 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
826 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
827 MagickFalse,resource_limit);
830 case ThrottleResource:
832 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
833 MagickFalse,resource_current);
834 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
835 MagickFalse,resource_limit);
840 resource_info.time-=size;
841 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
843 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
844 MagickFalse,resource_limit);
850 UnlockSemaphoreInfo(resource_semaphore);
851 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
852 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
853 resource_request,resource_current,resource_limit);
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 % 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 %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867 % RelinquishUniqueFileResource() relinquishes a unique file resource.
869 % The format of the RelinquishUniqueFileResource() method is:
871 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
873 % A description of each parameter follows:
875 % o name: the name of the temporary resource.
878 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
881 cache_path[MaxTextExtent];
883 assert(path != (const char *) NULL);
884 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
885 if (temporary_resources != (SplayTreeInfo *) NULL)
890 ResetSplayTreeIterator(temporary_resources);
891 p=(char *) GetNextKeyInSplayTree(temporary_resources);
892 while (p != (char *) NULL)
894 if (LocaleCompare(p,path) == 0)
896 p=(char *) GetNextKeyInSplayTree(temporary_resources);
898 if (p != (char *) NULL)
899 (void) DeleteNodeFromSplayTree(temporary_resources,p);
901 (void) CopyMagickString(cache_path,path,MaxTextExtent);
902 AppendImageFormat("cache",cache_path);
903 (void) ShredFile(cache_path);
904 return(ShredFile(path));
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 + R e s o u r c e C o m p o n e n t G e n e s i s %
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918 % ResourceComponentGenesis() instantiates the resource component.
920 % The format of the ResourceComponentGenesis method is:
922 % MagickBooleanType ResourceComponentGenesis(void)
926 static inline size_t MagickMax(const size_t x,const size_t y)
933 static inline MagickSizeType StringToSizeType(const char *string,
934 const double interval)
939 value=SiPrefixToDoubleInterval(string,interval);
940 if (value >= (double) MagickULLConstant(~0))
941 return(MagickULLConstant(~0));
942 return((MagickSizeType) value);
945 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
959 Set Magick resource limits.
961 AcquireSemaphoreInfo(&resource_semaphore);
962 pagesize=GetMagickPageSize();
964 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
965 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
967 memory=(MagickSizeType) pages*pagesize;
968 if ((pagesize <= 0) || (pages <= 0))
969 memory=2048UL*1024UL*1024UL;
970 #if defined(PixelCacheThreshold)
971 memory=PixelCacheThreshold;
973 (void) SetMagickResourceLimit(AreaResource,2*memory);
974 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
975 if (limit != (char *) NULL)
977 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
978 limit=DestroyString(limit);
980 (void) SetMagickResourceLimit(MemoryResource,memory);
981 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
982 if (limit != (char *) NULL)
984 (void) SetMagickResourceLimit(MemoryResource,
985 StringToSizeType(limit,100.0));
986 limit=DestroyString(limit);
988 (void) SetMagickResourceLimit(MapResource,2*memory);
989 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
990 if (limit != (char *) NULL)
992 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
993 limit=DestroyString(limit);
995 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
996 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
997 if (limit != (char *) NULL)
999 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1000 limit=DestroyString(limit);
1003 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1004 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1006 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1012 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1013 files=(ssize_t) resources.rlim_cur;
1016 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1018 files=(ssize_t) getdtablesize();
1022 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1024 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1025 if (limit != (char *) NULL)
1027 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1029 limit=DestroyString(limit);
1031 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1032 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1033 if (limit != (char *) NULL)
1035 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1037 limit=DestroyString(limit);
1039 (void) SetMagickResourceLimit(ThrottleResource,0);
1040 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1041 if (limit != (char *) NULL)
1043 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1045 limit=DestroyString(limit);
1047 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1048 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1049 if (limit != (char *) NULL)
1051 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1052 limit=DestroyString(limit);
1058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 + 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 %
1066 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068 % ResourceComponentTerminus() destroys the resource component.
1070 % The format of the ResourceComponentTerminus() method is:
1072 % ResourceComponentTerminus(void)
1075 MagickPrivate void ResourceComponentTerminus(void)
1077 if (resource_semaphore == (SemaphoreInfo *) NULL)
1078 AcquireSemaphoreInfo(&resource_semaphore);
1079 LockSemaphoreInfo(resource_semaphore);
1080 if (temporary_resources != (SplayTreeInfo *) NULL)
1081 temporary_resources=DestroySplayTree(temporary_resources);
1082 if (random_info != (RandomInfo *) NULL)
1083 random_info=DestroyRandomInfo(random_info);
1084 UnlockSemaphoreInfo(resource_semaphore);
1085 DestroySemaphoreInfo(&resource_semaphore);
1089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093 % S e t M a g i c k R e s o u r c e L i m i t %
1097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099 % SetMagickResourceLimit() sets the limit for a particular resource.
1101 % The format of the SetMagickResourceLimit() method is:
1103 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1104 % const MagickSizeType limit)
1106 % A description of each parameter follows:
1108 % o type: the type of resource.
1110 % o limit: the maximum limit for the resource.
1114 static inline MagickSizeType MagickMin(const MagickSizeType x,
1115 const MagickSizeType y)
1122 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1123 const MagickSizeType limit)
1128 if (resource_semaphore == (SemaphoreInfo *) NULL)
1129 AcquireSemaphoreInfo(&resource_semaphore);
1130 LockSemaphoreInfo(resource_semaphore);
1131 value=(char *) NULL;
1136 resource_info.area_limit=limit;
1137 value=GetPolicyValue("area");
1138 if (value != (char *) NULL)
1139 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1142 case MemoryResource:
1144 resource_info.memory_limit=limit;
1145 value=GetPolicyValue("memory");
1146 if (value != (char *) NULL)
1147 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1153 resource_info.map_limit=limit;
1154 value=GetPolicyValue("map");
1155 if (value != (char *) NULL)
1156 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1161 resource_info.disk_limit=limit;
1162 value=GetPolicyValue("disk");
1163 if (value != (char *) NULL)
1164 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1169 resource_info.file_limit=limit;
1170 value=GetPolicyValue("file");
1171 if (value != (char *) NULL)
1172 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1175 case ThreadResource:
1177 resource_info.thread_limit=limit;
1178 value=GetPolicyValue("thread");
1179 if (value != (char *) NULL)
1180 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1182 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1183 resource_info.thread_limit=GetOpenMPMaximumThreads();
1186 case ThrottleResource:
1188 resource_info.throttle_limit=limit;
1189 value=GetPolicyValue("throttle");
1190 if (value != (char *) NULL)
1191 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1193 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1194 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1199 resource_info.time_limit=limit;
1200 value=GetPolicyValue("time");
1201 if (value != (char *) NULL)
1202 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1208 if (value != (char *) NULL)
1209 value=DestroyString(value);
1210 UnlockSemaphoreInfo(resource_semaphore);