MagickCore  6.7.5
resource.c
Go to the documentation of this file.
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 }