2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % DDDD IIIII SSSSS TTTTT RRRR IIIII BBBB U U TTTTT EEEEE %
6 % D D I SS T R R I B B U U T E %
7 % D D I SSS T RRRR I BBBB U U T EEE %
8 % D D I SS T R R I B B U U T E %
9 % DDDDA IIIII SSSSS T R R IIIII BBBB UUU T EEEEE %
11 % CCCC AAA CCCC H H EEEEE %
13 % C AAAAA C HHHHH EEE %
15 % CCCC A A CCCC H H EEEEE %
18 % MagickCore Distributed Pixel Cache Methods %
25 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
31 % http://www.imagemagick.org/script/license.php %
33 % Unless required by applicable law or agreed to in writing, software %
34 % distributed under the License is distributed on an "AS IS" BASIS, %
35 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
36 % See the License for the specific language governing permissions and %
37 % limitations under the License. %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 % A distributed pixel cache is an extension of the traditional pixel cache
42 % available on a single host. The distributed pixel cache may span multiple
43 % servers so that it can grow in size and transactional capacity to support
44 % very large images. Start up the pixel cache server on one or more machines.
45 % When you read or operate on an image and the local pixel cache resources are
46 % exhausted, ImageMagick contacts one or more of these remote pixel servers to
47 % store or retrieve pixels.
54 #include "MagickCore/studio.h"
55 #include "MagickCore/cache.h"
56 #include "MagickCore/cache-private.h"
57 #include "MagickCore/distribute-cache.h"
58 #include "MagickCore/distribute-cache-private.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/geometry.h"
62 #include "MagickCore/image.h"
63 #include "MagickCore/list.h"
64 #include "MagickCore/locale_.h"
65 #include "MagickCore/memory_.h"
66 #include "MagickCore/nt-base-private.h"
67 #include "MagickCore/pixel.h"
68 #include "MagickCore/policy.h"
69 #include "MagickCore/random_.h"
70 #include "MagickCore/registry.h"
71 #include "MagickCore/splay-tree.h"
72 #include "MagickCore/string_.h"
73 #include "MagickCore/string-private.h"
74 #include "MagickCore/version.h"
75 #include "MagickCore/version-private.h"
76 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
77 #include <netinet/in.h>
79 #include <sys/socket.h>
80 #include <arpa/inet.h>
84 #define send(file,buffer,length,flags) 0
85 #define recv(file,buffer,length,flags) 0
91 #define DPCHostname "127.0.0.1"
92 #define DPCPendingConnections 10
94 #define DPCSessionKeyLength 8
96 # define MSG_NOSIGNAL 0
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 + A c q u i r e D i s t r i b u t e C a c h e I n f o %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
112 % The format of the AcquireDistributeCacheInfo method is:
114 % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
116 % A description of each parameter follows:
118 % o exception: return any errors or warnings in this structure.
122 static inline MagickSizeType MagickMin(const MagickSizeType x,
123 const MagickSizeType y)
130 static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
131 unsigned char *restrict message)
133 register MagickOffsetType
139 #if !defined(MAGICKCORE_HAVE_SOCKET) || !defined(MAGICKCORE_THREAD_SUPPORT)
140 magick_unreferenced(file);
141 magick_unreferenced(message);
145 for (i=0; i < (MagickOffsetType) length; i+=count)
147 count=recv(file,message+i,(size_t) MagickMin(length-i,(MagickSizeType)
159 static int ConnectPixelCacheServer(const char *hostname,const int port,
160 size_t *session_key,ExceptionInfo *exception)
162 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
164 service[MaxTextExtent];
181 secret[MaxTextExtent];
184 Connect to distributed pixel cache and get session key.
187 shared_secret=GetPolicyValue("shared-secret");
188 if (shared_secret == (const char *) NULL)
190 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
191 "DistributedPixelCache","'%s'","shared secret expected");
194 (void) ResetMagickMemory(&hint,0,sizeof(hint));
195 hint.ai_family=AF_INET;
196 hint.ai_socktype=SOCK_STREAM;
197 hint.ai_flags=AI_PASSIVE;
198 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
199 status=getaddrinfo(hostname,service,&hint,&result);
202 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
203 "DistributedPixelCache","'%s'",hostname);
206 client_socket=socket(result->ai_family,result->ai_socktype,
207 result->ai_protocol);
208 if (client_socket == -1)
210 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
211 "DistributedPixelCache","'%s'",hostname);
214 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
217 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
218 "DistributedPixelCache","'%s'",hostname);
221 count=recv(client_socket,secret,MaxTextExtent,0);
227 nonce=AcquireStringInfo(count);
228 (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
229 *session_key=GetMagickSignature(nonce);
230 nonce=DestroyStringInfo(nonce);
232 if (*session_key == 0)
234 close(client_socket);
237 return(client_socket);
239 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
240 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
245 static char *GetHostname(int *port,ExceptionInfo *exception)
262 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
264 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",exception);
265 if (hosts == (char *) NULL)
268 return(AcquireString(DPCHostname));
270 (void) SubstituteString(&hosts,","," ");
271 hostlist=StringToArgv(hosts,&argc);
272 hosts=DestroyString(hosts);
273 if (hostlist == (char **) NULL)
276 return(AcquireString(DPCHostname));
278 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
279 for (i=0; i < (ssize_t) argc; i++)
280 hostlist[i]=DestroyString(hostlist[i]);
281 hostlist=(char **) RelinquishMagickMemory(hostlist);
282 (void) SubstituteString(&hosts,":"," ");
283 hostlist=StringToArgv(hosts,&argc);
284 if (hostlist == (char **) NULL)
287 return(AcquireString(DPCHostname));
289 host=AcquireString(hostlist[1]);
290 if (hostlist[2] == (char *) NULL)
293 *port=StringToLong(hostlist[2]);
294 for (i=0; i < (ssize_t) argc; i++)
295 hostlist[i]=DestroyString(hostlist[i]);
296 hostlist=(char **) RelinquishMagickMemory(hostlist);
300 MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
301 ExceptionInfo *exception)
313 Connect to the distributed pixel cache server.
315 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
316 if (server_info == (DistributeCacheInfo *) NULL)
317 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
318 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
319 server_info->signature=MagickSignature;
321 hostname=GetHostname(&server_info->port,exception);
323 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
324 &session_key,exception);
325 server_info->session_key=session_key;
326 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
327 hostname=DestroyString(hostname);
328 if (server_info->file == -1)
329 server_info=DestroyDistributeCacheInfo(server_info);
330 server_info->debug=IsEventLogging();
335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 + D e s t r o y D i s t r i b u t e C a c h e I n f o %
343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 % DestroyDistributeCacheInfo() deallocates memory associated with an
346 % DistributeCacheInfo structure.
348 % The format of the DestroyDistributeCacheInfo method is:
350 % DistributeCacheInfo *DestroyDistributeCacheInfo(
351 % DistributeCacheInfo *server_info)
353 % A description of each parameter follows:
355 % o server_info: the distributed cache info.
358 MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
359 DistributeCacheInfo *server_info)
361 assert(server_info != (DistributeCacheInfo *) NULL);
362 assert(server_info->signature == MagickSignature);
363 if (server_info->file > 0)
364 (void) close(server_info->file);
365 server_info->signature=(~MagickSignature);
366 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 + D i s t r i b u t e P i x e l C a c h e S e r v e r %
379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381 % DistributePixelCacheServer() waits on the specified port for commands to
382 % create, read, update, or destroy a pixel cache.
384 % The format of the DistributePixelCacheServer() method is:
386 % void DistributePixelCacheServer(const int port)
388 % A description of each parameter follows:
390 % o port: connect the distributed pixel cache at this port.
392 % o exception: return any errors or warnings in this structure.
396 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
397 int magick_unused(file),const size_t session_key)
400 Destroy distributed pixel cache.
402 magick_unreferenced(file);
403 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
406 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
407 const unsigned char *restrict message)
412 register MagickOffsetType
415 #if !defined(MAGICKCORE_HAVE_SOCKET) || !defined(MAGICKCORE_THREAD_SUPPORT)
416 magick_unreferenced(file);
417 magick_unreferenced(message);
421 Ensure a complete message is sent.
424 for (i=0; i < (MagickOffsetType) length; i+=count)
426 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
427 (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
438 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file,
439 const size_t session_key,ExceptionInfo *exception)
453 register unsigned char
457 message[MaxTextExtent];
460 Open distributed pixel cache.
462 image=AcquireImage((ImageInfo *) NULL,exception);
463 if (image == (Image *) NULL)
465 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
466 sizeof(image->alpha_trait)+sizeof(image->read_mask)+
467 sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+
468 sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+
469 sizeof(image->metacontent_extent);
470 count=dpc_read(file,length,message);
471 if (count != (MagickOffsetType) length)
474 Deserialize the image attributes.
477 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
478 p+=sizeof(image->storage_class);
479 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
480 p+=sizeof(image->colorspace);
481 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
482 p+=sizeof(image->alpha_trait);
483 (void) memcpy(&image->read_mask,p,sizeof(image->read_mask));
484 p+=sizeof(image->read_mask);
485 (void) memcpy(&image->write_mask,p,sizeof(image->write_mask));
486 p+=sizeof(image->write_mask);
487 (void) memcpy(&image->columns,p,sizeof(image->columns));
488 p+=sizeof(image->columns);
489 (void) memcpy(&image->rows,p,sizeof(image->rows));
490 p+=sizeof(image->rows);
491 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
492 p+=sizeof(image->number_channels);
493 (void) memcpy(image->channel_map,p,MaxPixelChannels*
494 sizeof(*image->channel_map));
495 p+=MaxPixelChannels*sizeof(*image->channel_map);
496 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
497 p+=sizeof(image->metacontent_extent);
498 if (SyncImagePixelCache(image,exception) == MagickFalse)
500 status=AddValueToSplayTree(registry,(const void *) session_key,image);
504 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
505 int file,const size_t session_key,ExceptionInfo *exception)
522 register const Quantum
525 register unsigned char
529 message[MaxTextExtent];
532 Read distributed pixel cache metacontent.
534 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
535 if (image == (Image *) NULL)
537 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
538 sizeof(region.y)+sizeof(length);
539 count=dpc_read(file,length,message);
540 if (count != (MagickOffsetType) length)
543 (void) memcpy(®ion.width,q,sizeof(region.width));
544 q+=sizeof(region.width);
545 (void) memcpy(®ion.height,q,sizeof(region.height));
546 q+=sizeof(region.height);
547 (void) memcpy(®ion.x,q,sizeof(region.x));
549 (void) memcpy(®ion.y,q,sizeof(region.y));
551 (void) memcpy(&length,q,sizeof(length));
553 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
555 if (p == (const Quantum *) NULL)
557 metacontent=(const unsigned char *) GetVirtualMetacontent(image);
558 count=dpc_send(file,length,metacontent);
559 if (count != (MagickOffsetType) length)
564 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
565 int file,const size_t session_key,ExceptionInfo *exception)
579 register const Quantum
582 register unsigned char
586 message[MaxTextExtent];
589 Read distributed pixel cache pixels.
591 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
592 if (image == (Image *) NULL)
594 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
595 sizeof(region.y)+sizeof(length);
596 count=dpc_read(file,length,message);
597 if (count != (MagickOffsetType) length)
600 (void) memcpy(®ion.width,q,sizeof(region.width));
601 q+=sizeof(region.width);
602 (void) memcpy(®ion.height,q,sizeof(region.height));
603 q+=sizeof(region.height);
604 (void) memcpy(®ion.x,q,sizeof(region.x));
606 (void) memcpy(®ion.y,q,sizeof(region.y));
608 (void) memcpy(&length,q,sizeof(length));
610 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
612 if (p == (const Quantum *) NULL)
614 count=dpc_send(file,length,(unsigned char *) p);
615 if (count != (MagickOffsetType) length)
620 static void *RelinquishImageRegistry(void *image)
622 return((void *) DestroyImageList((Image *) image));
625 static MagickBooleanType WriteDistributeCacheMetacontent(
626 SplayTreeInfo *registry,int file,const size_t session_key,
627 ExceptionInfo *exception)
644 register unsigned char
648 message[MaxTextExtent],
652 Write distributed pixel cache metacontent.
654 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
655 if (image == (Image *) NULL)
657 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
658 sizeof(region.y)+sizeof(length);
659 count=dpc_read(file,length,message);
660 if (count != (MagickOffsetType) length)
663 (void) memcpy(®ion.width,p,sizeof(region.width));
664 p+=sizeof(region.width);
665 (void) memcpy(®ion.height,p,sizeof(region.height));
666 p+=sizeof(region.height);
667 (void) memcpy(®ion.x,p,sizeof(region.x));
669 (void) memcpy(®ion.y,p,sizeof(region.y));
671 (void) memcpy(&length,p,sizeof(length));
673 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
675 if (q == (Quantum *) NULL)
677 metacontent=(unsigned char *) GetAuthenticMetacontent(image);
678 count=dpc_read(file,length,metacontent);
679 if (count != (MagickOffsetType) length)
681 return(SyncAuthenticPixels(image,exception));
684 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
685 int file,const size_t session_key,ExceptionInfo *exception)
702 register unsigned char
706 message[MaxTextExtent];
709 Write distributed pixel cache pixels.
711 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
712 if (image == (Image *) NULL)
714 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
715 sizeof(region.y)+sizeof(length);
716 count=dpc_read(file,length,message);
717 if (count != (MagickOffsetType) length)
720 (void) memcpy(®ion.width,p,sizeof(region.width));
721 p+=sizeof(region.width);
722 (void) memcpy(®ion.height,p,sizeof(region.height));
723 p+=sizeof(region.height);
724 (void) memcpy(®ion.x,p,sizeof(region.x));
726 (void) memcpy(®ion.y,p,sizeof(region.y));
728 (void) memcpy(&length,p,sizeof(length));
730 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
732 if (q == (Quantum *) NULL)
734 count=dpc_read(file,length,(unsigned char *) q);
735 if (count != (MagickOffsetType) length)
737 return(SyncAuthenticPixels(image,exception));
740 static void *DistributePixelCacheClient(void *socket)
757 register unsigned char
775 session[2*MaxTextExtent];
778 Distributed pixel cache client.
780 shared_secret=GetPolicyValue("shared-secret");
781 if (shared_secret == (const char *) NULL)
782 ThrowFatalException(CacheFatalError,"shared secret expected");
784 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
785 p+=strlen(shared_secret);
786 random_info=AcquireRandomInfo();
787 secret=GetRandomKey(random_info,DPCSessionKeyLength);
788 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
789 session_key=GetMagickSignature(secret);
790 random_info=DestroyRandomInfo(random_info);
791 exception=AcquireExceptionInfo();
792 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
793 (void *(*)(void *)) NULL,RelinquishImageRegistry);
794 client_socket=(*(int *) socket);
795 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
796 secret=DestroyStringInfo(secret);
799 count=dpc_read(client_socket,1,(unsigned char *) &command);
802 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
803 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
810 status=OpenDistributeCache(registry,client_socket,session_key,
812 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
817 status=ReadDistributeCachePixels(registry,client_socket,session_key,
823 status=ReadDistributeCacheMetacontent(registry,client_socket,
824 session_key,exception);
829 status=WriteDistributeCachePixels(registry,client_socket,session_key,
835 status=WriteDistributeCacheMetacontent(registry,client_socket,
836 session_key,exception);
841 status=DestroyDistributeCache(registry,client_socket,session_key);
847 if (status == MagickFalse)
852 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
853 (void) close(client_socket);
854 exception=DestroyExceptionInfo(exception);
855 registry=DestroySplayTree(registry);
856 return((void *) NULL);
859 MagickExport void DistributePixelCacheServer(const int port,
860 ExceptionInfo *exception)
862 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
864 service[MaxTextExtent];
876 register struct addrinfo
887 Launch distributed pixel cache server.
889 assert(exception != (ExceptionInfo *) NULL);
890 assert(exception->signature == MagickSignature);
891 (void) ResetMagickMemory(&hint,0,sizeof(hint));
892 hint.ai_family=AF_INET;
893 hint.ai_socktype=SOCK_STREAM;
894 hint.ai_flags=AI_PASSIVE;
895 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
896 status=getaddrinfo((const char *) NULL,service,&hint,&result);
898 ThrowFatalException(CacheFatalError,"UnableToListen");
900 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
905 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
906 if (server_socket == -1)
909 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
913 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
916 (void) close(status);
921 if (p == (struct addrinfo *) NULL)
922 ThrowFatalException(CacheFatalError,"UnableToBind");
923 freeaddrinfo(result);
924 status=listen(server_socket,DPCPendingConnections);
926 ThrowFatalException(CacheFatalError,"UnableToListen");
927 pthread_attr_init(&attributes);
936 length=(socklen_t) sizeof(address);
937 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
938 if (client_socket == -1)
939 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
940 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
941 (void *) &client_socket);
943 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
945 (void) close(server_socket);
947 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956 + G e t D i s t r i b u t e C a c h e F i l e %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962 % GetDistributeCacheFile() returns the file associated with this
963 % DistributeCacheInfo structure.
965 % The format of the GetDistributeCacheFile method is:
967 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
969 % A description of each parameter follows:
971 % o server_info: the distributed cache info.
974 MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
976 assert(server_info != (DistributeCacheInfo *) NULL);
977 assert(server_info->signature == MagickSignature);
978 return(server_info->file);
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986 + G e t D i s t r i b u t e C a c h e H o s t n a m e %
990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 % GetDistributeCacheHostname() returns the hostname associated with this
993 % DistributeCacheInfo structure.
995 % The format of the GetDistributeCacheHostname method is:
997 % const char *GetDistributeCacheHostname(
998 % const DistributeCacheInfo *server_info)
1000 % A description of each parameter follows:
1002 % o server_info: the distributed cache info.
1005 MagickPrivate const char *GetDistributeCacheHostname(
1006 const DistributeCacheInfo *server_info)
1008 assert(server_info != (DistributeCacheInfo *) NULL);
1009 assert(server_info->signature == MagickSignature);
1010 return(server_info->hostname);
1014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 + G e t D i s t r i b u t e C a c h e P o r t %
1022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024 % GetDistributeCachePort() returns the port associated with this
1025 % DistributeCacheInfo structure.
1027 % The format of the GetDistributeCachePort method is:
1029 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1031 % A description of each parameter follows:
1033 % o server_info: the distributed cache info.
1036 MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1038 assert(server_info != (DistributeCacheInfo *) NULL);
1039 assert(server_info->signature == MagickSignature);
1040 return(server_info->port);
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 + O p e n D i s t r i b u t e P i x e l C a c h e %
1052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1056 % The format of the OpenDistributePixelCache method is:
1058 % MagickBooleanType *OpenDistributePixelCache(
1059 % DistributeCacheInfo *server_info,Image *image)
1061 % A description of each parameter follows:
1063 % o server_info: the distributed cache info.
1065 % o image: the image.
1068 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1069 DistributeCacheInfo *server_info,Image *image)
1077 register unsigned char
1081 message[MaxTextExtent];
1084 Open distributed pixel cache.
1086 assert(server_info != (DistributeCacheInfo *) NULL);
1087 assert(server_info->signature == MagickSignature);
1088 assert(image != (Image *) NULL);
1089 assert(image->signature == MagickSignature);
1091 *p++='o'; /* open */
1093 Serialize image attributes (see ValidatePixelCacheMorphology()).
1095 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1096 p+=sizeof(server_info->session_key);
1097 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1098 p+=sizeof(image->storage_class);
1099 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1100 p+=sizeof(image->colorspace);
1101 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1102 p+=sizeof(image->alpha_trait);
1103 (void) memcpy(p,&image->read_mask,sizeof(image->read_mask));
1104 p+=sizeof(image->read_mask);
1105 (void) memcpy(p,&image->write_mask,sizeof(image->write_mask));
1106 p+=sizeof(image->write_mask);
1107 (void) memcpy(p,&image->columns,sizeof(image->columns));
1108 p+=sizeof(image->columns);
1109 (void) memcpy(p,&image->rows,sizeof(image->rows));
1110 p+=sizeof(image->rows);
1111 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1112 p+=sizeof(image->number_channels);
1113 (void) memcpy(p,image->channel_map,MaxPixelChannels*
1114 sizeof(*image->channel_map));
1115 p+=MaxPixelChannels*sizeof(*image->channel_map);
1116 (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1117 p+=sizeof(image->metacontent_extent);
1118 count=dpc_send(server_info->file,p-message,message);
1119 if (count != (MagickOffsetType) (p-message))
1120 return(MagickFalse);
1122 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1123 if (count != (MagickOffsetType) sizeof(status))
1124 return(MagickFalse);
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1133 + R e a d D i s t r i b u t e P i x e l C a c h e M e t a c o n t e n t %
1137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1140 % region of the distributed pixel cache.
1142 % The format of the ReadDistributePixelCacheMetacontents method is:
1144 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1145 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1146 % const MagickSizeType length,unsigned char *metacontent)
1148 % A description of each parameter follows:
1150 % o server_info: the distributed cache info.
1152 % o image: the image.
1154 % o region: read the metacontent from this region of the image.
1156 % o length: the length in bytes of the metacontent.
1158 % o metacontent: read these metacontent from the pixel cache.
1161 MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1162 DistributeCacheInfo *server_info,const RectangleInfo *region,
1163 const MagickSizeType length,unsigned char *metacontent)
1168 register unsigned char
1172 message[MaxTextExtent];
1175 Read distributed pixel cache metacontent.
1177 assert(server_info != (DistributeCacheInfo *) NULL);
1178 assert(server_info->signature == MagickSignature);
1179 assert(region != (RectangleInfo *) NULL);
1180 assert(metacontent != (unsigned char *) NULL);
1181 if (length > (MagickSizeType) SSIZE_MAX)
1185 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1186 p+=sizeof(server_info->session_key);
1187 (void) memcpy(p,®ion->width,sizeof(region->width));
1188 p+=sizeof(region->width);
1189 (void) memcpy(p,®ion->height,sizeof(region->height));
1190 p+=sizeof(region->height);
1191 (void) memcpy(p,®ion->x,sizeof(region->x));
1192 p+=sizeof(region->x);
1193 (void) memcpy(p,®ion->y,sizeof(region->y));
1194 p+=sizeof(region->y);
1195 (void) memcpy(p,&length,sizeof(length));
1197 count=dpc_send(server_info->file,p-message,message);
1198 if (count != (MagickOffsetType) (p-message))
1200 return(dpc_read(server_info->file,length,metacontent));
1204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208 + R e a d D i s t r i b u t e P i x e l C a c h e P i x e l s %
1212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1215 % the distributed pixel cache.
1217 % The format of the ReadDistributePixelCachePixels method is:
1219 % MagickOffsetType ReadDistributePixelCachePixels(
1220 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1221 % const MagickSizeType length,unsigned char *restrict pixels)
1223 % A description of each parameter follows:
1225 % o server_info: the distributed cache info.
1227 % o image: the image.
1229 % o region: read the pixels from this region of the image.
1231 % o length: the length in bytes of the pixels.
1233 % o pixels: read these pixels from the pixel cache.
1236 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1237 DistributeCacheInfo *server_info,const RectangleInfo *region,
1238 const MagickSizeType length,unsigned char *restrict pixels)
1243 register unsigned char
1247 message[MaxTextExtent];
1250 Read distributed pixel cache pixels.
1252 assert(server_info != (DistributeCacheInfo *) NULL);
1253 assert(server_info->signature == MagickSignature);
1254 assert(region != (RectangleInfo *) NULL);
1255 assert(pixels != (unsigned char *) NULL);
1256 if (length > (MagickSizeType) SSIZE_MAX)
1260 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1261 p+=sizeof(server_info->session_key);
1262 (void) memcpy(p,®ion->width,sizeof(region->width));
1263 p+=sizeof(region->width);
1264 (void) memcpy(p,®ion->height,sizeof(region->height));
1265 p+=sizeof(region->height);
1266 (void) memcpy(p,®ion->x,sizeof(region->x));
1267 p+=sizeof(region->x);
1268 (void) memcpy(p,®ion->y,sizeof(region->y));
1269 p+=sizeof(region->y);
1270 (void) memcpy(p,&length,sizeof(length));
1272 count=dpc_send(server_info->file,p-message,message);
1273 if (count != (MagickOffsetType) (p-message))
1275 return(dpc_read(server_info->file,length,pixels));
1279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1283 + R e l i n q u i s h D i s t r i b u t e P i x e l C a c h e %
1287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289 % RelinquishDistributePixelCache() frees resources acquired with
1290 % OpenDistributePixelCache().
1292 % The format of the RelinquishDistributePixelCache method is:
1294 % MagickBooleanType RelinquishDistributePixelCache(
1295 % DistributeCacheInfo *server_info)
1297 % A description of each parameter follows:
1299 % o server_info: the distributed cache info.
1302 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1303 DistributeCacheInfo *server_info)
1311 register unsigned char
1315 message[MaxTextExtent];
1318 Delete distributed pixel cache.
1320 assert(server_info != (DistributeCacheInfo *) NULL);
1321 assert(server_info->signature == MagickSignature);
1324 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1325 p+=sizeof(server_info->session_key);
1326 count=dpc_send(server_info->file,p-message,message);
1327 if (count != (MagickOffsetType) (p-message))
1328 return(MagickFalse);
1329 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1330 if (count != (MagickOffsetType) sizeof(status))
1331 return(MagickFalse);
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1340 + W r i t e D i s t r i b u t e P i x e l C a c h e M e t a c o n t e n t %
1344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1346 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1347 % specified region of the distributed pixel cache.
1349 % The format of the WriteDistributePixelCacheMetacontents method is:
1351 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1352 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1353 % const MagickSizeType length,const unsigned char *metacontent)
1355 % A description of each parameter follows:
1357 % o server_info: the distributed cache info.
1359 % o image: the image.
1361 % o region: write the metacontent to this region of the image.
1363 % o length: the length in bytes of the metacontent.
1365 % o metacontent: write these metacontent to the pixel cache.
1368 MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1369 DistributeCacheInfo *server_info,const RectangleInfo *region,
1370 const MagickSizeType length,const unsigned char *metacontent)
1375 register unsigned char
1379 message[MaxTextExtent];
1382 Write distributed pixel cache metacontent.
1384 assert(server_info != (DistributeCacheInfo *) NULL);
1385 assert(server_info->signature == MagickSignature);
1386 assert(region != (RectangleInfo *) NULL);
1387 assert(metacontent != (unsigned char *) NULL);
1388 if (length > (MagickSizeType) SSIZE_MAX)
1392 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1393 p+=sizeof(server_info->session_key);
1394 (void) memcpy(p,®ion->width,sizeof(region->width));
1395 p+=sizeof(region->width);
1396 (void) memcpy(p,®ion->height,sizeof(region->height));
1397 p+=sizeof(region->height);
1398 (void) memcpy(p,®ion->x,sizeof(region->x));
1399 p+=sizeof(region->x);
1400 (void) memcpy(p,®ion->y,sizeof(region->y));
1401 p+=sizeof(region->y);
1402 (void) memcpy(p,&length,sizeof(length));
1404 count=dpc_send(server_info->file,p-message,message);
1405 if (count != (MagickOffsetType) (p-message))
1407 return(dpc_send(server_info->file,length,metacontent));
1411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1415 + W r i t e D i s t r i b u t e P i x e l C a c h e P i x e l s %
1419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1421 % WriteDistributePixelCachePixels() writes image pixels to the specified
1422 % region of the distributed pixel cache.
1424 % The format of the WriteDistributePixelCachePixels method is:
1426 % MagickBooleanType WriteDistributePixelCachePixels(
1427 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1428 % const MagickSizeType length,const unsigned char *restrict pixels)
1430 % A description of each parameter follows:
1432 % o server_info: the distributed cache info.
1434 % o image: the image.
1436 % o region: write the pixels to this region of the image.
1438 % o length: the length in bytes of the pixels.
1440 % o pixels: write these pixels to the pixel cache.
1443 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1444 DistributeCacheInfo *server_info,const RectangleInfo *region,
1445 const MagickSizeType length,const unsigned char *restrict pixels)
1450 register unsigned char
1454 message[MaxTextExtent];
1457 Write distributed pixel cache pixels.
1459 assert(server_info != (DistributeCacheInfo *) NULL);
1460 assert(server_info->signature == MagickSignature);
1461 assert(region != (RectangleInfo *) NULL);
1462 assert(pixels != (const unsigned char *) NULL);
1463 if (length > (MagickSizeType) SSIZE_MAX)
1467 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1468 p+=sizeof(server_info->session_key);
1469 (void) memcpy(p,®ion->width,sizeof(region->width));
1470 p+=sizeof(region->width);
1471 (void) memcpy(p,®ion->height,sizeof(region->height));
1472 p+=sizeof(region->height);
1473 (void) memcpy(p,®ion->x,sizeof(region->x));
1474 p+=sizeof(region->x);
1475 (void) memcpy(p,®ion->y,sizeof(region->y));
1476 p+=sizeof(region->y);
1477 (void) memcpy(p,&length,sizeof(length));
1479 count=dpc_send(server_info->file,p-message,message);
1480 if (count != (MagickOffsetType) (p-message))
1482 return(dpc_send(server_info->file,length,pixels));