blob: 8d926786443fd10a1488436bd53824c6b9517acc [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% %
cristydf1cc5f2009-10-19 16:02:33 +0000268+ A s y n c h r o n o u s D e s t r o y R e s o u r c e C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000269% %
270% %
271% %
272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273%
cristydf1cc5f2009-10-19 16:02:33 +0000274% AsynchronousDestroyResourceComponent() destroys the resource environment.
275% It differs from DestroyResourceComponent() in that it can be called from a
cristy3ed852e2009-09-05 21:47:34 +0000276% asynchronous signal handler.
277%
cristydf1cc5f2009-10-19 16:02:33 +0000278% The format of the DestroyResourceComponent() method is:
cristy3ed852e2009-09-05 21:47:34 +0000279%
cristydf1cc5f2009-10-19 16:02:33 +0000280% DestroyResourceComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000281%
282*/
cristydf1cc5f2009-10-19 16:02:33 +0000283MagickExport void AsynchronousDestroyResourceComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000284{
285 const char
286 *path;
287
288 if (temporary_resources == (SplayTreeInfo *) NULL)
289 return;
290 /*
291 Remove any lingering temporary files.
292 */
293 ResetSplayTreeIterator(temporary_resources);
294 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
295 while (path != (const char *) NULL)
296 {
297 (void) remove(path);
298 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
299 }
300}
301
302/*
303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304% %
305% %
306% %
307% A c q u i r e U n i q u e F i l e R e s o u r c e %
308% %
309% %
310% %
311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312%
313% AcquireUniqueFileResource() returns a unique file name, and returns a file
314% descriptor for the file open for reading and writing.
315%
316% The format of the AcquireUniqueFileResource() method is:
317%
318% int AcquireUniqueFileResource(char *path)
319%
320% A description of each parameter follows:
321%
322% o path: Specifies a pointer to an array of characters. The unique path
323% name is returned in this array.
324%
325*/
326
327static void *DestroyTemporaryResources(void *temporary_resource)
328{
329 (void) remove((char *) temporary_resource);
330 return((void *) NULL);
331}
332
333static MagickBooleanType GetPathTemplate(char *path)
334{
335 char
336 *directory;
337
338 ExceptionInfo
339 *exception;
340
341 MagickBooleanType
342 status;
343
344 register char
345 *p;
346
347 struct stat
348 attributes;
349
350 (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent);
351 exception=AcquireExceptionInfo();
352 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
353 exception);
354 exception=DestroyExceptionInfo(exception);
355 if (directory == (char *) NULL)
356 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
357 if (directory == (char *) NULL)
358 directory=GetEnvironmentValue("MAGICK_TMPDIR");
359 if (directory == (char *) NULL)
360 directory=GetPolicyValue("temporary-path");
361 if (directory == (char *) NULL)
362 directory=GetEnvironmentValue("TMPDIR");
363#if defined(__WINDOWS__) || defined(__OS2__)
364 if (directory == (char *) NULL)
365 directory=GetEnvironmentValue("TMP");
366 if (directory == (char *) NULL)
367 directory=GetEnvironmentValue("TEMP");
368#endif
369#if defined(__VMS)
370 if (directory == (char *) NULL)
371 directory=GetEnvironmentValue("MTMPDIR");
372#endif
373#if defined(P_tmpdir)
374 if (directory == (char *) NULL)
375 directory=ConstantString(P_tmpdir);
376#endif
377 if (directory == (char *) NULL)
378 return(MagickTrue);
379 if (strlen(directory) > (MaxTextExtent-15))
380 {
381 directory=DestroyString(directory);
382 return(MagickTrue);
383 }
384 status=GetPathAttributes(directory,&attributes);
385 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
386 {
387 directory=DestroyString(directory);
388 return(MagickTrue);
389 }
390 if (directory[strlen(directory)-1] == *DirectorySeparator)
391 (void) FormatMagickString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory);
392 else
393 (void) FormatMagickString(path,MaxTextExtent,"%s%smagick-XXXXXXXX",
394 directory,DirectorySeparator);
395 directory=DestroyString(directory);
396 if (*DirectorySeparator != '/')
397 for (p=path; *p != '\0'; p++)
398 if (*p == *DirectorySeparator)
399 *p='/';
400 return(MagickTrue);
401}
402
403MagickExport int AcquireUniqueFileResource(char *path)
404{
405#if !defined(O_NOFOLLOW)
406#define O_NOFOLLOW 0
407#endif
408#if !defined(TMP_MAX)
409# define TMP_MAX 238328
410#endif
411
412 char
413 *resource;
414
415 int
416 c,
417 file;
418
419 register char
420 *p;
421
422 register long
423 i;
424
425 static const char
426 portable_filename[65] =
427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
428
429 StringInfo
430 *key;
431
432 unsigned char
433 *datum;
434
435 assert(path != (char *) NULL);
436 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
437 if (random_info == (RandomInfo *) NULL)
438 random_info=AcquireRandomInfo();
439 file=(-1);
440 for (i=0; i < TMP_MAX; i++)
441 {
442 /*
443 Get temporary pathname.
444 */
445 (void) GetPathTemplate(path);
446#if defined(MAGICKCORE_HAVE_MKSTEMP)
447 file=mkstemp(path);
448#if defined(__OS2__)
449 setmode(file,O_BINARY);
450#endif
451 if (file != -1)
452 break;
453#endif
454 key=GetRandomKey(random_info,8);
455 p=path+strlen(path)-8;
456 datum=GetStringInfoDatum(key);
457 for (i=0; i < 8; i++)
458 {
459 c=(int) (datum[i] & 0x3f);
460 *p++=portable_filename[c];
461 }
462 key=DestroyStringInfo(key);
463 file=open(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE);
464 if ((file > 0) || (errno != EEXIST))
465 break;
466 }
467 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
468 if (file == -1)
469 return(file);
470 AcquireSemaphoreInfo(&resource_semaphore);
471 if (temporary_resources == (SplayTreeInfo *) NULL)
472 temporary_resources=NewSplayTree(CompareSplayTreeString,
473 RelinquishMagickMemory,DestroyTemporaryResources);
474 RelinquishSemaphoreInfo(resource_semaphore);
475 resource=ConstantString(path);
476 (void) AddValueToSplayTree(temporary_resources,resource,resource);
477 return(file);
478}
479
480/*
481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482% %
483% %
484% %
cristydf1cc5f2009-10-19 16:02:33 +0000485+ D e s t r o y R e s o u r c e C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000486% %
487% %
488% %
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%
cristydf1cc5f2009-10-19 16:02:33 +0000491% DestroyResourceComponent() destroys the resource component.
cristy3ed852e2009-09-05 21:47:34 +0000492%
cristydf1cc5f2009-10-19 16:02:33 +0000493% The format of the DestroyResourceComponent() method is:
cristy3ed852e2009-09-05 21:47:34 +0000494%
cristydf1cc5f2009-10-19 16:02:33 +0000495% DestroyResourceComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000496%
497*/
cristydf1cc5f2009-10-19 16:02:33 +0000498MagickExport void DestroyResourceComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000499{
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% %
cristydf1cc5f2009-10-19 16:02:33 +0000660+ I n s t a n t i a t e R e s o u r c e C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000661% %
662% %
663% %
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%
cristydf1cc5f2009-10-19 16:02:33 +0000666% InstantiateResourcesComponent() instantiates the resource component.
cristy3ed852e2009-09-05 21:47:34 +0000667%
cristydf1cc5f2009-10-19 16:02:33 +0000668% The format of the InstantiateResourcesComponent method is:
cristy3ed852e2009-09-05 21:47:34 +0000669%
cristydf1cc5f2009-10-19 16:02:33 +0000670% MagickBooleanType InstantiateResourcesComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000671%
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
cristydf1cc5f2009-10-19 16:02:33 +0000694MagickExport MagickBooleanType InstantiateResourcesComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000695{
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 */
cristy41c3c772009-10-19 02:17:37 +0000710 AcquireSemaphoreInfo(&resource_semaphore);
cristy688f07b2009-09-27 15:19:13 +0000711 pagesize=GetMagickPageSize();
cristy3ed852e2009-09-05 21:47:34 +0000712 pages=(-1);
713#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
714 pages=sysconf(_SC_PHYS_PAGES);
715#endif
716 memory=(MagickSizeType) pages*pagesize;
717 if ((pagesize <= 0) || (pages <= 0))
718 memory=2048UL*1024UL*1024UL;
719#if defined(PixelCacheThreshold)
720 memory=PixelCacheThreshold;
721#endif
722 (void) SetMagickResourceLimit(AreaResource,2UL*memory);
723 (void) SetMagickResourceLimit(MemoryResource,3UL*memory/2UL);
724 (void) SetMagickResourceLimit(MapResource,4UL*memory);
725 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
726 if (limit == (char *) NULL)
727 limit=GetPolicyValue("area");
728 if (limit != (char *) NULL)
729 {
730 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
731 limit=DestroyString(limit);
732 }
733 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
734 if (limit == (char *) NULL)
735 limit=GetPolicyValue("memory");
736 if (limit != (char *) NULL)
737 {
738 (void) SetMagickResourceLimit(MemoryResource,
739 StringToSizeType(limit,100.0));
740 limit=DestroyString(limit);
741 }
742 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
743 if (limit == (char *) NULL)
744 limit=GetPolicyValue("map");
745 if (limit != (char *) NULL)
746 {
747 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
748 limit=DestroyString(limit);
749 }
750 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
751 if (limit == (char *) NULL)
752 limit=GetPolicyValue("disk");
753 if (limit != (char *) NULL)
754 {
755 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
756 limit=DestroyString(limit);
757 }
758 files=(-1);
759#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
760 files=sysconf(_SC_OPEN_MAX);
cristy3ed852e2009-09-05 21:47:34 +0000761#endif
cristy56489a52009-09-09 03:13:52 +0000762#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
763 if (files < 0)
764 {
765 struct rlimit
766 resources;
767
768 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
769 files=resources.rlim_cur;
770 }
771#endif
772#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
773 if (files < 0)
774 files=getdtablesize();
775#endif
776 if (files < 0)
777 files=64;
cristy3ed852e2009-09-05 21:47:34 +0000778 (void) SetMagickResourceLimit(FileResource,MagickMax((unsigned long)
779 (3*files/4),64));
780 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
781 if (limit == (char *) NULL)
782 limit=GetPolicyValue("file");
783 if (limit != (char *) NULL)
784 {
785 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
786 limit=DestroyString(limit);
787 }
788 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
789 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
790 if (limit == (char *) NULL)
791 limit=GetPolicyValue("thread");
792 if (limit != (char *) NULL)
793 {
794 SetOpenMPMaximumThreads((unsigned long) atol(limit));
795 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
796 100.0));
797 limit=DestroyString(limit);
798 }
799 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
800 if (limit == (char *) NULL)
801 limit=GetPolicyValue("time");
802 if (limit != (char *) NULL)
803 {
804 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
805 limit=DestroyString(limit);
806 }
cristy41c3c772009-10-19 02:17:37 +0000807 RelinquishSemaphoreInfo(resource_semaphore);
808 return(MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +0000809}
810
811/*
812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813% %
814% %
815% %
816% L i s t M a g i c k R e s o u r c e I n f o %
817% %
818% %
819% %
820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821%
822% ListMagickResourceInfo() lists the resource info to a file.
823%
824% The format of the ListMagickResourceInfo method is:
825%
826% MagickBooleanType ListMagickResourceInfo(FILE *file,
827% ExceptionInfo *exception)
828%
829% A description of each parameter follows.
830%
831% o file: An pointer to a FILE.
832%
833% o exception: return any errors or warnings in this structure.
834%
835*/
836MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
837 ExceptionInfo *magick_unused(exception))
838{
839 char
840 area_limit[MaxTextExtent],
841 disk_limit[MaxTextExtent],
842 map_limit[MaxTextExtent],
843 memory_limit[MaxTextExtent],
844 time_limit[MaxTextExtent];
845
846 if (file == (const FILE *) NULL)
847 file=stdout;
848 AcquireSemaphoreInfo(&resource_semaphore);
849 (void) FormatMagickSize(resource_info.area_limit,area_limit);
850 (void) FormatMagickSize(resource_info.memory_limit,memory_limit);
851 (void) FormatMagickSize(resource_info.map_limit,map_limit);
852 (void) FormatMagickSize(resource_info.disk_limit,disk_limit);
853 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
854 if (resource_info.time_limit != MagickResourceInfinity)
855 (void) FormatMagickString(time_limit,MaxTextExtent,"%lu",(unsigned long)
856 resource_info.time_limit);
cristy9bf9da32009-09-27 16:48:34 +0000857 (void) fprintf(file,"File Area Memory Map"
858 " Disk Thread Time\n");
859 (void) fprintf(file,"------------------------------------------------------"
860 "------------------\n");
861 (void) fprintf(file,"%4lu %10s %10s %10s %10s %6lu %10s\n",
862 (unsigned long) resource_info.file_limit,area_limit,memory_limit,map_limit,
863 disk_limit,(unsigned long) resource_info.thread_limit,time_limit);
cristy3ed852e2009-09-05 21:47:34 +0000864 (void) fflush(file);
865 RelinquishSemaphoreInfo(resource_semaphore);
866 return(MagickTrue);
867}
868
869/*
870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871% %
872% %
873% %
874% R e l i n q u i s h M a g i c k R e s o u r c e %
875% %
876% %
877% %
878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879%
880% RelinquishMagickResource() relinquishes resources of the specified type.
881%
882% The format of the RelinquishMagickResource() method is:
883%
884% void RelinquishMagickResource(const ResourceType type,
885% const MagickSizeType size)
886%
887% A description of each parameter follows:
888%
889% o type: the type of resource.
890%
891% o size: the size of the resource.
892%
893*/
894MagickExport void RelinquishMagickResource(const ResourceType type,
895 const MagickSizeType size)
896{
897 char
898 resource_current[MaxTextExtent],
899 resource_limit[MaxTextExtent],
900 resource_request[MaxTextExtent];
901
902 (void) FormatMagickSize(size,resource_request);
903 AcquireSemaphoreInfo(&resource_semaphore);
904 switch (type)
905 {
906 case AreaResource:
907 {
908 resource_info.area=(MagickOffsetType) size;
909 (void) FormatMagickSize((MagickSizeType) resource_info.area,
910 resource_current);
911 (void) FormatMagickSize(resource_info.area_limit,resource_limit);
912 break;
913 }
914 case MemoryResource:
915 {
916 resource_info.memory-=size;
917 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
918 resource_current);
919 (void) FormatMagickSize(resource_info.memory_limit,resource_limit);
920 break;
921 }
922 case MapResource:
923 {
924 resource_info.map-=size;
925 (void) FormatMagickSize((MagickSizeType) resource_info.map,
926 resource_current);
927 (void) FormatMagickSize(resource_info.map_limit,resource_limit);
928 break;
929 }
930 case DiskResource:
931 {
932 resource_info.disk-=size;
933 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
934 resource_current);
935 (void) FormatMagickSize(resource_info.disk_limit,resource_limit);
936 break;
937 }
938 case FileResource:
939 {
940 resource_info.file-=size;
941 (void) FormatMagickSize((MagickSizeType) resource_info.file,
942 resource_current);
943 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
944 resource_limit);
945 break;
946 }
947 case ThreadResource:
948 {
949 resource_info.thread-=size;
950 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
951 resource_current);
952 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
953 resource_limit);
954 break;
955 }
956 case TimeResource:
957 {
958 resource_info.time-=size;
959 (void) FormatMagickSize((MagickSizeType) resource_info.time,
960 resource_current);
961 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
962 resource_limit);
963 break;
964 }
965 default:
966 break;
967 }
968 RelinquishSemaphoreInfo(resource_semaphore);
969 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
970 MagickOptionToMnemonic(MagickResourceOptions,(long) type),resource_request,
971 resource_current,resource_limit);
972}
973
974/*
975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976% %
977% %
978% %
979% 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 %
980% %
981% %
982% %
983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984%
985% RelinquishUniqueFileResource() relinquishes a unique file resource.
986%
987% The format of the RelinquishUniqueFileResource() method is:
988%
989% MagickBooleanType RelinquishUniqueFileResource(const char *path)
990%
991% A description of each parameter follows:
992%
993% o name: the name of the temporary resource.
994%
995*/
996MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
997{
998 char
999 cache_path[MaxTextExtent];
1000
1001 assert(path != (const char *) NULL);
1002 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1003 if (temporary_resources != (SplayTreeInfo *) NULL)
1004 {
1005 register char
1006 *p;
1007
1008 ResetSplayTreeIterator(temporary_resources);
1009 p=(char *) GetNextKeyInSplayTree(temporary_resources);
1010 while (p != (char *) NULL)
1011 {
1012 if (LocaleCompare(p,path) == 0)
1013 break;
1014 p=(char *) GetNextKeyInSplayTree(temporary_resources);
1015 }
1016 if (p != (char *) NULL)
1017 (void) DeleteNodeFromSplayTree(temporary_resources,p);
1018 }
1019 (void) CopyMagickString(cache_path,path,MaxTextExtent);
1020 AppendImageFormat("cache",cache_path);
1021 (void) remove(cache_path);
1022 return(remove(path) == 0 ? MagickTrue : MagickFalse);
1023}
1024
1025/*
1026%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1027% %
1028% %
1029% %
1030% S e t M a g i c k R e s o u r c e L i m i t %
1031% %
1032% %
1033% %
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035%
1036% SetMagickResourceLimit() sets the limit for a particular resource.
1037%
1038% The format of the SetMagickResourceLimit() method is:
1039%
1040% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1041% const MagickSizeType limit)
1042%
1043% A description of each parameter follows:
1044%
1045% o type: the type of resource.
1046%
1047% o limit: the maximum limit for the resource.
1048%
1049*/
1050MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1051 const MagickSizeType limit)
1052{
1053 AcquireSemaphoreInfo(&resource_semaphore);
1054 switch (type)
1055 {
1056 case AreaResource:
1057 {
1058 resource_info.area_limit=limit;
1059 break;
1060 }
1061 case MemoryResource:
1062 {
1063 resource_info.memory_limit=limit;
1064 break;
1065 }
1066 case MapResource:
1067 {
1068 resource_info.map_limit=limit;
1069 break;
1070 }
1071 case DiskResource:
1072 {
1073 resource_info.disk_limit=limit;
1074 break;
1075 }
1076 case FileResource:
1077 {
1078 resource_info.file_limit=limit;
1079 break;
1080 }
1081 case ThreadResource:
1082 {
1083 SetOpenMPMaximumThreads((unsigned long) limit);
1084 resource_info.thread_limit=GetOpenMPMaximumThreads();
1085 break;
1086 }
1087 case TimeResource:
1088 {
1089 resource_info.time_limit=limit;
1090 break;
1091 }
1092 default:
1093 break;
1094 }
1095 RelinquishSemaphoreInfo(resource_semaphore);
1096 return(MagickTrue);
1097}