54#include <MagickCore/studio.h>
55#include <MagickCore/MagickCore.h>
56#include "MagickCache/MagickCache.h"
57#include "MagickCache/magick-cache-private.h"
62#define MagickCacheAPIVersion 1
63#define MagickCacheMax(x,y) (((x) > (y)) ? (x) : (y))
64#define MagickCacheMin(x,y) (((x) < (y)) ? (x) : (y))
65#define MagickCacheDigestExtent 64
66#define MagickCacheNonce "MagickCache"
67#define MagickCacheNonceExtent 8
68#define MagickCacheSignature 0xabacadabU
69#define ThrowMagickCacheException(severity,tag,context) \
71 (void) ThrowMagickException(cache->exception,GetMagickModule(),severity,tag, \
73 CatchException(cache->exception); \
109 MagickCacheResourceType
187static void GetMagickCacheSentinel(MagickCache *cache,
unsigned char *sentinel)
199 p+=
sizeof(signature);
200 (void) memcpy(GetStringInfoDatum(cache->nonce),p,
201 GetStringInfoLength(cache->nonce));
202 p+=GetStringInfoLength(cache->nonce);
203 (void) memcpy(cache->digest,p,strlen(cache->digest));
204 p+=strlen(cache->digest);
207static inline unsigned int GetMagickCacheSignature(
const StringInfo *nonce)
221 version=AcquireStringInfo(MagickPathExtent);
222 p=GetStringInfoDatum(version);
223 (void) memcpy(p,MagickCachePackageName,strlen(MagickCachePackageName));
224 p+=strlen(MagickCachePackageName);
225 signature=MagickCacheAPIVersion;
226 (void) memcpy(p,&signature,
sizeof(signature));
227 p+=
sizeof(signature);
228 signature=MagickCacheSignature;
229 (void) memcpy(p,&signature,
sizeof(signature));
230 p+=
sizeof(signature);
231 SetStringInfoLength(version,(
size_t) (p-GetStringInfoDatum(version)));
232 ConcatenateStringInfo(version,nonce);
233 signature=CRC32(GetStringInfoDatum(version),GetStringInfoLength(version));
234 version=DestroyStringInfo(version);
238MagickExport MagickCache *AcquireMagickCache(
const char *path,
239 const StringInfo *passkey)
262 if (path == (
const char *) NULL)
263 return((MagickCache *) NULL);
264 if (GetPathAttributes(path,&attributes) <= 0)
265 return((MagickCache *) NULL);
269 cache=(MagickCache *) AcquireCriticalMemory(
sizeof(*cache));
270 (void) memset(cache,0,
sizeof(*cache));
271 cache->path=ConstantString(path);
272 cache->timestamp=(time_t) attributes.st_ctime;
273 cache->random_info=AcquireRandomInfo();
274 cache->nonce=AcquireStringInfo(MagickCacheNonceExtent);
275 if (passkey == (StringInfo *) NULL)
276 cache->passkey=AcquireStringInfo(0);
278 cache->passkey=CloneStringInfo(passkey);
279 cache->digest=StringInfoToDigest(cache->passkey);
280 cache->exception=AcquireExceptionInfo();
281 cache->debug=IsEventLogging();
282 cache->signature=MagickCacheSignature;
286 sentinel_path=AcquireString(path);
287 (void) ConcatenateString(&sentinel_path,
"/");
288 (void) ConcatenateString(&sentinel_path,MagickCacheSentinel);
289 sentinel=FileToBlob(sentinel_path,~0UL,&extent,cache->exception);
290 sentinel_path=DestroyString(sentinel_path);
291 if (sentinel == NULL)
293 cache=DestroyMagickCache(cache);
294 return((MagickCache *) NULL);
296 GetMagickCacheSentinel(cache,(
unsigned char *) sentinel);
297 signature=GetMagickCacheSignature(cache->nonce);
298 if (memcmp(&signature,sentinel,
sizeof(signature)) != 0)
300 sentinel=RelinquishMagickMemory(sentinel);
301 cache=DestroyMagickCache(cache);
302 return((MagickCache *) NULL);
304 sentinel=RelinquishMagickMemory(sentinel);
335MagickExport MagickCacheResource *AcquireMagickCacheResource(MagickCache *cache,
341 resource=(MagickCacheResource *) AcquireCriticalMemory(
sizeof(*resource));
342 (void) memset(resource,0,
sizeof(*resource));
343 resource->nonce=GetRandomKey(cache->random_info,MagickCacheNonceExtent);
344 resource->version=MagickCacheAPIVersion;
345 resource->exception=AcquireExceptionInfo();
346 resource->signature=MagickCacheSignature;
347 (void) SetMagickCacheResourceIRI(cache,resource,iri);
373MagickExport MagickBooleanType ClearMagickCacheException(MagickCache *cache)
375 assert(cache != (MagickCache *) NULL);
376 assert(cache->signature == MagickCacheSignature);
377 if (cache->debug != MagickFalse)
378 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
379 cache->path != (
char *) NULL ? cache->path :
"");
380 ClearMagickException(cache->exception);
408MagickExport MagickBooleanType ClearMagickCacheResourceException(
409 MagickCacheResource *resource)
411 assert(resource != (MagickCacheResource *) NULL);
412 assert(resource->signature == MagickCacheSignature);
413 if (resource->debug != MagickFalse)
414 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
415 resource->iri != (
char *) NULL ? resource->iri :
"");
416 ClearMagickException(resource->exception);
443MagickExport
size_t GetMagickCacheResourceExtent(
444 const MagickCacheResource *resource)
446 assert(resource != (MagickCacheResource *) NULL);
447 assert(resource->signature == MagickCacheSignature);
448 return(resource->extent);
478static StringInfo *SetMagickCacheSentinel(
const char *path,
479 const StringInfo *passkey)
501 sentinel=AcquireStringInfo(MagickPathExtent);
502 random_info=AcquireRandomInfo();
503 key_info=GetRandomKey(random_info,MagickCacheNonceExtent);
504 p=GetStringInfoDatum(sentinel);
505 signature=GetMagickCacheSignature(key_info);
506 (void) memcpy(p,&signature,
sizeof(signature));
507 p+=
sizeof(signature);
508 (void) memcpy(p,GetStringInfoDatum(key_info),MagickCacheNonceExtent);
509 p+=MagickCacheNonceExtent;
510 cache_key=StringToStringInfo(path);
511 if (passkey != (
const StringInfo *) NULL)
512 ConcatenateStringInfo(cache_key,passkey);
513 ConcatenateStringInfo(cache_key,key_info);
514 digest=StringInfoToDigest(cache_key);
515 cache_key=DestroyStringInfo(cache_key);
516 (void) memcpy(p,digest,strlen(digest));
518 SetStringInfoLength(sentinel,(
size_t) (p-GetStringInfoDatum(sentinel)));
519 digest=DestroyString(digest);
520 key_info=DestroyStringInfo(key_info);
521 random_info=DestroyRandomInfo(random_info);
525MagickExport MagickBooleanType CreateMagickCache(
const char *path,
526 const StringInfo *passkey)
543 if (MagickCreatePath(path) == MagickFalse)
548 sentinel_path=AcquireString(path);
549 (void) ConcatenateString(&sentinel_path,
"/");
550 (void) ConcatenateString(&sentinel_path,MagickCacheSentinel);
551 if (IsPathAccessible(sentinel_path) != MagickFalse)
553 sentinel_path=DestroyString(sentinel_path);
557 meta=SetMagickCacheSentinel(path,passkey);
558 exception=AcquireExceptionInfo();
559 status=BlobToFile(sentinel_path,GetStringInfoDatum(meta),
560 GetStringInfoLength(meta),exception);
561 exception=DestroyExceptionInfo(exception);
562 meta=DestroyStringInfo(meta);
563 sentinel_path=DestroyString(sentinel_path);
592MagickExport MagickBooleanType DeleteMagickCacheResource(MagickCache *cache,
593 MagickCacheResource *resource)
605 assert(cache != (MagickCache *) NULL);
606 assert(cache->signature == MagickCacheSignature);
607 assert(resource != (MagickCacheResource *) NULL);
608 assert(resource->signature == MagickCacheSignature);
609 status=GetMagickCacheResource(cache,resource);
610 if (status == MagickFalse)
615 path=AcquireString(cache->path);
616 (void) ConcatenateString(&path,
"/");
617 (void) ConcatenateString(&path,resource->iri);
618 (void) ConcatenateString(&path,
"/");
619 (void) ConcatenateString(&path,resource->id);
620 if (remove_utf8(path) != 0)
622 path=DestroyString(path);
625 if (resource->resource_type == ImageResourceType)
630 (void) ConcatenateString(&path,
".cache");
631 (void) remove_utf8(path);
633 path=DestroyString(path);
637 path=AcquireString(cache->path);
638 (void) ConcatenateString(&path,
"/");
639 (void) ConcatenateString(&path,resource->iri);
640 (void) ConcatenateString(&path,
"/");
641 (void) ConcatenateString(&path,MagickCacheResourceSentinel);
642 if (remove_utf8(path) != 0)
644 path=DestroyString(path);
647 path=DestroyString(path);
651 iri=AcquireString(resource->iri);
652 for ( ; *iri !=
'\0'; GetPathComponent(iri,HeadPath,iri))
654 path=AcquireString(cache->path);
655 (void) ConcatenateString(&path,
"/");
656 (void) ConcatenateString(&path,iri);
657 (void) remove_utf8(path);
658 path=DestroyString(path);
660 iri=DestroyString(iri);
686MagickExport MagickCache *DestroyMagickCache(MagickCache *cache)
688 assert(cache != (MagickCache *) NULL);
689 assert(cache->signature == MagickCacheSignature);
690 if (cache->path != (
char *) NULL )
691 cache->path=DestroyString(cache->path);
692 if (cache->nonce != (StringInfo *) NULL )
693 cache->nonce=DestroyStringInfo(cache->nonce);
694 if (cache->digest != (
char *) NULL )
695 cache->digest=DestroyString(cache->digest);
696 if (cache->random_info != (RandomInfo *) NULL)
697 cache->random_info=DestroyRandomInfo(cache->random_info);
698 if (cache->passkey != (StringInfo *) NULL )
699 cache->passkey=DestroyStringInfo(cache->passkey);
700 if (cache->exception != (ExceptionInfo *) NULL)
701 cache->exception=DestroyExceptionInfo(cache->exception);
702 cache->signature=(~MagickCacheSignature);
703 cache=(MagickCache *) RelinquishMagickMemory(cache);
731static MagickBooleanType UnmapResourceBlob(
void *map,
const size_t length)
733#if defined(MAGICKCORE_HAVE_MMAP)
737 status=munmap(map,length);
738 return(status == -1 ? MagickFalse : MagickTrue);
746static void DestroyMagickCacheResourceBlob(MagickCacheResource *resource)
748 if (resource->resource_type == ImageResourceType)
749 resource->blob=DestroyImageList((Image *) resource->blob);
751 if (resource->memory_mapped == MagickFalse)
752 resource->blob=RelinquishMagickMemory(resource->blob);
755 (void) UnmapResourceBlob(resource->blob,resource->extent);
756 resource->memory_mapped=MagickFalse;
760MagickExport MagickCacheResource *DestroyMagickCacheResource(
761 MagickCacheResource *resource)
766 assert(resource != (MagickCacheResource *) NULL);
767 assert(resource->signature == MagickCoreSignature);
768 if (resource->blob != NULL)
769 DestroyMagickCacheResourceBlob(resource);
770 if (resource->iri != (
char *) NULL)
771 resource->iri=DestroyString(resource->iri);
772 if (resource->project != (
char *) NULL)
773 resource->project=DestroyString(resource->project);
774 if (resource->type != (
char *) NULL)
775 resource->type=DestroyString(resource->type);
776 if (resource->id != (
char *) NULL)
777 resource->id=DestroyString(resource->id);
778 if (resource->nonce != (StringInfo *) NULL)
779 resource->nonce=DestroyStringInfo(resource->nonce);
780 if (resource->exception != (ExceptionInfo *) NULL)
781 resource->exception=DestroyExceptionInfo(resource->exception);
782 resource->signature=(~MagickCacheSignature);
783 resource=(MagickCacheResource *) RelinquishMagickMemory(resource);
813MagickExport
char *GetMagickCacheException(
const MagickCache *cache,
814 ExceptionType *severity)
819 assert(cache != (
const MagickCache *) NULL);
820 assert(cache->signature == MagickCacheSignature);
821 if (cache->debug != MagickFalse)
822 (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",cache->path);
823 assert(severity != (ExceptionType *) NULL);
824 *severity=cache->exception->severity;
825 description=(
char *) AcquireQuantumMemory(2UL*MagickPathExtent,
826 sizeof(*description));
827 if (description == (
char *) NULL)
829 (void) ThrowMagickException(cache->exception,GetMagickModule(),CacheError,
830 "MemoryAllocationFailed",
"`%s'",cache->path);
831 return((
char *) NULL);
834 if (cache->exception->reason != (
char *) NULL)
835 (void) CopyMagickString(description,GetLocaleExceptionMessage(
836 cache->exception->severity,cache->exception->reason),MagickPathExtent);
837 if (cache->exception->description != (
char *) NULL)
839 (void) ConcatenateMagickString(description,
" (",MagickPathExtent);
840 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
841 cache->exception->severity,cache->exception->description),
843 (void) ConcatenateMagickString(description,
")",MagickPathExtent);
876static void GetMagickCacheResourceSentinel(MagickCacheResource *resource,
877 unsigned char *sentinel)
889 p+=
sizeof(signature);
890 (void) memcpy(GetStringInfoDatum(resource->nonce),p,
891 GetStringInfoLength(resource->nonce));
892 p+=GetStringInfoLength(resource->nonce);
893 (void) memcpy(&resource->ttl,p,
sizeof(resource->ttl));
894 p+=
sizeof(resource->ttl);
895 (void) memcpy(&resource->columns,p,
sizeof(resource->columns));
896 p+=
sizeof(resource->columns);
897 (void) memcpy(&resource->rows,p,
sizeof(resource->rows));
898 p+=
sizeof(resource->rows);
899 if (resource->id != (
char *) NULL)
900 resource->id=DestroyString(resource->id);
901 resource->id=StringInfoToDigest(resource->nonce);
902 (void) memcpy(resource->id,p,strlen(resource->id));
903 p+=strlen(resource->id);
906static void SetMagickCacheResourceID(MagickCache *cache,
907 MagickCacheResource *resource)
918 signature=StringToStringInfo(resource->iri);
919 ConcatenateStringInfo(signature,resource->nonce);
920 ConcatenateStringInfo(signature,cache->passkey);
921 ConcatenateStringInfo(signature,cache->nonce);
922 digest=StringInfoToDigest(signature);
923 signature=DestroyStringInfo(signature);
924 if (resource->id != (
char *) NULL)
925 resource->id=DestroyString(resource->id);
929MagickExport MagickBooleanType GetMagickCacheResource(MagickCache *cache,
930 MagickCacheResource *resource)
954 assert(cache != (MagickCache *) NULL);
955 assert(cache->signature == MagickCacheSignature);
956 assert(resource != (MagickCacheResource *) NULL);
957 assert(resource->signature == MagickCacheSignature);
958 path=AcquireString(cache->path);
959 (void) ConcatenateString(&path,
"/");
960 (void) ConcatenateString(&path,resource->iri);
961 (void) ConcatenateString(&path,
"/");
962 (void) ConcatenateString(&path,MagickCacheResourceSentinel);
963 sentinel=FileToBlob(path,~0UL,&extent,resource->exception);
964 path=DestroyString(path);
965 if (sentinel == NULL)
967 GetMagickCacheResourceSentinel(resource,(
unsigned char *) sentinel);
968 signature=GetMagickCacheSignature(resource->nonce);
972 if (memcmp(&signature,sentinel,
sizeof(signature)) != 0)
974 sentinel=RelinquishMagickMemory(sentinel);
975 (void) ThrowMagickException(resource->exception,GetMagickModule(),
976 CacheError,
"resource sentinel signature mismatch",
"`%s'",path);
979 sentinel=RelinquishMagickMemory(sentinel);
980 passkey=StringToStringInfo(cache->path);
981 ConcatenateStringInfo(passkey,cache->passkey);
982 ConcatenateStringInfo(passkey,cache->nonce);
983 digest=StringInfoToDigest(passkey);
984 passkey=DestroyStringInfo(passkey);
985 if (strcmp(cache->digest,digest) != 0)
986 SetMagickCacheResourceID(cache,resource);
987 digest=DestroyString(digest);
991 path=AcquireString(cache->path);
992 (void) ConcatenateString(&path,
"/");
993 (void) ConcatenateString(&path,resource->iri);
994 (void) ConcatenateString(&path,
"/");
995 (void) ConcatenateString(&path,resource->id);
996 if (GetPathAttributes(path,&attributes) <= 0)
998 path=DestroyString(path);
999 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1000 CacheError,
"cannot access resource sentinel",
"`%s'",path);
1001 return(MagickFalse);
1003 resource->timestamp=(time_t) attributes.st_ctime;
1004 resource->extent=(size_t) attributes.st_size;
1005 path=DestroyString(path);
1036static void *MapResourceBlob(
int file,
const MapMode mode,
1037 const MagickOffsetType offset,
const size_t length)
1039#if defined(MAGICKCORE_HAVE_MMAP)
1052#if defined(MAP_ANONYMOUS)
1053 flags|=MAP_ANONYMOUS;
1062 protection=PROT_READ;
1068 protection=PROT_WRITE;
1074 protection=PROT_READ | PROT_WRITE;
1079#if !defined(MAGICKCORE_HAVE_HUGEPAGES) || !defined(MAP_HUGETLB)
1080 map=mmap((
char *) NULL,length,protection,flags,file,offset);
1082 map=mmap((
char *) NULL,length,protection,flags | MAP_HUGETLB,file,offset);
1083 if (map == MAP_FAILED)
1084 map=mmap((
char *) NULL,length,protection,flags,file,offset);
1086 if (map == MAP_FAILED)
1098static MagickBooleanType ResourceToBlob(MagickCacheResource *resource,
1114 if (GetPathAttributes(path,&attributes) == MagickFalse)
1116 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1117 CacheError,
"cannot get resource",
"`%s'",resource->iri);
1118 return(MagickFalse);
1120 resource->extent=(size_t) attributes.st_size;
1121 file=open_utf8(path,O_RDONLY | O_BINARY,0);
1122 if (resource->blob != NULL)
1123 DestroyMagickCacheResourceBlob(resource);
1124 resource->blob=MapResourceBlob(file,ReadMode,0,resource->extent);
1125 if (resource->blob != NULL)
1127 resource->memory_mapped=MagickTrue;
1131 resource->blob=AcquireMagickMemory(resource->extent);
1132 if (resource->blob == NULL)
1133 return(MagickFalse);
1134 for (i=0; i < (ssize_t) resource->extent; i+=count)
1139 count=read(file,(
unsigned char *) resource->blob+i,(
size_t)
1140 MagickCacheMin(resource->extent-(
size_t) i,(
size_t) SSIZE_MAX));
1148 if (i < (ssize_t) resource->extent)
1151 resource->blob=RelinquishMagickMemory(resource->blob);
1152 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1153 CacheError,
"cannot get resource",
"`%s'",resource->iri);
1154 return(MagickFalse);
1156 if (close(file) == -1)
1158 resource->blob=RelinquishMagickMemory(resource->blob);
1159 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1160 CacheError,
"cannot get resource",
"`%s'",resource->iri);
1161 return(MagickFalse);
1166MagickExport
void *GetMagickCacheResourceBlob(MagickCache *cache,
1167 MagickCacheResource *resource)
1178 assert(cache != (MagickCache *) NULL);
1179 assert(cache->signature == MagickCacheSignature);
1180 assert(resource != (MagickCacheResource *) NULL);
1181 assert(resource->signature == MagickCacheSignature);
1182 status=GetMagickCacheResource(cache,resource);
1183 if (status == MagickFalse)
1185 path=AcquireString(cache->path);
1186 (void) ConcatenateString(&path,
"/");
1187 (void) ConcatenateString(&path,resource->iri);
1188 (void) ConcatenateString(&path,
"/");
1189 (void) ConcatenateString(&path,resource->id);
1190 status=ResourceToBlob(resource,path);
1191 path=DestroyString(path);
1192 if (status == MagickFalse)
1193 return((
void *) NULL);
1194 return((
void *) resource->blob);
1223MagickExport
char *GetMagickCacheResourceException(
1224 const MagickCacheResource *resource,ExceptionType *severity)
1232 assert(resource != (
const MagickCacheResource *) NULL);
1233 assert(resource->signature == MagickCacheSignature);
1234 if (resource->debug != MagickFalse)
1235 (void) LogMagickEvent(WandEvent,GetMagickModule(),
"%s",resource->iri);
1236 assert(severity != (ExceptionType *) NULL);
1237 *severity=resource->exception->severity;
1238 description=(
char *) AcquireQuantumMemory(2UL*MagickPathExtent,
1239 sizeof(*description));
1240 if (description == (
char *) NULL)
1242 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1243 CacheError,
"MemoryAllocationFailed",
"`%s'",resource->iri);
1244 return((
char *) NULL);
1247 if (resource->exception->reason != (
char *) NULL)
1248 (void) CopyMagickString(description,GetLocaleExceptionMessage(
1249 resource->exception->severity,resource->exception->reason),
1251 if (resource->exception->description != (
char *) NULL)
1253 (void) ConcatenateMagickString(description,
" (",MagickPathExtent);
1254 (void) ConcatenateMagickString(description,GetLocaleExceptionMessage(
1255 resource->exception->severity,resource->exception->description),
1257 (void) ConcatenateMagickString(description,
")",MagickPathExtent);
1259 return(description);
1289MagickExport MagickBooleanType GetMagickCacheResourceID(MagickCache *cache,
1290 const size_t length,
char *
id)
1305 assert(cache != (
const MagickCache *) NULL);
1306 assert(cache->signature == MagickCacheSignature);
1307 for (j=0; j < (ssize_t) length; j++)
1309 passkey=GetRandomKey(cache->random_info,length);
1310 if (passkey == (StringInfo *) NULL)
1311 return(MagickFalse);
1312 code=GetStringInfoDatum(passkey);
1313 for (i=0; i < (ssize_t) length; i++)
1315 if ((code[i] <= 32) || ((code[i] <= 0x9f && code[i] > 0x7F)))
1317 id[j++]=(char) code[i];
1318 if (j == (ssize_t) length)
1321 passkey=DestroyStringInfo(passkey);
1358MagickExport Image *GetMagickCacheResourceImage(MagickCache *cache,
1359 MagickCacheResource *resource,
const char *extract)
1376 assert(cache != (MagickCache *) NULL);
1377 assert(cache->signature == MagickCacheSignature);
1378 assert(resource != (MagickCacheResource *) NULL);
1379 assert(resource->signature == MagickCacheSignature);
1380 status=GetMagickCacheResource(cache,resource);
1381 if (status == MagickFalse)
1382 return((Image *) NULL);
1383 path=AcquireString(cache->path);
1384 (void) ConcatenateString(&path,
"/");
1385 (void) ConcatenateString(&path,resource->iri);
1386 (void) ConcatenateString(&path,
"/");
1387 (void) ConcatenateString(&path,resource->id);
1388 if (extract != (
const char *) NULL)
1390 (void) ConcatenateString(&path,
"[");
1391 (void) ConcatenateString(&path,extract);
1392 (void) ConcatenateString(&path,
"]");
1394 if (strlen(path) > (MagickPathExtent-2))
1396 path=DestroyString(path);
1398 return((Image *) NULL);
1400 image_info=AcquireImageInfo();
1401 (void) CopyMagickString(image_info->filename,path,MagickPathExtent);
1402 (void) CopyMagickString(image_info->magick,
"MPC",MagickPathExtent);
1403 exception=AcquireExceptionInfo();
1404 if (resource->blob != NULL)
1405 DestroyMagickCacheResourceBlob(resource);
1406 resource->blob=(
void *) ReadImage(image_info,exception);
1407 exception=DestroyExceptionInfo(exception);
1408 if (resource->blob == (
void *) NULL)
1409 (void) ThrowMagickException(resource->exception,GetMagickModule(),
1410 CacheError,
"cannot get resource",
"`%s'",resource->iri);
1413 const Image *image = (
const Image *) resource->blob;
1414 resource->columns=image->columns;
1415 resource->rows=image->rows;
1417 path=DestroyString(path);
1418 image_info=DestroyImageInfo(image_info);
1419 return((Image *) resource->blob);
1445MagickExport
char *GetMagickCacheResourceIRI(
1446 const MagickCacheResource *resource)
1448 assert(resource != (MagickCacheResource *) NULL);
1449 assert(resource->signature == MagickCacheSignature);
1450 return(resource->iri);
1478MagickExport
char *GetMagickCacheResourceMeta(MagickCache *cache,
1479 MagickCacheResource *resource)
1490 assert(cache != (MagickCache *) NULL);
1491 assert(cache->signature == MagickCacheSignature);
1492 assert(resource != (MagickCacheResource *) NULL);
1493 assert(resource->signature == MagickCacheSignature);
1494 status=GetMagickCacheResource(cache,resource);
1495 if (status == MagickFalse)
1496 return((
char *) NULL);
1497 path=AcquireString(cache->path);
1498 (void) ConcatenateString(&path,
"/");
1499 (void) ConcatenateString(&path,resource->iri);
1500 (void) ConcatenateString(&path,
"/");
1501 (void) ConcatenateString(&path,resource->id);
1502 if (strlen(path) > (MagickPathExtent-2))
1504 path=DestroyString(path);
1506 return((
char *) NULL);
1508 status=ResourceToBlob(resource,path);
1509 path=DestroyString(path);
1510 if (status == MagickFalse)
1511 return((
char *) NULL);
1512 return((
char *) resource->blob);
1539MagickExport
void GetMagickCacheResourceSize(
1540 const MagickCacheResource *resource,
size_t *columns,
size_t *rows)
1542 assert(resource != (MagickCacheResource *) NULL);
1543 assert(resource->signature == MagickCacheSignature);
1544 *columns=resource->columns;
1545 *rows=resource->rows;
1572MagickExport time_t GetMagickCacheResourceTimestamp(
1573 const MagickCacheResource *resource)
1575 assert(resource != (MagickCacheResource *) NULL);
1576 assert(resource->signature == MagickCacheSignature);
1577 return(resource->timestamp);
1603MagickExport time_t GetMagickCacheResourceTTL(
1604 const MagickCacheResource *resource)
1606 assert(resource != (MagickCacheResource *) NULL);
1607 assert(resource->signature == MagickCacheSignature);
1608 return(resource->ttl);
1635MagickExport MagickCacheResourceType GetMagickCacheResourceType(
1636 const MagickCacheResource *resource)
1638 assert(resource != (MagickCacheResource *) NULL);
1639 assert(resource->signature == MagickCacheSignature);
1640 return(resource->resource_type);
1667MagickExport
size_t GetMagickCacheResourceVersion(
1668 const MagickCacheResource *resource)
1670 assert(resource != (MagickCacheResource *) NULL);
1671 assert(resource->signature == MagickCacheSignature);
1672 return(resource->version);
1698MagickExport time_t GetMagickCacheTimestamp(
const MagickCache *cache)
1700 assert(cache != (MagickCache *) NULL);
1701 assert(cache->signature == MagickCacheSignature);
1702 return(cache->timestamp);
1733MagickExport MagickBooleanType IdentifyMagickCacheResource(MagickCache *cache,
1734 MagickCacheResource *resource,FILE *file)
1737 extent[MagickPathExtent],
1738 iso8601[
sizeof(
"9999-99-99T99:99:99Z")],
1740 size[MagickPathExtent];
1754 assert(cache != (MagickCache *) NULL);
1755 assert(cache->signature == MagickCacheSignature);
1756 path=AcquireString(cache->path);
1757 (void) ConcatenateString(&path,
"/");
1758 (void) ConcatenateString(&path,resource->iri);
1759 (void) ConcatenateString(&path,
"/");
1760 (void) ConcatenateString(&path,resource->id);
1761 status=GetMagickCacheResource(cache,resource);
1763 if (resource->resource_type == ImageResourceType)
1764 (void) snprintf(size,MagickPathExtent,
"[%gx%g]",(
double) resource->columns,
1765 (
double) resource->rows);
1766 (void) FormatMagickSize(GetMagickCacheResourceExtent(resource),MagickTrue,
1767 "B",MagickPathExtent,extent);
1768 (void) GetMagickUTCTime(&resource->timestamp,×tamp);
1769 (void) strftime(iso8601,
sizeof(iso8601),
"%FT%TZ",×tamp);
1771 if ((resource->ttl != 0) && ((resource->timestamp+resource->ttl) < time(0)))
1773 (void) fprintf(file,
"%s%s %s %g:%02g:%02g:%02g%c %s\n",
1774 GetMagickCacheResourceIRI(resource),size,extent,
1775 ceil((
double) (resource->ttl/(3600*24))),
1776 ceil((
double) ((resource->ttl % (24*3600))/3600)),
1777 ceil((
double) ((resource->ttl % 3600)/60)),
1778 ceil((
double) ((resource->ttl % 3600) % 60)),expired,iso8601);
1779 path=DestroyString(path);
1810MagickExport MagickBooleanType IsMagickCacheResourceExpired(MagickCache *cache,
1811 MagickCacheResource *resource)
1816 assert(cache != (MagickCache *) NULL);
1817 assert(cache->signature == MagickCacheSignature);
1818 status=GetMagickCacheResource(cache,resource);
1819 if (status == MagickFalse)
1821 if ((resource->ttl != 0) && ((resource->timestamp+resource->ttl) < time(0)))
1828 return(MagickFalse);
1862MagickExport MagickBooleanType IterateMagickCacheResources(MagickCache *cache,
1863 const char *iri,
const void *context,MagickBooleanType (*callback)(
1864 MagickCache *cache,MagickCacheResource *resource,
const void *context))
1890 assert(cache != (MagickCache *) NULL);
1891 assert(cache->signature == MagickCacheSignature);
1893 head=(
struct ResourceNode *) AcquireCriticalMemory(
sizeof(*node));
1894 (void) memset(head,0,
sizeof(*head));
1895 head->path=AcquireString(cache->path);
1896 (void) ConcatenateString(&head->path,
"/");
1897 (void) ConcatenateString(&head->path,iri);
1901 for (p=head; p != (
struct ResourceNode *) NULL; p=p->next)
1903 directory=opendir(p->path);
1904 if (directory == (DIR *) NULL)
1909 while ((entry=readdir(directory)) != (
struct dirent *) NULL)
1911 path=AcquireString(p->path);
1912 (void) ConcatenateString(&path,
"/");
1913 (void) ConcatenateString(&path,entry->d_name);
1914 if (GetPathAttributes(path,&attributes) <= 0)
1916 path=DestroyString(path);
1919 if ((strcmp(entry->d_name,
".") == 0) ||
1920 (strcmp(entry->d_name,
"..") == 0))
1922 path=DestroyString(path);
1925 if (S_ISDIR(attributes.st_mode) != 0)
1927 node=(
struct ResourceNode *) AcquireCriticalMemory(
sizeof(*node));
1928 (void) memset(node,0,
sizeof(*node));
1936 if (S_ISREG(attributes.st_mode) != 0)
1938 char *sentinel = ConstantString(path);
1939 GetPathComponent(path,TailPath,sentinel);
1940 if (strcmp(sentinel,MagickCacheResourceSentinel) == 0)
1945 GetPathComponent(path,HeadPath,path);
1946 resource=AcquireMagickCacheResource(cache,path+
1947 strlen(cache->path)+1);
1948 status=GetMagickCacheResource(cache,resource);
1949 if (status != MagickFalse)
1951 status=callback(cache,resource,context);
1952 if (status == MagickFalse)
1954 path=DestroyString(path);
1955 resource=DestroyMagickCacheResource(resource);
1956 sentinel=DestroyString(sentinel);
1960 resource=DestroyMagickCacheResource(resource);
1962 path=DestroyString(path);
1963 sentinel=DestroyString(sentinel);
1966 (void) closedir(directory);
1975 node->path=DestroyString(node->path);
1976 node=(
struct ResourceNode *) RelinquishMagickMemory(node);
2011static StringInfo *SetMagickCacheResourceSentinel(
2012 const MagickCacheResource *resource)
2026 meta=AcquireStringInfo(MagickPathExtent);
2027 p=GetStringInfoDatum(meta);
2028 signature=GetMagickCacheSignature(resource->nonce);
2029 (void) memcpy(p,&signature,
sizeof(signature));
2030 p+=
sizeof(signature);
2031 (void) memcpy(p,GetStringInfoDatum(resource->nonce),
2032 GetStringInfoLength(resource->nonce));
2033 p+=GetStringInfoLength(resource->nonce);
2034 (void) memcpy(p,&resource->ttl,
sizeof(resource->ttl));
2035 p+=
sizeof(resource->ttl);
2036 (void) memcpy(p,&resource->columns,
sizeof(resource->columns));
2037 p+=
sizeof(resource->columns);
2038 (void) memcpy(p,&resource->rows,
sizeof(resource->rows));
2039 p+=
sizeof(resource->rows);
2040 (void) memcpy(p,resource->id,MagickCacheDigestExtent);
2041 p+=MagickCacheDigestExtent;
2042 SetStringInfoLength(meta,(
size_t) (p-GetStringInfoDatum(meta)));
2046MagickExport MagickBooleanType PutMagickCacheResource(MagickCache *cache,
2047 MagickCacheResource *resource)
2061 assert(cache != (MagickCache *) NULL);
2062 assert(cache->signature == MagickCacheSignature);
2063 assert(resource != (MagickCacheResource *) NULL);
2064 assert(resource->signature == MagickCacheSignature);
2065 status=GetMagickCacheResource(cache,resource);
2066 if (status != MagickFalse)
2068 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2069 CacheError,
"cannot overwrite resource",
"`%s'",resource->iri);
2070 return(MagickFalse);
2072 path=AcquireString(cache->path);
2073 (void) ConcatenateString(&path,
"/");
2074 (void) ConcatenateString(&path,resource->iri);
2075 if (MagickCreatePath(path) == MagickFalse)
2077 path=DestroyString(path);
2078 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2079 CacheError,
"cannot put resource",
"`%s'",path);
2080 return(MagickFalse);
2085 (void) ConcatenateString(&path,
"/");
2086 (void) ConcatenateString(&path,MagickCacheResourceSentinel);
2087 if (IsPathAccessible(path) != MagickFalse)
2089 path=DestroyString(path);
2091 return(MagickFalse);
2093 SetMagickCacheResourceID(cache,resource);
2094 meta=SetMagickCacheResourceSentinel(resource);
2095 status=BlobToFile(path,GetStringInfoDatum(meta),GetStringInfoLength(meta),
2096 resource->exception);
2097 meta=DestroyStringInfo(meta);
2098 path=DestroyString(path);
2131MagickExport MagickBooleanType PutMagickCacheResourceBlob(MagickCache *cache,
2132 MagickCacheResource *resource,
const size_t extent,
const void *blob)
2143 status=PutMagickCacheResource(cache,resource);
2144 if (status == MagickFalse)
2145 return(MagickFalse);
2146 path=AcquireString(cache->path);
2147 (void) ConcatenateString(&path,
"/");
2148 (void) ConcatenateString(&path,resource->iri);
2149 (void) ConcatenateString(&path,
"/");
2150 (void) ConcatenateString(&path,resource->id);
2151 status=BlobToFile(path,blob,extent,cache->exception);
2152 path=DestroyString(path);
2184MagickExport MagickBooleanType PutMagickCacheResourceImage(MagickCache *cache,
2185 MagickCacheResource *resource,
const Image *image)
2202 resource->columns=image->columns;
2203 resource->rows=image->rows;
2204 status=PutMagickCacheResource(cache,resource);
2205 if (status == MagickFalse)
2207 path=AcquireString(cache->path);
2208 (void) ConcatenateString(&path,
"/");
2209 (void) ConcatenateString(&path,resource->iri);
2210 if (MagickCreatePath(path) == MagickFalse)
2211 return(MagickFalse);
2212 image_info=AcquireImageInfo();
2213 images=CloneImageList(image,resource->exception);
2214 (void) ConcatenateString(&path,
"/");
2215 (void) ConcatenateString(&path,resource->id);
2216 (void) FormatLocaleString(images->filename,MagickPathExtent,
"mpc:%s",path);
2217 path=DestroyString(path);
2218 status=WriteImages(image_info,images,images->filename,resource->exception);
2219 images=DestroyImageList(images);
2220 image_info=DestroyImageInfo(image_info);
2252MagickExport MagickBooleanType PutMagickCacheResourceMeta(MagickCache *cache,
2253 MagickCacheResource *resource,
const char *properties)
2264 status=PutMagickCacheResource(cache,resource);
2265 if (status == MagickFalse)
2266 return(MagickFalse);
2267 path=AcquireString(cache->path);
2268 (void) ConcatenateString(&path,
"/");
2269 (void) ConcatenateString(&path,resource->iri);
2270 (void) ConcatenateString(&path,
"/");
2271 (void) ConcatenateString(&path,resource->id);
2272 status=BlobToFile(path,properties,strlen(properties)+1,cache->exception);
2273 path=DestroyString(path);
2302MagickExport MagickBooleanType SetMagickCacheResourceIRI(MagickCache *cache,
2303 MagickCacheResource *resource,
const char *iri)
2312 assert(resource != (MagickCacheResource *) NULL);
2313 assert(resource->signature == MagickCoreSignature);
2314 if (resource->iri != (
char *) NULL)
2315 resource->iri=DestroyString(resource->iri);
2316 resource->iri=ConstantString(iri);
2317 path=ConstantString(iri);
2319 if (p == (
char *) NULL)
2320 return(MagickFalse);
2321 if (resource->project != (
char *) NULL)
2322 resource->project=DestroyString(resource->project);
2323 resource->project=ConstantString(p);
2325 if (p == (
char *) NULL)
2326 return(MagickFalse);
2327 if (resource->type != (
char *) NULL)
2328 resource->type=DestroyString(resource->type);
2329 resource->type=ConstantString(p);
2330 path=DestroyString(path);
2331 if (resource->id != (
char *) NULL)
2332 resource->id=DestroyString(resource->id);
2333 resource->id=ConstantString(
"");
2334 if (LocaleCompare(resource->type,
"*") == 0)
2335 resource->resource_type=WildResourceType;
2337 if (LocaleCompare(resource->type,
"blob") == 0)
2338 resource->resource_type=BlobResourceType;
2340 if (LocaleCompare(resource->type,
"image") == 0)
2341 resource->resource_type=ImageResourceType;
2343 if (LocaleCompare(resource->type,
"meta") == 0)
2344 resource->resource_type=MetaResourceType;
2347 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2348 CacheError,
"unknown resource type",
"`%s'",resource->type);
2349 return(MagickFalse);
2380MagickExport
void SetMagickCacheResourceTTL(MagickCacheResource *resource,
2383 assert(resource != (MagickCacheResource *) NULL);
2384 assert(resource->signature == MagickCoreSignature);
2413MagickExport MagickBooleanType SetMagickCacheResourceVersion(
2414 MagickCacheResource *resource,
const size_t version)
2416 assert(resource != (MagickCacheResource *) NULL);
2417 assert(resource->signature == MagickCoreSignature);
2418 resource->version=version;