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)
264 if (GetPathAttributes(path,&attributes) <= 0)
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);
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);
304 sentinel=RelinquishMagickMemory(sentinel);
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)
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(
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(
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,
606 assert(cache->signature == MagickCacheSignature);
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);
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);
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;
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);
813MagickExport
char *GetMagickCacheException(
const MagickCache *cache,
814 ExceptionType *severity)
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);
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,
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,
955 assert(cache->signature == MagickCacheSignature);
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)
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,
1179 assert(cache->signature == MagickCacheSignature);
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(
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)
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,
1377 assert(cache->signature == MagickCacheSignature);
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(
1449 assert(resource->signature == MagickCacheSignature);
1450 return(resource->iri);
1478MagickExport
char *GetMagickCacheResourceMeta(
MagickCache *cache,
1491 assert(cache->signature == MagickCacheSignature);
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(
1543 assert(resource->signature == MagickCacheSignature);
1544 *columns=resource->columns;
1545 *rows=resource->rows;
1572MagickExport time_t GetMagickCacheResourceTimestamp(
1576 assert(resource->signature == MagickCacheSignature);
1577 return(resource->timestamp);
1603MagickExport time_t GetMagickCacheResourceTTL(
1607 assert(resource->signature == MagickCacheSignature);
1608 return(resource->ttl);
1635MagickExport MagickCacheResourceType GetMagickCacheResourceType(
1639 assert(resource->signature == MagickCacheSignature);
1640 return(resource->resource_type);
1667MagickExport
size_t GetMagickCacheResourceVersion(
1671 assert(resource->signature == MagickCacheSignature);
1672 return(resource->version);
1698MagickExport time_t GetMagickCacheTimestamp(
const MagickCache *cache)
1701 assert(cache->signature == MagickCacheSignature);
1702 return(cache->timestamp);
1733MagickExport MagickBooleanType IdentifyMagickCacheResource(
MagickCache *cache,
1737 extent[MagickPathExtent],
1738 iso8601[
sizeof(
"9999-99-99T99:99:99Z")],
1740 size[MagickPathExtent];
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:%g:%g:%g%c %s\n",GetMagickCacheResourceIRI(
1774 resource),size,extent,(
double) (resource->ttl/(3600*24)),(
double)
1775 ((resource->ttl % (24*3600))/3600),(
double) ((resource->ttl % 3600)/60),
1776 (
double) ((resource->ttl % 3600) % 60),expired,iso8601);
1777 path=DestroyString(path);
1808MagickExport MagickBooleanType IsMagickCacheResourceExpired(
MagickCache *cache,
1815 assert(cache->signature == MagickCacheSignature);
1816 status=GetMagickCacheResource(cache,resource);
1817 if (status == MagickFalse)
1819 if ((resource->ttl != 0) && ((resource->timestamp+resource->ttl) < time(0)))
1826 return(MagickFalse);
1860MagickExport MagickBooleanType IterateMagickCacheResources(
MagickCache *cache,
1861 const char *iri,
const void *context,MagickBooleanType (*callback)(
1889 assert(cache->signature == MagickCacheSignature);
1891 head=(
struct ResourceNode *) AcquireCriticalMemory(
sizeof(*node));
1892 (void) memset(head,0,
sizeof(*head));
1893 head->path=AcquireString(cache->path);
1894 (void) ConcatenateString(&head->path,
"/");
1895 (void) ConcatenateString(&head->path,iri);
1899 for (p=head; p != (
struct ResourceNode *) NULL; p=p->next)
1901 directory=opendir(p->path);
1902 if (directory == (DIR *) NULL)
1907 while ((entry=readdir(directory)) != (
struct dirent *) NULL)
1909 path=AcquireString(p->path);
1910 (void) ConcatenateString(&path,
"/");
1911 (void) ConcatenateString(&path,entry->d_name);
1912 if (GetPathAttributes(path,&attributes) <= 0)
1914 path=DestroyString(path);
1917 if ((strcmp(entry->d_name,
".") == 0) ||
1918 (strcmp(entry->d_name,
"..") == 0))
1920 path=DestroyString(path);
1923 if (S_ISDIR(attributes.st_mode) != 0)
1925 node=(
struct ResourceNode *) AcquireCriticalMemory(
sizeof(*node));
1926 (void) memset(node,0,
sizeof(*node));
1934 if (S_ISREG(attributes.st_mode) != 0)
1936 char *sentinel = ConstantString(path);
1937 GetPathComponent(path,TailPath,sentinel);
1938 if (strcmp(sentinel,MagickCacheResourceSentinel) == 0)
1943 GetPathComponent(path,HeadPath,path);
1944 resource=AcquireMagickCacheResource(cache,path+
1945 strlen(cache->path)+1);
1946 status=GetMagickCacheResource(cache,resource);
1947 if (status != MagickFalse)
1949 status=callback(cache,resource,context);
1950 if (status == MagickFalse)
1952 path=DestroyString(path);
1953 resource=DestroyMagickCacheResource(resource);
1954 sentinel=DestroyString(sentinel);
1958 resource=DestroyMagickCacheResource(resource);
1960 path=DestroyString(path);
1961 sentinel=DestroyString(sentinel);
1964 (void) closedir(directory);
1973 node->path=DestroyString(node->path);
1974 node=(
struct ResourceNode *) RelinquishMagickMemory(node);
2009static StringInfo *SetMagickCacheResourceSentinel(
2024 meta=AcquireStringInfo(MagickPathExtent);
2025 p=GetStringInfoDatum(meta);
2026 signature=GetMagickCacheSignature(resource->nonce);
2027 (void) memcpy(p,&signature,
sizeof(signature));
2028 p+=
sizeof(signature);
2029 (void) memcpy(p,GetStringInfoDatum(resource->nonce),
2030 GetStringInfoLength(resource->nonce));
2031 p+=GetStringInfoLength(resource->nonce);
2032 (void) memcpy(p,&resource->ttl,
sizeof(resource->ttl));
2033 p+=
sizeof(resource->ttl);
2034 (void) memcpy(p,&resource->columns,
sizeof(resource->columns));
2035 p+=
sizeof(resource->columns);
2036 (void) memcpy(p,&resource->rows,
sizeof(resource->rows));
2037 p+=
sizeof(resource->rows);
2038 (void) memcpy(p,resource->id,MagickCacheDigestExtent);
2039 p+=MagickCacheDigestExtent;
2040 SetStringInfoLength(meta,(
size_t) (p-GetStringInfoDatum(meta)));
2044MagickExport MagickBooleanType PutMagickCacheResource(
MagickCache *cache,
2060 assert(cache->signature == MagickCacheSignature);
2062 assert(resource->signature == MagickCacheSignature);
2063 status=GetMagickCacheResource(cache,resource);
2064 if (status != MagickFalse)
2066 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2067 CacheError,
"cannot overwrite resource",
"`%s'",resource->iri);
2068 return(MagickFalse);
2070 path=AcquireString(cache->path);
2071 (void) ConcatenateString(&path,
"/");
2072 (void) ConcatenateString(&path,resource->iri);
2073 if (MagickCreatePath(path) == MagickFalse)
2075 path=DestroyString(path);
2076 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2077 CacheError,
"cannot put resource",
"`%s'",path);
2078 return(MagickFalse);
2083 (void) ConcatenateString(&path,
"/");
2084 (void) ConcatenateString(&path,MagickCacheResourceSentinel);
2085 if (IsPathAccessible(path) != MagickFalse)
2087 path=DestroyString(path);
2089 return(MagickFalse);
2091 SetMagickCacheResourceID(cache,resource);
2092 meta=SetMagickCacheResourceSentinel(resource);
2093 status=BlobToFile(path,GetStringInfoDatum(meta),GetStringInfoLength(meta),
2094 resource->exception);
2095 meta=DestroyStringInfo(meta);
2096 path=DestroyString(path);
2129MagickExport MagickBooleanType PutMagickCacheResourceBlob(
MagickCache *cache,
2141 status=PutMagickCacheResource(cache,resource);
2142 if (status == MagickFalse)
2143 return(MagickFalse);
2144 path=AcquireString(cache->path);
2145 (void) ConcatenateString(&path,
"/");
2146 (void) ConcatenateString(&path,resource->iri);
2147 (void) ConcatenateString(&path,
"/");
2148 (void) ConcatenateString(&path,resource->id);
2149 status=BlobToFile(path,blob,extent,cache->exception);
2150 path=DestroyString(path);
2182MagickExport MagickBooleanType PutMagickCacheResourceImage(
MagickCache *cache,
2200 resource->columns=image->columns;
2201 resource->rows=image->rows;
2202 status=PutMagickCacheResource(cache,resource);
2203 if (status == MagickFalse)
2205 path=AcquireString(cache->path);
2206 (void) ConcatenateString(&path,
"/");
2207 (void) ConcatenateString(&path,resource->iri);
2208 if (MagickCreatePath(path) == MagickFalse)
2209 return(MagickFalse);
2210 image_info=AcquireImageInfo();
2211 images=CloneImageList(image,resource->exception);
2212 (void) ConcatenateString(&path,
"/");
2213 (void) ConcatenateString(&path,resource->id);
2214 (void) FormatLocaleString(images->filename,MagickPathExtent,
"mpc:%s",path);
2215 path=DestroyString(path);
2216 status=WriteImages(image_info,images,images->filename,resource->exception);
2217 images=DestroyImageList(images);
2218 image_info=DestroyImageInfo(image_info);
2250MagickExport MagickBooleanType PutMagickCacheResourceMeta(
MagickCache *cache,
2262 status=PutMagickCacheResource(cache,resource);
2263 if (status == MagickFalse)
2264 return(MagickFalse);
2265 path=AcquireString(cache->path);
2266 (void) ConcatenateString(&path,
"/");
2267 (void) ConcatenateString(&path,resource->iri);
2268 (void) ConcatenateString(&path,
"/");
2269 (void) ConcatenateString(&path,resource->id);
2270 status=BlobToFile(path,properties,strlen(properties)+1,cache->exception);
2271 path=DestroyString(path);
2300MagickExport MagickBooleanType SetMagickCacheResourceIRI(
MagickCache *cache,
2311 assert(resource->signature == MagickCoreSignature);
2312 if (resource->iri != (
char *) NULL)
2313 resource->iri=DestroyString(resource->iri);
2314 resource->iri=ConstantString(iri);
2315 path=ConstantString(iri);
2317 if (p == (
char *) NULL)
2318 return(MagickFalse);
2319 if (resource->project != (
char *) NULL)
2320 resource->project=DestroyString(resource->project);
2321 resource->project=ConstantString(p);
2323 if (p == (
char *) NULL)
2324 return(MagickFalse);
2325 if (resource->type != (
char *) NULL)
2326 resource->type=DestroyString(resource->type);
2327 resource->type=ConstantString(p);
2328 path=DestroyString(path);
2329 if (resource->id != (
char *) NULL)
2330 resource->id=DestroyString(resource->id);
2331 resource->id=ConstantString(
"");
2332 if (LocaleCompare(resource->type,
"*") == 0)
2333 resource->resource_type=WildResourceType;
2335 if (LocaleCompare(resource->type,
"blob") == 0)
2336 resource->resource_type=BlobResourceType;
2338 if (LocaleCompare(resource->type,
"image") == 0)
2339 resource->resource_type=ImageResourceType;
2341 if (LocaleCompare(resource->type,
"meta") == 0)
2342 resource->resource_type=MetaResourceType;
2345 (void) ThrowMagickException(resource->exception,GetMagickModule(),
2346 CacheError,
"unknown resource type",
"`%s'",resource->type);
2347 return(MagickFalse);
2382 assert(resource->signature == MagickCoreSignature);
2411MagickExport MagickBooleanType SetMagickCacheResourceVersion(
2415 assert(resource->signature == MagickCoreSignature);
2416 resource->version=version;