|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE % 00007 % R R E SS O O U U R R C E % 00008 % RRRR EEE SSS O O U U RRRR C EEE % 00009 % R R E SS O O U U R R C E % 00010 % R R EEEEE SSSSS OOO UUU R R CCCC EEEEE % 00011 % % 00012 % % 00013 % Get/Set MagickCore Resources % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % September 2002 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 */ 00038 00039 /* 00040 Include declarations. 00041 */ 00042 #include "MagickCore/studio.h" 00043 #include "MagickCore/cache.h" 00044 #include "MagickCore/configure.h" 00045 #include "MagickCore/exception.h" 00046 #include "MagickCore/exception-private.h" 00047 #include "MagickCore/hashmap.h" 00048 #include "MagickCore/log.h" 00049 #include "MagickCore/image.h" 00050 #include "MagickCore/memory_.h" 00051 #include "MagickCore/option.h" 00052 #include "MagickCore/policy.h" 00053 #include "MagickCore/random_.h" 00054 #include "MagickCore/registry.h" 00055 #include "MagickCore/resource_.h" 00056 #include "MagickCore/resource-private.h" 00057 #include "MagickCore/semaphore.h" 00058 #include "MagickCore/signature-private.h" 00059 #include "MagickCore/string_.h" 00060 #include "MagickCore/string-private.h" 00061 #include "MagickCore/splay-tree.h" 00062 #include "MagickCore/thread-private.h" 00063 #include "MagickCore/token.h" 00064 #include "MagickCore/utility.h" 00065 #include "MagickCore/utility-private.h" 00066 00067 /* 00068 Typedef declarations. 00069 */ 00070 typedef struct _ResourceInfo 00071 { 00072 MagickOffsetType 00073 area, 00074 memory, 00075 map, 00076 disk, 00077 file, 00078 thread, 00079 time; 00080 00081 MagickSizeType 00082 area_limit, 00083 memory_limit, 00084 map_limit, 00085 disk_limit, 00086 file_limit, 00087 thread_limit, 00088 time_limit; 00089 } ResourceInfo; 00090 00091 /* 00092 Global declarations. 00093 */ 00094 static RandomInfo 00095 *random_info = (RandomInfo *) NULL; 00096 00097 static ResourceInfo 00098 resource_info = 00099 { 00100 MagickULLConstant(0), 00101 MagickULLConstant(0), 00102 MagickULLConstant(0), 00103 MagickULLConstant(0), 00104 MagickULLConstant(0), 00105 MagickULLConstant(0), 00106 MagickULLConstant(0), 00107 MagickULLConstant(3072)*1024*1024, 00108 MagickULLConstant(1536)*1024*1024, 00109 MagickULLConstant(3072)*1024*1024, 00110 MagickResourceInfinity, 00111 MagickULLConstant(768), 00112 MagickULLConstant(4), 00113 MagickResourceInfinity 00114 }; 00115 00116 static SemaphoreInfo 00117 *resource_semaphore = (SemaphoreInfo *) NULL; 00118 00119 static SplayTreeInfo 00120 *temporary_resources = (SplayTreeInfo *) NULL; 00121 00122 /* 00123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00124 % % 00125 % % 00126 % % 00127 % A c q u i r e M a g i c k R e s o u r c e % 00128 % % 00129 % % 00130 % % 00131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00132 % 00133 % AcquireMagickResource() acquires resources of the specified type. 00134 % MagickFalse is returned if the specified resource is exhausted otherwise 00135 % MagickTrue. 00136 % 00137 % The format of the AcquireMagickResource() method is: 00138 % 00139 % MagickBooleanType AcquireMagickResource(const ResourceType type, 00140 % const MagickSizeType size) 00141 % 00142 % A description of each parameter follows: 00143 % 00144 % o type: the type of resource. 00145 % 00146 % o size: the number of bytes needed from for this resource. 00147 % 00148 */ 00149 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type, 00150 const MagickSizeType size) 00151 { 00152 char 00153 resource_current[MaxTextExtent], 00154 resource_limit[MaxTextExtent], 00155 resource_request[MaxTextExtent]; 00156 00157 MagickBooleanType 00158 status; 00159 00160 MagickSizeType 00161 limit; 00162 00163 status=MagickFalse; 00164 (void) FormatMagickSize(size,MagickFalse,resource_request); 00165 if (resource_semaphore == (SemaphoreInfo *) NULL) 00166 AcquireSemaphoreInfo(&resource_semaphore); 00167 LockSemaphoreInfo(resource_semaphore); 00168 switch (type) 00169 { 00170 case AreaResource: 00171 { 00172 resource_info.area=(MagickOffsetType) size; 00173 limit=resource_info.area_limit; 00174 status=(resource_info.area_limit == MagickResourceInfinity) || 00175 (size < limit) ? MagickTrue : MagickFalse; 00176 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse, 00177 resource_current); 00178 (void) FormatMagickSize(resource_info.area_limit,MagickFalse, 00179 resource_limit); 00180 break; 00181 } 00182 case MemoryResource: 00183 { 00184 resource_info.memory+=size; 00185 limit=resource_info.memory_limit; 00186 status=(resource_info.memory_limit == MagickResourceInfinity) || 00187 ((MagickSizeType) resource_info.memory < limit) ? 00188 MagickTrue : MagickFalse; 00189 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue, 00190 resource_current); 00191 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue, 00192 resource_limit); 00193 break; 00194 } 00195 case MapResource: 00196 { 00197 resource_info.map+=size; 00198 limit=resource_info.map_limit; 00199 status=(resource_info.map_limit == MagickResourceInfinity) || 00200 ((MagickSizeType) resource_info.map < limit) ? 00201 MagickTrue : MagickFalse; 00202 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue, 00203 resource_current); 00204 (void) FormatMagickSize(resource_info.map_limit,MagickTrue, 00205 resource_limit); 00206 break; 00207 } 00208 case DiskResource: 00209 { 00210 resource_info.disk+=size; 00211 limit=resource_info.disk_limit; 00212 status=(resource_info.disk_limit == MagickResourceInfinity) || 00213 ((MagickSizeType) resource_info.disk < limit) ? 00214 MagickTrue : MagickFalse; 00215 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue, 00216 resource_current); 00217 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue, 00218 resource_limit); 00219 break; 00220 } 00221 case FileResource: 00222 { 00223 resource_info.file+=size; 00224 limit=resource_info.file_limit; 00225 status=(resource_info.file_limit == MagickResourceInfinity) || 00226 ((MagickSizeType) resource_info.file < limit) ? 00227 MagickTrue : MagickFalse; 00228 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse, 00229 resource_current); 00230 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit, 00231 MagickFalse,resource_limit); 00232 break; 00233 } 00234 case ThreadResource: 00235 { 00236 resource_info.thread+=size; 00237 limit=resource_info.thread_limit; 00238 status=(resource_info.thread_limit == MagickResourceInfinity) || 00239 ((MagickSizeType) resource_info.thread < limit) ? 00240 MagickTrue : MagickFalse; 00241 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse, 00242 resource_current); 00243 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit, 00244 MagickFalse,resource_limit); 00245 break; 00246 } 00247 case TimeResource: 00248 { 00249 resource_info.time+=size; 00250 limit=resource_info.time_limit; 00251 status=(resource_info.time_limit == MagickResourceInfinity) || 00252 ((MagickSizeType) resource_info.time < limit) ? 00253 MagickTrue : MagickFalse; 00254 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse, 00255 resource_current); 00256 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit, 00257 MagickFalse,resource_limit); 00258 break; 00259 } 00260 default: 00261 break; 00262 } 00263 UnlockSemaphoreInfo(resource_semaphore); 00264 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s", 00265 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type), 00266 resource_request,resource_current,resource_limit); 00267 return(status); 00268 } 00269 00270 /* 00271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00272 % % 00273 % % 00274 % % 00275 + 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 % 00276 % % 00277 % % 00278 % % 00279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00280 % 00281 % AsynchronousResourceComponentTerminus() destroys the resource environment. 00282 % It differs from ResourceComponentTerminus() in that it can be called from a 00283 % asynchronous signal handler. 00284 % 00285 % The format of the ResourceComponentTerminus() method is: 00286 % 00287 % ResourceComponentTerminus(void) 00288 % 00289 */ 00290 MagickPrivate void AsynchronousResourceComponentTerminus(void) 00291 { 00292 const char 00293 *path; 00294 00295 if (temporary_resources == (SplayTreeInfo *) NULL) 00296 return; 00297 /* 00298 Remove any lingering temporary files. 00299 */ 00300 ResetSplayTreeIterator(temporary_resources); 00301 path=(const char *) GetNextKeyInSplayTree(temporary_resources); 00302 while (path != (const char *) NULL) 00303 { 00304 (void) remove_utf8(path); 00305 path=(const char *) GetNextKeyInSplayTree(temporary_resources); 00306 } 00307 } 00308 00309 /* 00310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00311 % % 00312 % % 00313 % % 00314 % 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 % 00315 % % 00316 % % 00317 % % 00318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00319 % 00320 % AcquireUniqueFileResource() returns a unique file name, and returns a file 00321 % descriptor for the file open for reading and writing. 00322 % 00323 % The format of the AcquireUniqueFileResource() method is: 00324 % 00325 % int AcquireUniqueFileResource(char *path) 00326 % 00327 % A description of each parameter follows: 00328 % 00329 % o path: Specifies a pointer to an array of characters. The unique path 00330 % name is returned in this array. 00331 % 00332 */ 00333 00334 static void *DestroyTemporaryResources(void *temporary_resource) 00335 { 00336 (void) remove_utf8((char *) temporary_resource); 00337 temporary_resource=DestroyString((char *) temporary_resource); 00338 return((void *) NULL); 00339 } 00340 00341 static MagickBooleanType GetPathTemplate(char *path) 00342 { 00343 char 00344 *directory; 00345 00346 ExceptionInfo 00347 *exception; 00348 00349 MagickBooleanType 00350 status; 00351 00352 register char 00353 *p; 00354 00355 struct stat 00356 attributes; 00357 00358 (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent); 00359 exception=AcquireExceptionInfo(); 00360 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", 00361 exception); 00362 exception=DestroyExceptionInfo(exception); 00363 if (directory == (char *) NULL) 00364 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); 00365 if (directory == (char *) NULL) 00366 directory=GetEnvironmentValue("MAGICK_TMPDIR"); 00367 if (directory == (char *) NULL) 00368 directory=GetPolicyValue("temporary-path"); 00369 if (directory == (char *) NULL) 00370 directory=GetEnvironmentValue("TMPDIR"); 00371 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) 00372 if (directory == (char *) NULL) 00373 directory=GetEnvironmentValue("TMP"); 00374 if (directory == (char *) NULL) 00375 directory=GetEnvironmentValue("TEMP"); 00376 #endif 00377 #if defined(__VMS) 00378 if (directory == (char *) NULL) 00379 directory=GetEnvironmentValue("MTMPDIR"); 00380 #endif 00381 #if defined(P_tmpdir) 00382 if (directory == (char *) NULL) 00383 directory=ConstantString(P_tmpdir); 00384 #endif 00385 if (directory == (char *) NULL) 00386 return(MagickTrue); 00387 if (strlen(directory) > (MaxTextExtent-15)) 00388 { 00389 directory=DestroyString(directory); 00390 return(MagickTrue); 00391 } 00392 status=GetPathAttributes(directory,&attributes); 00393 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) 00394 { 00395 directory=DestroyString(directory); 00396 return(MagickTrue); 00397 } 00398 if (directory[strlen(directory)-1] == *DirectorySeparator) 00399 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory); 00400 else 00401 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-XXXXXXXX", 00402 directory,DirectorySeparator); 00403 directory=DestroyString(directory); 00404 if (*DirectorySeparator != '/') 00405 for (p=path; *p != '\0'; p++) 00406 if (*p == *DirectorySeparator) 00407 *p='/'; 00408 return(MagickTrue); 00409 } 00410 00411 MagickExport int AcquireUniqueFileResource(char *path) 00412 { 00413 #if !defined(O_NOFOLLOW) 00414 #define O_NOFOLLOW 0 00415 #endif 00416 #if !defined(TMP_MAX) 00417 # define TMP_MAX 238328 00418 #endif 00419 00420 int 00421 c, 00422 file; 00423 00424 register char 00425 *p; 00426 00427 register ssize_t 00428 i; 00429 00430 static const char 00431 portable_filename[65] = 00432 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"; 00433 00434 StringInfo 00435 *key; 00436 00437 unsigned char 00438 *datum; 00439 00440 assert(path != (char *) NULL); 00441 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); 00442 if (random_info == (RandomInfo *) NULL) 00443 random_info=AcquireRandomInfo(); 00444 file=(-1); 00445 for (i=0; i < (ssize_t) TMP_MAX; i++) 00446 { 00447 /* 00448 Get temporary pathname. 00449 */ 00450 (void) GetPathTemplate(path); 00451 key=GetRandomKey(random_info,2); 00452 p=path+strlen(path)-8; 00453 datum=GetStringInfoDatum(key); 00454 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++) 00455 { 00456 c=(int) (datum[i] & 0x3f); 00457 *p++=portable_filename[c]; 00458 } 00459 key=DestroyStringInfo(key); 00460 #if defined(MAGICKCORE_HAVE_MKSTEMP) 00461 file=mkstemp(path); 00462 #if defined(__OS2__) 00463 setmode(file,O_BINARY); 00464 #endif 00465 if (file != -1) 00466 break; 00467 #endif 00468 key=GetRandomKey(random_info,6); 00469 p=path+strlen(path)-6; 00470 datum=GetStringInfoDatum(key); 00471 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++) 00472 { 00473 c=(int) (datum[i] & 0x3f); 00474 *p++=portable_filename[c]; 00475 } 00476 key=DestroyStringInfo(key); 00477 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE); 00478 if ((file >= 0) || (errno != EEXIST)) 00479 break; 00480 } 00481 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); 00482 if (file == -1) 00483 return(file); 00484 if (resource_semaphore == (SemaphoreInfo *) NULL) 00485 AcquireSemaphoreInfo(&resource_semaphore); 00486 LockSemaphoreInfo(resource_semaphore); 00487 if (temporary_resources == (SplayTreeInfo *) NULL) 00488 temporary_resources=NewSplayTree(CompareSplayTreeString, 00489 DestroyTemporaryResources,(void *(*)(void *)) NULL); 00490 UnlockSemaphoreInfo(resource_semaphore); 00491 (void) AddValueToSplayTree(temporary_resources,ConstantString(path), 00492 (const void *) NULL); 00493 return(file); 00494 } 00495 00496 /* 00497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00498 % % 00499 % % 00500 % % 00501 % G e t M a g i c k R e s o u r c e % 00502 % % 00503 % % 00504 % % 00505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00506 % 00507 % GetMagickResource() returns the specified resource. 00508 % 00509 % The format of the GetMagickResource() method is: 00510 % 00511 % MagickSizeType GetMagickResource(const ResourceType type) 00512 % 00513 % A description of each parameter follows: 00514 % 00515 % o type: the type of resource. 00516 % 00517 */ 00518 MagickExport MagickSizeType GetMagickResource(const ResourceType type) 00519 { 00520 MagickSizeType 00521 resource; 00522 00523 resource=0; 00524 LockSemaphoreInfo(resource_semaphore); 00525 switch (type) 00526 { 00527 case AreaResource: 00528 { 00529 resource=(MagickSizeType) resource_info.area; 00530 break; 00531 } 00532 case MemoryResource: 00533 { 00534 resource=(MagickSizeType) resource_info.memory; 00535 break; 00536 } 00537 case MapResource: 00538 { 00539 resource=(MagickSizeType) resource_info.map; 00540 break; 00541 } 00542 case DiskResource: 00543 { 00544 resource=(MagickSizeType) resource_info.disk; 00545 break; 00546 } 00547 case FileResource: 00548 { 00549 resource=(MagickSizeType) resource_info.file; 00550 break; 00551 } 00552 case ThreadResource: 00553 { 00554 resource=(MagickSizeType) resource_info.thread; 00555 break; 00556 } 00557 case TimeResource: 00558 { 00559 resource=(MagickSizeType) resource_info.time; 00560 break; 00561 } 00562 default: 00563 break; 00564 } 00565 UnlockSemaphoreInfo(resource_semaphore); 00566 return(resource); 00567 } 00568 00569 /* 00570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00571 % % 00572 % % 00573 % % 00574 % G e t M a g i c k R e s o u r c e L i m i t % 00575 % % 00576 % % 00577 % % 00578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00579 % 00580 % GetMagickResourceLimit() returns the specified resource limit. 00581 % 00582 % The format of the GetMagickResourceLimit() method is: 00583 % 00584 % MagickSizeType GetMagickResourceLimit(const ResourceType type) 00585 % 00586 % A description of each parameter follows: 00587 % 00588 % o type: the type of resource. 00589 % 00590 */ 00591 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type) 00592 { 00593 MagickSizeType 00594 resource; 00595 00596 resource=0; 00597 if (resource_semaphore == (SemaphoreInfo *) NULL) 00598 AcquireSemaphoreInfo(&resource_semaphore); 00599 LockSemaphoreInfo(resource_semaphore); 00600 switch (type) 00601 { 00602 case AreaResource: 00603 { 00604 resource=resource_info.area_limit; 00605 break; 00606 } 00607 case MemoryResource: 00608 { 00609 resource=resource_info.memory_limit; 00610 break; 00611 } 00612 case MapResource: 00613 { 00614 resource=resource_info.map_limit; 00615 break; 00616 } 00617 case DiskResource: 00618 { 00619 resource=resource_info.disk_limit; 00620 break; 00621 } 00622 case FileResource: 00623 { 00624 resource=resource_info.file_limit; 00625 break; 00626 } 00627 case ThreadResource: 00628 { 00629 resource=resource_info.thread_limit; 00630 break; 00631 } 00632 case TimeResource: 00633 { 00634 resource=resource_info.time_limit; 00635 break; 00636 } 00637 default: 00638 break; 00639 } 00640 UnlockSemaphoreInfo(resource_semaphore); 00641 return(resource); 00642 } 00643 00644 /* 00645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00646 % % 00647 % % 00648 % % 00649 % L i s t M a g i c k R e s o u r c e I n f o % 00650 % % 00651 % % 00652 % % 00653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00654 % 00655 % ListMagickResourceInfo() lists the resource info to a file. 00656 % 00657 % The format of the ListMagickResourceInfo method is: 00658 % 00659 % MagickBooleanType ListMagickResourceInfo(FILE *file, 00660 % ExceptionInfo *exception) 00661 % 00662 % A description of each parameter follows. 00663 % 00664 % o file: An pointer to a FILE. 00665 % 00666 % o exception: return any errors or warnings in this structure. 00667 % 00668 */ 00669 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file, 00670 ExceptionInfo *magick_unused(exception)) 00671 { 00672 char 00673 area_limit[MaxTextExtent], 00674 disk_limit[MaxTextExtent], 00675 map_limit[MaxTextExtent], 00676 memory_limit[MaxTextExtent], 00677 time_limit[MaxTextExtent]; 00678 00679 if (file == (const FILE *) NULL) 00680 file=stdout; 00681 if (resource_semaphore == (SemaphoreInfo *) NULL) 00682 AcquireSemaphoreInfo(&resource_semaphore); 00683 LockSemaphoreInfo(resource_semaphore); 00684 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit); 00685 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit); 00686 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit); 00687 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent); 00688 if (resource_info.disk_limit != MagickResourceInfinity) 00689 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit); 00690 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent); 00691 if (resource_info.time_limit != MagickResourceInfinity) 00692 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double) 00693 ((MagickOffsetType) resource_info.time_limit)); 00694 (void) FormatLocaleFile(file,"File Area Memory Map" 00695 " Disk Thread Time\n"); 00696 (void) FormatLocaleFile(file, 00697 "--------------------------------------------------------" 00698 "-----------------------\n"); 00699 (void) FormatLocaleFile(file,"%4g %10s %10s %10s %10s %6g %11s\n", 00700 (double) ((MagickOffsetType) resource_info.file_limit),area_limit, 00701 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType) 00702 resource_info.thread_limit),time_limit); 00703 (void) fflush(file); 00704 UnlockSemaphoreInfo(resource_semaphore); 00705 return(MagickTrue); 00706 } 00707 00708 /* 00709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00710 % % 00711 % % 00712 % % 00713 % R e l i n q u i s h M a g i c k R e s o u r c e % 00714 % % 00715 % % 00716 % % 00717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00718 % 00719 % RelinquishMagickResource() relinquishes resources of the specified type. 00720 % 00721 % The format of the RelinquishMagickResource() method is: 00722 % 00723 % void RelinquishMagickResource(const ResourceType type, 00724 % const MagickSizeType size) 00725 % 00726 % A description of each parameter follows: 00727 % 00728 % o type: the type of resource. 00729 % 00730 % o size: the size of the resource. 00731 % 00732 */ 00733 MagickExport void RelinquishMagickResource(const ResourceType type, 00734 const MagickSizeType size) 00735 { 00736 char 00737 resource_current[MaxTextExtent], 00738 resource_limit[MaxTextExtent], 00739 resource_request[MaxTextExtent]; 00740 00741 (void) FormatMagickSize(size,MagickFalse,resource_request); 00742 if (resource_semaphore == (SemaphoreInfo *) NULL) 00743 AcquireSemaphoreInfo(&resource_semaphore); 00744 LockSemaphoreInfo(resource_semaphore); 00745 switch (type) 00746 { 00747 case AreaResource: 00748 { 00749 resource_info.area=(MagickOffsetType) size; 00750 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse, 00751 resource_current); 00752 (void) FormatMagickSize(resource_info.area_limit,MagickFalse, 00753 resource_limit); 00754 break; 00755 } 00756 case MemoryResource: 00757 { 00758 resource_info.memory-=size; 00759 (void) FormatMagickSize((MagickSizeType) resource_info.memory, 00760 MagickTrue,resource_current); 00761 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue, 00762 resource_limit); 00763 break; 00764 } 00765 case MapResource: 00766 { 00767 resource_info.map-=size; 00768 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue, 00769 resource_current); 00770 (void) FormatMagickSize(resource_info.map_limit,MagickTrue, 00771 resource_limit); 00772 break; 00773 } 00774 case DiskResource: 00775 { 00776 resource_info.disk-=size; 00777 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue, 00778 resource_current); 00779 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue, 00780 resource_limit); 00781 break; 00782 } 00783 case FileResource: 00784 { 00785 resource_info.file-=size; 00786 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse, 00787 resource_current); 00788 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit, 00789 MagickFalse,resource_limit); 00790 break; 00791 } 00792 case ThreadResource: 00793 { 00794 resource_info.thread-=size; 00795 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse, 00796 resource_current); 00797 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit, 00798 MagickFalse,resource_limit); 00799 break; 00800 } 00801 case TimeResource: 00802 { 00803 resource_info.time-=size; 00804 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse, 00805 resource_current); 00806 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit, 00807 MagickFalse,resource_limit); 00808 break; 00809 } 00810 default: 00811 break; 00812 } 00813 UnlockSemaphoreInfo(resource_semaphore); 00814 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s", 00815 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type), 00816 resource_request,resource_current,resource_limit); 00817 } 00818 00819 /* 00820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00821 % % 00822 % % 00823 % % 00824 % 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 % 00825 % % 00826 % % 00827 % % 00828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00829 % 00830 % RelinquishUniqueFileResource() relinquishes a unique file resource. 00831 % 00832 % The format of the RelinquishUniqueFileResource() method is: 00833 % 00834 % MagickBooleanType RelinquishUniqueFileResource(const char *path) 00835 % 00836 % A description of each parameter follows: 00837 % 00838 % o name: the name of the temporary resource. 00839 % 00840 */ 00841 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path) 00842 { 00843 char 00844 cache_path[MaxTextExtent]; 00845 00846 assert(path != (const char *) NULL); 00847 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); 00848 if (temporary_resources != (SplayTreeInfo *) NULL) 00849 { 00850 register char 00851 *p; 00852 00853 ResetSplayTreeIterator(temporary_resources); 00854 p=(char *) GetNextKeyInSplayTree(temporary_resources); 00855 while (p != (char *) NULL) 00856 { 00857 if (LocaleCompare(p,path) == 0) 00858 break; 00859 p=(char *) GetNextKeyInSplayTree(temporary_resources); 00860 } 00861 if (p != (char *) NULL) 00862 (void) DeleteNodeFromSplayTree(temporary_resources,p); 00863 } 00864 (void) CopyMagickString(cache_path,path,MaxTextExtent); 00865 AppendImageFormat("cache",cache_path); 00866 (void) remove_utf8(cache_path); 00867 return(remove_utf8(path) == 0 ? MagickTrue : MagickFalse); 00868 } 00869 00870 /* 00871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00872 % % 00873 % % 00874 % % 00875 + R e s o u r c e C o m p o n e n t G e n e s i s % 00876 % % 00877 % % 00878 % % 00879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00880 % 00881 % ResourceComponentGenesis() instantiates the resource component. 00882 % 00883 % The format of the ResourceComponentGenesis method is: 00884 % 00885 % MagickBooleanType ResourceComponentGenesis(void) 00886 % 00887 */ 00888 00889 static inline size_t MagickMax(const size_t x,const size_t y) 00890 { 00891 if (x > y) 00892 return(x); 00893 return(y); 00894 } 00895 00896 static inline MagickSizeType StringToSizeType(const char *string, 00897 const double interval) 00898 { 00899 double 00900 value; 00901 00902 value=SiPrefixToDoubleInterval(string,interval); 00903 if (value >= (double) MagickULLConstant(~0)) 00904 return(MagickULLConstant(~0)); 00905 return((MagickSizeType) value); 00906 } 00907 00908 MagickPrivate MagickBooleanType ResourceComponentGenesis(void) 00909 { 00910 char 00911 *limit; 00912 00913 MagickSizeType 00914 memory; 00915 00916 ssize_t 00917 files, 00918 pages, 00919 pagesize; 00920 00921 /* 00922 Set Magick resource limits. 00923 */ 00924 AcquireSemaphoreInfo(&resource_semaphore); 00925 pagesize=GetMagickPageSize(); 00926 pages=(-1); 00927 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) 00928 pages=(ssize_t) sysconf(_SC_PHYS_PAGES); 00929 #endif 00930 memory=(MagickSizeType) pages*pagesize; 00931 if ((pagesize <= 0) || (pages <= 0)) 00932 memory=2048UL*1024UL*1024UL; 00933 #if defined(PixelCacheThreshold) 00934 memory=PixelCacheThreshold; 00935 #endif 00936 (void) SetMagickResourceLimit(AreaResource,2*memory); 00937 (void) SetMagickResourceLimit(MemoryResource,memory); 00938 (void) SetMagickResourceLimit(MapResource,2*memory); 00939 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT"); 00940 if (limit == (char *) NULL) 00941 limit=GetPolicyValue("area"); 00942 if (limit != (char *) NULL) 00943 { 00944 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0)); 00945 limit=DestroyString(limit); 00946 } 00947 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT"); 00948 if (limit == (char *) NULL) 00949 limit=GetPolicyValue("memory"); 00950 if (limit != (char *) NULL) 00951 { 00952 (void) SetMagickResourceLimit(MemoryResource, 00953 StringToSizeType(limit,100.0)); 00954 limit=DestroyString(limit); 00955 } 00956 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT"); 00957 if (limit == (char *) NULL) 00958 limit=GetPolicyValue("map"); 00959 if (limit != (char *) NULL) 00960 { 00961 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0)); 00962 limit=DestroyString(limit); 00963 } 00964 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT"); 00965 if (limit == (char *) NULL) 00966 limit=GetPolicyValue("disk"); 00967 if (limit != (char *) NULL) 00968 { 00969 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0)); 00970 limit=DestroyString(limit); 00971 } 00972 files=(-1); 00973 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 00974 files=(ssize_t) sysconf(_SC_OPEN_MAX); 00975 #endif 00976 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 00977 if (files < 0) 00978 { 00979 struct rlimit 00980 resources; 00981 00982 if (getrlimit(RLIMIT_NOFILE,&resources) != -1) 00983 files=(ssize_t) resources.rlim_cur; 00984 } 00985 #endif 00986 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT) 00987 if (files < 0) 00988 files=(ssize_t) getdtablesize(); 00989 #endif 00990 if (files < 0) 00991 files=64; 00992 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t) 00993 (3*files/4),64)); 00994 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT"); 00995 if (limit == (char *) NULL) 00996 limit=GetPolicyValue("file"); 00997 if (limit != (char *) NULL) 00998 { 00999 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit, 01000 100.0)); 01001 limit=DestroyString(limit); 01002 } 01003 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads()); 01004 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT"); 01005 if (limit == (char *) NULL) 01006 limit=GetPolicyValue("thread"); 01007 if (limit != (char *) NULL) 01008 { 01009 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit, 01010 100.0)); 01011 limit=DestroyString(limit); 01012 } 01013 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT"); 01014 if (limit == (char *) NULL) 01015 limit=GetPolicyValue("time"); 01016 if (limit != (char *) NULL) 01017 { 01018 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0)); 01019 limit=DestroyString(limit); 01020 } 01021 return(MagickTrue); 01022 } 01023 01024 /* 01025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01026 % % 01027 % % 01028 % % 01029 + 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 % 01030 % % 01031 % % 01032 % % 01033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01034 % 01035 % ResourceComponentTerminus() destroys the resource component. 01036 % 01037 % The format of the ResourceComponentTerminus() method is: 01038 % 01039 % ResourceComponentTerminus(void) 01040 % 01041 */ 01042 MagickPrivate void ResourceComponentTerminus(void) 01043 { 01044 if (resource_semaphore == (SemaphoreInfo *) NULL) 01045 AcquireSemaphoreInfo(&resource_semaphore); 01046 LockSemaphoreInfo(resource_semaphore); 01047 if (temporary_resources != (SplayTreeInfo *) NULL) 01048 temporary_resources=DestroySplayTree(temporary_resources); 01049 if (random_info != (RandomInfo *) NULL) 01050 random_info=DestroyRandomInfo(random_info); 01051 UnlockSemaphoreInfo(resource_semaphore); 01052 DestroySemaphoreInfo(&resource_semaphore); 01053 } 01054 01055 /* 01056 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01057 % % 01058 % % 01059 % % 01060 % S e t M a g i c k R e s o u r c e L i m i t % 01061 % % 01062 % % 01063 % % 01064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01065 % 01066 % SetMagickResourceLimit() sets the limit for a particular resource. 01067 % 01068 % The format of the SetMagickResourceLimit() method is: 01069 % 01070 % MagickBooleanType SetMagickResourceLimit(const ResourceType type, 01071 % const MagickSizeType limit) 01072 % 01073 % A description of each parameter follows: 01074 % 01075 % o type: the type of resource. 01076 % 01077 % o limit: the maximum limit for the resource. 01078 % 01079 */ 01080 01081 static inline MagickSizeType MagickMin(const MagickSizeType x, 01082 const MagickSizeType y) 01083 { 01084 if (x < y) 01085 return(x); 01086 return(y); 01087 } 01088 01089 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type, 01090 const MagickSizeType limit) 01091 { 01092 char 01093 *value; 01094 01095 if (resource_semaphore == (SemaphoreInfo *) NULL) 01096 AcquireSemaphoreInfo(&resource_semaphore); 01097 LockSemaphoreInfo(resource_semaphore); 01098 value=(char *) NULL; 01099 switch (type) 01100 { 01101 case AreaResource: 01102 { 01103 resource_info.area_limit=limit; 01104 value=GetPolicyValue("area"); 01105 if (value != (char *) NULL) 01106 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0)); 01107 break; 01108 } 01109 case MemoryResource: 01110 { 01111 resource_info.memory_limit=limit; 01112 value=GetPolicyValue("memory"); 01113 if (value != (char *) NULL) 01114 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value, 01115 100.0)); 01116 break; 01117 } 01118 case MapResource: 01119 { 01120 resource_info.map_limit=limit; 01121 value=GetPolicyValue("map"); 01122 if (value != (char *) NULL) 01123 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0)); 01124 break; 01125 } 01126 case DiskResource: 01127 { 01128 resource_info.disk_limit=limit; 01129 value=GetPolicyValue("disk"); 01130 if (value != (char *) NULL) 01131 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0)); 01132 break; 01133 } 01134 case FileResource: 01135 { 01136 resource_info.file_limit=limit; 01137 value=GetPolicyValue("file"); 01138 if (value != (char *) NULL) 01139 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0)); 01140 break; 01141 } 01142 case ThreadResource: 01143 { 01144 resource_info.thread_limit=limit; 01145 value=GetPolicyValue("thread"); 01146 if (value != (char *) NULL) 01147 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value, 01148 100.0)); 01149 SetOpenMPMaximumThreads((int) resource_info.thread_limit); 01150 break; 01151 } 01152 case TimeResource: 01153 { 01154 resource_info.time_limit=limit; 01155 value=GetPolicyValue("time"); 01156 if (value != (char *) NULL) 01157 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0)); 01158 break; 01159 } 01160 default: 01161 break; 01162 } 01163 if (value != (char *) NULL) 01164 value=DestroyString(value); 01165 UnlockSemaphoreInfo(resource_semaphore); 01166 return(MagickTrue); 01167 }