]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/resource.c
(no commit message)
[imagemagick] / MagickCore / resource.c
index 567d9fce27c24749e0a8407bf558e39eb4dbf540..b28af7d478f17b56e901d770ded5ff4e9658cefa 100644 (file)
 %                        Get/Set MagickCore Resources                         %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                               September 2002                                %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -48,6 +48,7 @@
 #include "MagickCore/log.h"
 #include "MagickCore/image.h"
 #include "MagickCore/memory_.h"
+#include "MagickCore/nt-base-private.h"
 #include "MagickCore/option.h"
 #include "MagickCore/policy.h"
 #include "MagickCore/random_.h"
@@ -76,6 +77,7 @@ typedef struct _ResourceInfo
     disk,
     file,
     thread,
+    throttle,
     time;
 
   MagickSizeType
@@ -85,6 +87,7 @@ typedef struct _ResourceInfo
     disk_limit,
     file_limit,
     thread_limit,
+    throttle_limit,
     time_limit;
 } ResourceInfo;
 \f
@@ -97,20 +100,22 @@ static RandomInfo
 static ResourceInfo
   resource_info =
   {
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(0),
-    MagickULLConstant(3072)*1024*1024,
-    MagickULLConstant(1536)*1024*1024,
-    MagickULLConstant(3072)*1024*1024,
-    MagickResourceInfinity,
-    MagickULLConstant(768),
-    MagickULLConstant(4),
-    MagickResourceInfinity
+    MagickULLConstant(0),              /* initial area */
+    MagickULLConstant(0),              /* initial memory */
+    MagickULLConstant(0),              /* initial map */
+    MagickULLConstant(0),              /* initial disk */
+    MagickULLConstant(0),              /* initial file */
+    MagickULLConstant(0),              /* initial thread */
+    MagickULLConstant(0),              /* initial throttle */
+    MagickULLConstant(0),              /* initial time */
+    MagickULLConstant(3072)*1024*1024, /* area limit */
+    MagickULLConstant(1536)*1024*1024, /* memory limit */
+    MagickULLConstant(3072)*1024*1024, /* map limit */
+    MagickResourceInfinity,            /* disk limit */
+    MagickULLConstant(768),            /* file limit */
+    MagickULLConstant(1),              /* thread limit */
+    MagickULLConstant(0),              /* throttle limit */
+    MagickResourceInfinity             /* time limit */
   };
 
 static SemaphoreInfo
@@ -163,7 +168,7 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
   status=MagickFalse;
   (void) FormatMagickSize(size,MagickFalse,resource_request);
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    ActivateSemaphoreInfo(&resource_semaphore);
   LockSemaphoreInfo(resource_semaphore);
   switch (type)
   {
@@ -184,8 +189,8 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
       resource_info.memory+=size;
       limit=resource_info.memory_limit;
       status=(resource_info.memory_limit == MagickResourceInfinity) ||
-        ((MagickSizeType) resource_info.memory < limit) ?
-        MagickTrue : MagickFalse;
+        ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
+        MagickFalse;
       (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
         resource_current);
       (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
@@ -197,8 +202,7 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
       resource_info.map+=size;
       limit=resource_info.map_limit;
       status=(resource_info.map_limit == MagickResourceInfinity) ||
-        ((MagickSizeType) resource_info.map < limit) ?
-        MagickTrue : MagickFalse;
+        ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
       (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
         resource_current);
       (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
@@ -210,8 +214,8 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
       resource_info.disk+=size;
       limit=resource_info.disk_limit;
       status=(resource_info.disk_limit == MagickResourceInfinity) ||
-        ((MagickSizeType) resource_info.disk < limit) ?
-        MagickTrue : MagickFalse;
+        ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
+        MagickFalse;
       (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
         resource_current);
       (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
@@ -233,7 +237,6 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
     }
     case ThreadResource:
     {
-      resource_info.thread+=size;
       limit=resource_info.thread_limit;
       status=(resource_info.thread_limit == MagickResourceInfinity) ||
         ((MagickSizeType) resource_info.thread < limit) ?
@@ -244,6 +247,18 @@ MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
         MagickFalse,resource_limit);
       break;
     }
+    case ThrottleResource:
+    {
+      limit=resource_info.throttle_limit;
+      status=(resource_info.throttle_limit == MagickResourceInfinity) ||
+        ((MagickSizeType) resource_info.throttle < limit) ?
+        MagickTrue : MagickFalse;
+      (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
+        MagickFalse,resource_current);
+      (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
+        MagickFalse,resource_limit);
+      break;
+    }
     case TimeResource:
     {
       resource_info.time+=size;
@@ -301,7 +316,7 @@ MagickPrivate void AsynchronousResourceComponentTerminus(void)
   path=(const char *) GetNextKeyInSplayTree(temporary_resources);
   while (path != (const char *) NULL)
   {
-    (void) remove_utf8(path);
+    (void) ShredFile(path);
     path=(const char *) GetNextKeyInSplayTree(temporary_resources);
   }
 }
@@ -333,15 +348,16 @@ MagickPrivate void AsynchronousResourceComponentTerminus(void)
 
 static void *DestroyTemporaryResources(void *temporary_resource)
 {
-  (void) remove_utf8((char *) temporary_resource);
+  (void) ShredFile((char *) temporary_resource);
   temporary_resource=DestroyString((char *) temporary_resource);
   return((void *) NULL);
 }
 
-static MagickBooleanType GetPathTemplate(char *path)
+MagickExport MagickBooleanType GetPathTemplate(char *path)
 {
   char
-    *directory;
+    *directory,
+    *value;
 
   ExceptionInfo
     *exception;
@@ -349,13 +365,11 @@ static MagickBooleanType GetPathTemplate(char *path)
   MagickBooleanType
     status;
 
-  register char
-    *p;
-
   struct stat
     attributes;
 
-  (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent);
+  (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
+    (double) getpid());
   exception=AcquireExceptionInfo();
   directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
     exception);
@@ -364,8 +378,6 @@ static MagickBooleanType GetPathTemplate(char *path)
     directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
   if (directory == (char *) NULL)
     directory=GetEnvironmentValue("MAGICK_TMPDIR");
-  if (directory == (char *) NULL)
-    directory=GetPolicyValue("temporary-path");
   if (directory == (char *) NULL)
     directory=GetEnvironmentValue("TMPDIR");
 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
@@ -384,27 +396,42 @@ static MagickBooleanType GetPathTemplate(char *path)
 #endif
   if (directory == (char *) NULL)
     return(MagickTrue);
-  if (strlen(directory) > (MaxTextExtent-15))
+  value=GetPolicyValue("temporary-path");
+  if (value != (char *) NULL)
+    (void) CloneString(&directory,value);
+  if (strlen(directory) > (MaxTextExtent-25))
     {
       directory=DestroyString(directory);
-      return(MagickTrue);
+      return(MagickFalse);
     }
   status=GetPathAttributes(directory,&attributes);
   if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
     {
       directory=DestroyString(directory);
-      return(MagickTrue);
+      return(MagickFalse);
     }
   if (directory[strlen(directory)-1] == *DirectorySeparator)
-    (void) FormatLocaleString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory);
+    (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
+      directory,(double) getpid());
   else
-    (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-XXXXXXXX",
-      directory,DirectorySeparator);
+    (void) FormatLocaleString(path,MaxTextExtent,
+      "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,
+      (double) getpid());
   directory=DestroyString(directory);
-  if (*DirectorySeparator != '/')
-    for (p=path; *p != '\0'; p++)
+#if defined(MAGICKCORE_WINDOWS_SUPPORT)
+  {
+    register char
+      *p;
+
+    /*
+      Ghostscript does not like backslashes so we need to replace them. The
+      forward slash also works under Windows.
+    */
+    for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
       if (*p == *DirectorySeparator)
         *p='/';
+  }
+#endif
   return(MagickTrue);
 }
 
@@ -438,7 +465,7 @@ MagickExport int AcquireUniqueFileResource(char *path)
     *datum;
 
   assert(path != (char *) NULL);
-  (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
+  (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
   if (random_info == (RandomInfo *) NULL)
     random_info=AcquireRandomInfo();
   file=(-1);
@@ -448,8 +475,8 @@ MagickExport int AcquireUniqueFileResource(char *path)
       Get temporary pathname.
     */
     (void) GetPathTemplate(path);
-    key=GetRandomKey(random_info,2);
-    p=path+strlen(path)-8;
+    key=GetRandomKey(random_info,6);
+    p=path+strlen(path)-12;
     datum=GetStringInfoDatum(key);
     for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
     {
@@ -465,8 +492,8 @@ MagickExport int AcquireUniqueFileResource(char *path)
     if (file != -1)
       break;
 #endif
-    key=GetRandomKey(random_info,6);
-    p=path+strlen(path)-6;
+    key=GetRandomKey(random_info,12);
+    p=path+strlen(path)-12;
     datum=GetStringInfoDatum(key);
     for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
     {
@@ -474,7 +501,8 @@ MagickExport int AcquireUniqueFileResource(char *path)
       *p++=portable_filename[c];
     }
     key=DestroyStringInfo(key);
-    file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE);
+    file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
+      S_MODE);
     if ((file >= 0) || (errno != EEXIST))
       break;
   }
@@ -482,7 +510,7 @@ MagickExport int AcquireUniqueFileResource(char *path)
   if (file == -1)
     return(file);
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    ActivateSemaphoreInfo(&resource_semaphore);
   LockSemaphoreInfo(resource_semaphore);
   if (temporary_resources == (SplayTreeInfo *) NULL)
     temporary_resources=NewSplayTree(CompareSplayTreeString,
@@ -554,6 +582,11 @@ MagickExport MagickSizeType GetMagickResource(const ResourceType type)
       resource=(MagickSizeType) resource_info.thread;
       break;
     }
+    case ThrottleResource:
+    {
+      resource=(MagickSizeType) resource_info.throttle;
+      break;
+    }
     case TimeResource:
     {
       resource=(MagickSizeType) resource_info.time;
@@ -595,7 +628,7 @@ MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
 
   resource=0;
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    ActivateSemaphoreInfo(&resource_semaphore);
   LockSemaphoreInfo(resource_semaphore);
   switch (type)
   {
@@ -629,6 +662,11 @@ MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
       resource=resource_info.thread_limit;
       break;
     }
+    case ThrottleResource:
+    {
+      resource=resource_info.throttle_limit;
+      break;
+    }
     case TimeResource:
     {
       resource=resource_info.time_limit;
@@ -679,7 +717,7 @@ MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
   if (file == (const FILE *) NULL)
     file=stdout;
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    ActivateSemaphoreInfo(&resource_semaphore);
   LockSemaphoreInfo(resource_semaphore);
   (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
   (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
@@ -691,15 +729,16 @@ MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
   if (resource_info.time_limit != MagickResourceInfinity)
     (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
       ((MagickOffsetType) resource_info.time_limit));
-  (void) FormatLocaleFile(file,"File         Area       Memory          Map"
-    "         Disk    Thread         Time\n");
+  (void) FormatLocaleFile(file,"  File       Area     Memory        Map"
+    "       Disk   Thread  Throttle       Time\n");
   (void) FormatLocaleFile(file,
     "--------------------------------------------------------"
-    "-----------------------\n");
-  (void) FormatLocaleFile(file,"%4g   %10s   %10s   %10s   %10s    %6g  %11s\n",
+    "------------------------\n");
+  (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %8g  %8g %10s\n",
     (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
     memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
-    resource_info.thread_limit),time_limit);
+    resource_info.thread_limit),(double) ((MagickOffsetType)
+    resource_info.throttle_limit),time_limit);
   (void) fflush(file);
   UnlockSemaphoreInfo(resource_semaphore);
   return(MagickTrue);
@@ -740,7 +779,7 @@ MagickExport void RelinquishMagickResource(const ResourceType type,
 
   (void) FormatMagickSize(size,MagickFalse,resource_request);
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+               ActivateSemaphoreInfo(&resource_semaphore);
   LockSemaphoreInfo(resource_semaphore);
   switch (type)
   {
@@ -791,13 +830,20 @@ MagickExport void RelinquishMagickResource(const ResourceType type,
     }
     case ThreadResource:
     {
-      resource_info.thread-=size;
       (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
         resource_current);
       (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
         MagickFalse,resource_limit);
       break;
     }
+    case ThrottleResource:
+    {
+      (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
+        MagickFalse,resource_current);
+      (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
+        MagickFalse,resource_limit);
+      break;
+    }
     case TimeResource:
     {
       resource_info.time-=size;
@@ -863,8 +909,8 @@ MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
     }
   (void) CopyMagickString(cache_path,path,MaxTextExtent);
   AppendImageFormat("cache",cache_path);
-  (void) remove_utf8(cache_path);
-  return(remove_utf8(path) == 0 ? MagickTrue : MagickFalse);
+  (void) ShredFile(cache_path);
+  return(ShredFile(path));
 }
 \f
 /*
@@ -899,7 +945,7 @@ static inline MagickSizeType StringToSizeType(const char *string,
   double
     value;
 
-  value=SiPrefixToDouble(string,interval);
+  value=SiPrefixToDoubleInterval(string,interval);
   if (value >= (double) MagickULLConstant(~0))
     return(MagickULLConstant(~0));
   return((MagickSizeType) value);
@@ -921,7 +967,8 @@ MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
   /*
     Set Magick resource limits.
   */
-  AcquireSemaphoreInfo(&resource_semaphore);
+  if (resource_semaphore == (SemaphoreInfo *) NULL)
+    resource_semaphore=AcquireSemaphoreInfo();
   pagesize=GetMagickPageSize();
   pages=(-1);
 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
@@ -934,36 +981,29 @@ MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
   memory=PixelCacheThreshold;
 #endif
   (void) SetMagickResourceLimit(AreaResource,2*memory);
-  (void) SetMagickResourceLimit(MemoryResource,memory);
-  (void) SetMagickResourceLimit(MapResource,2*memory);
   limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("area");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
       limit=DestroyString(limit);
     }
+  (void) SetMagickResourceLimit(MemoryResource,memory);
   limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("memory");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(MemoryResource,
         StringToSizeType(limit,100.0));
       limit=DestroyString(limit);
     }
+  (void) SetMagickResourceLimit(MapResource,2*memory);
   limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("map");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
       limit=DestroyString(limit);
     }
+  (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
   limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("disk");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
@@ -992,26 +1032,30 @@ MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
   (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
     (3*files/4),64));
   limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("file");
   if (limit != (char *) NULL)
     {
-      (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
+      (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
+        100.0));
       limit=DestroyString(limit);
     }
   (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
   limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("thread");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
         100.0));
       limit=DestroyString(limit);
     }
+  (void) SetMagickResourceLimit(ThrottleResource,0);
+  limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
+  if (limit != (char *) NULL)
+    {
+      (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
+        100.0));
+      limit=DestroyString(limit);
+    }
+  (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
   limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
-  if (limit == (char *) NULL)
-    limit=GetPolicyValue("time");
   if (limit != (char *) NULL)
     {
       (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
@@ -1041,14 +1085,14 @@ MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
 MagickPrivate void ResourceComponentTerminus(void)
 {
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    resource_semaphore=AcquireSemaphoreInfo();
   LockSemaphoreInfo(resource_semaphore);
   if (temporary_resources != (SplayTreeInfo *) NULL)
     temporary_resources=DestroySplayTree(temporary_resources);
   if (random_info != (RandomInfo *) NULL)
     random_info=DestroyRandomInfo(random_info);
   UnlockSemaphoreInfo(resource_semaphore);
-  DestroySemaphoreInfo(&resource_semaphore);
+  RelinquishSemaphoreInfo(&resource_semaphore);
 }
 \f
 /*
@@ -1092,7 +1136,7 @@ MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
     *value;
 
   if (resource_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&resource_semaphore);
+    resource_semaphore=AcquireSemaphoreInfo();
   LockSemaphoreInfo(resource_semaphore);
   value=(char *) NULL;
   switch (type)
@@ -1145,7 +1189,19 @@ MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
       if (value != (char *) NULL)
         resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
           100.0));
-      SetOpenMPMaximumThreads((int) resource_info.thread_limit);
+      if (resource_info.thread_limit > GetOpenMPMaximumThreads())
+        resource_info.thread_limit=GetOpenMPMaximumThreads();
+      break;
+    }
+    case ThrottleResource:
+    {
+      resource_info.throttle_limit=limit;
+      value=GetPolicyValue("throttle");
+      if (value != (char *) NULL)
+        resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
+          100.0));
+      if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
+        resource_info.throttle_limit=GetOpenMPMaximumThreads();
       break;
     }
     case TimeResource: