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-2013 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/pixel.h"
67 #include "MagickCore/policy.h"
68 #include "MagickCore/random_.h"
69 #include "MagickCore/registry.h"
70 #include "MagickCore/splay-tree.h"
71 #include "MagickCore/string_.h"
72 #include "MagickCore/string-private.h"
73 #include "MagickCore/version.h"
74 #include "MagickCore/version-private.h"
75 #if defined(MAGICKCORE_HAVE_SOCKET)
76 #include <netinet/in.h>
78 #include <sys/socket.h>
79 #include <arpa/inet.h>
85 #define DPCHostname "127.0.0.1"
86 #define DPCPendingConnections 10
88 #define DPCSessionKeyLength 8
90 # define MSG_NOSIGNAL 0
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 + 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 %
102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
106 % The format of the AcquireDistributeCacheInfo method is:
108 % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
110 % A description of each parameter follows:
112 % o exception: return any errors or warnings in this structure.
116 static inline MagickSizeType MagickMin(const MagickSizeType x,
117 const MagickSizeType y)
124 static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
125 unsigned char *restrict message)
127 register MagickOffsetType
134 for (i=0; i < (MagickOffsetType) length; i+=count)
136 count=recv(file,message+i,(size_t) MagickMin(length-i,(MagickSizeType)
148 static int ConnectPixelCacheServer(const char *hostname,const int port,
149 size_t *session_key,ExceptionInfo *exception)
151 #if defined(MAGICKCORE_HAVE_SOCKET)
153 service[MaxTextExtent];
170 secret[MaxTextExtent];
173 Connect to distributed pixel cache and get session key.
176 shared_secret=GetPolicyValue("shared-secret");
177 if (shared_secret == (const char *) NULL)
179 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
180 "DistributedPixelCache","'%s'","shared secret expected");
183 (void) ResetMagickMemory(&hint,0,sizeof(hint));
184 hint.ai_family=AF_INET;
185 hint.ai_socktype=SOCK_STREAM;
186 hint.ai_flags=AI_PASSIVE;
187 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
188 status=getaddrinfo(hostname,service,&hint,&result);
191 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
192 "DistributedPixelCache","'%s'",hostname);
195 client_socket=socket(result->ai_family,result->ai_socktype,
196 result->ai_protocol);
197 if (client_socket == -1)
199 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
200 "DistributedPixelCache","'%s'",hostname);
203 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
206 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
207 "DistributedPixelCache","'%s'",hostname);
210 count=recv(client_socket,secret,MaxTextExtent,0);
216 nonce=AcquireStringInfo(count);
217 (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
218 *session_key=GetMagickSignature(nonce);
219 nonce=DestroyStringInfo(nonce);
221 if (*session_key == 0)
223 close(client_socket);
226 return(client_socket);
228 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
229 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
234 static char *GetHostname(int *port,ExceptionInfo *exception)
251 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
253 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",
255 if (hosts == (char *) NULL)
258 return(AcquireString(DPCHostname));
260 (void) SubstituteString(&hosts,","," ");
261 hostlist=StringToArgv(hosts,&argc);
262 hosts=DestroyString(hosts);
263 if (hostlist == (char **) NULL)
266 return(AcquireString(DPCHostname));
268 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
269 for (i=0; i < (ssize_t) argc; i++)
270 hostlist[i]=DestroyString(hostlist[i]);
271 hostlist=(char **) RelinquishMagickMemory(hostlist);
272 (void) SubstituteString(&hosts,":"," ");
273 hostlist=StringToArgv(hosts,&argc);
274 if (hostlist == (char **) NULL)
277 return(AcquireString(DPCHostname));
279 host=AcquireString(hostlist[1]);
280 if (hostlist[2] == (char *) NULL)
283 *port=StringToLong(hostlist[2]);
284 for (i=0; i < (ssize_t) argc; i++)
285 hostlist[i]=DestroyString(hostlist[i]);
286 hostlist=(char **) RelinquishMagickMemory(hostlist);
290 MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
291 ExceptionInfo *exception)
303 Connect to the distributed pixel cache server.
305 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
306 if (server_info == (DistributeCacheInfo *) NULL)
307 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
308 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
309 server_info->signature=MagickSignature;
311 hostname=GetHostname(&server_info->port,exception);
313 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
314 &session_key,exception);
315 server_info->session_key=session_key;
316 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
317 hostname=DestroyString(hostname);
318 if (server_info->file == -1)
319 server_info=DestroyDistributeCacheInfo(server_info);
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 + 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 %
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % DestroyDistributeCacheInfo() deallocates memory associated with an
335 % DistributeCacheInfo structure.
337 % The format of the DestroyDistributeCacheInfo method is:
339 % DistributeCacheInfo *DestroyDistributeCacheInfo(
340 % DistributeCacheInfo *server_info)
342 % A description of each parameter follows:
344 % o server_info: the distributed cache info.
347 MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
348 DistributeCacheInfo *server_info)
350 assert(server_info != (DistributeCacheInfo *) NULL);
351 assert(server_info->signature == MagickSignature);
352 if (server_info->file > 0)
353 (void) close(server_info->file);
354 server_info->signature=(~MagickSignature);
355 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364 + 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 %
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 % DistributePixelCacheServer() waits on the specified port for commands to
371 % create, read, update, or destroy a pixel cache.
373 % The format of the DistributePixelCacheServer() method is:
375 % void DistributePixelCacheServer(const int port)
377 % A description of each parameter follows:
379 % o port: connect the distributed pixel cache at this port.
381 % o exception: return any errors or warnings in this structure.
385 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
386 int file,const size_t session_key)
389 Destroy distributed pixel cache.
391 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
394 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
395 const unsigned char *restrict message)
400 register MagickOffsetType
404 Ensure a complete message is sent.
407 for (i=0; i < (MagickOffsetType) length; i+=count)
409 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
410 (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
421 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
422 int file,const size_t session_key,ExceptionInfo *exception)
436 register unsigned char
440 message[MaxTextExtent];
443 Open distributed pixel cache.
445 image=AcquireImage((ImageInfo *) NULL,exception);
446 if (image == (Image *) NULL)
448 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
449 sizeof(image->alpha_trait)+sizeof(image->mask)+sizeof(image->columns)+
450 sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels*
451 sizeof(*image->channel_map)+sizeof(image->metacontent_extent);
452 count=dpc_read(file,length,message);
453 if (count != (MagickOffsetType) length)
456 Deserialize the image attributes.
459 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
460 p+=sizeof(image->storage_class);
461 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
462 p+=sizeof(image->colorspace);
463 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
464 p+=sizeof(image->alpha_trait);
465 (void) memcpy(&image->mask,p,sizeof(image->mask));
466 p+=sizeof(image->mask);
467 (void) memcpy(&image->columns,p,sizeof(image->columns));
468 p+=sizeof(image->columns);
469 (void) memcpy(&image->rows,p,sizeof(image->rows));
470 p+=sizeof(image->rows);
471 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
472 p+=sizeof(image->number_channels);
473 (void) memcpy(image->channel_map,p,MaxPixelChannels*
474 sizeof(*image->channel_map));
475 p+=MaxPixelChannels*sizeof(*image->channel_map);
476 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
477 p+=sizeof(image->metacontent_extent);
478 if (SyncImagePixelCache(image,exception) == MagickFalse)
480 status=AddValueToSplayTree(registry,(const void *) session_key,image);
484 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
485 int file,const size_t session_key,ExceptionInfo *exception)
502 register const Quantum
505 register unsigned char
509 message[MaxTextExtent];
512 Read distributed pixel cache metacontent.
514 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
515 if (image == (Image *) NULL)
517 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
518 sizeof(region.y)+sizeof(length);
519 count=dpc_read(file,length,message);
520 if (count != (MagickOffsetType) length)
523 (void) memcpy(®ion.width,q,sizeof(region.width));
524 q+=sizeof(region.width);
525 (void) memcpy(®ion.height,q,sizeof(region.height));
526 q+=sizeof(region.height);
527 (void) memcpy(®ion.x,q,sizeof(region.x));
529 (void) memcpy(®ion.y,q,sizeof(region.y));
531 (void) memcpy(&length,q,sizeof(length));
533 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
535 if (p == (const Quantum *) NULL)
537 metacontent=GetVirtualMetacontent(image);
538 count=dpc_send(file,length,metacontent);
539 if (count != (MagickOffsetType) length)
544 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
545 int file,const size_t session_key,ExceptionInfo *exception)
559 register const Quantum
562 register unsigned char
566 message[MaxTextExtent];
569 Read distributed pixel cache pixels.
571 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
572 if (image == (Image *) NULL)
574 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
575 sizeof(region.y)+sizeof(length);
576 count=dpc_read(file,length,message);
577 if (count != (MagickOffsetType) length)
580 (void) memcpy(®ion.width,q,sizeof(region.width));
581 q+=sizeof(region.width);
582 (void) memcpy(®ion.height,q,sizeof(region.height));
583 q+=sizeof(region.height);
584 (void) memcpy(®ion.x,q,sizeof(region.x));
586 (void) memcpy(®ion.y,q,sizeof(region.y));
588 (void) memcpy(&length,q,sizeof(length));
590 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
592 if (p == (const Quantum *) NULL)
594 count=dpc_send(file,length,(unsigned char *) p);
595 if (count != (MagickOffsetType) length)
600 static void *RelinquishImageRegistry(void *image)
602 return((void *) DestroyImageList((Image *) image));
605 static MagickBooleanType WriteDistributeCacheMetacontent(
606 SplayTreeInfo *registry,int file,const size_t session_key,
607 ExceptionInfo *exception)
624 register unsigned char
628 message[MaxTextExtent],
632 Write distributed pixel cache metacontent.
634 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
635 if (image == (Image *) NULL)
637 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
638 sizeof(region.y)+sizeof(length);
639 count=dpc_read(file,length,message);
640 if (count != (MagickOffsetType) length)
643 (void) memcpy(®ion.width,p,sizeof(region.width));
644 p+=sizeof(region.width);
645 (void) memcpy(®ion.height,p,sizeof(region.height));
646 p+=sizeof(region.height);
647 (void) memcpy(®ion.x,p,sizeof(region.x));
649 (void) memcpy(®ion.y,p,sizeof(region.y));
651 (void) memcpy(&length,p,sizeof(length));
653 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
655 if (q == (Quantum *) NULL)
657 metacontent=GetAuthenticMetacontent(image);
658 count=dpc_read(file,length,metacontent);
659 if (count != (MagickOffsetType) length)
661 return(SyncAuthenticPixels(image,exception));
664 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
665 int file,const size_t session_key,ExceptionInfo *exception)
682 register unsigned char
686 message[MaxTextExtent];
689 Write distributed pixel cache pixels.
691 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
692 if (image == (Image *) NULL)
694 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
695 sizeof(region.y)+sizeof(length);
696 count=dpc_read(file,length,message);
697 if (count != (MagickOffsetType) length)
700 (void) memcpy(®ion.width,p,sizeof(region.width));
701 p+=sizeof(region.width);
702 (void) memcpy(®ion.height,p,sizeof(region.height));
703 p+=sizeof(region.height);
704 (void) memcpy(®ion.x,p,sizeof(region.x));
706 (void) memcpy(®ion.y,p,sizeof(region.y));
708 (void) memcpy(&length,p,sizeof(length));
710 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
712 if (q == (Quantum *) NULL)
714 count=dpc_read(file,length,(unsigned char *) q);
715 if (count != (MagickOffsetType) length)
717 return(SyncAuthenticPixels(image,exception));
720 static void *DistributePixelCacheClient(void *socket)
737 register unsigned char
755 session[2*MaxTextExtent];
758 Distributed pixel cache client.
760 shared_secret=GetPolicyValue("shared-secret");
761 if (shared_secret == (const char *) NULL)
762 ThrowFatalException(CacheFatalError,"shared secret expected");
764 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
765 p+=strlen(shared_secret);
766 random_info=AcquireRandomInfo();
767 secret=GetRandomKey(random_info,DPCSessionKeyLength);
768 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
769 session_key=GetMagickSignature(secret);
770 random_info=DestroyRandomInfo(random_info);
771 exception=AcquireExceptionInfo();
772 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
773 (void *(*)(void *)) NULL,RelinquishImageRegistry);
774 client_socket=(*(int *) socket);
775 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
776 secret=DestroyStringInfo(secret);
779 count=dpc_read(client_socket,1,(unsigned char *) &command);
782 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
783 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
790 status=OpenDistributeCache(registry,client_socket,session_key,
792 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
797 status=ReadDistributeCachePixels(registry,client_socket,session_key,
803 status=ReadDistributeCacheMetacontent(registry,client_socket,
804 session_key,exception);
809 status=WriteDistributeCachePixels(registry,client_socket,session_key,
815 status=WriteDistributeCacheMetacontent(registry,client_socket,
816 session_key,exception);
821 status=DestroyDistributeCache(registry,client_socket,session_key);
827 if (status == MagickFalse)
832 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
833 (void) close(client_socket);
834 exception=DestroyExceptionInfo(exception);
835 registry=DestroySplayTree(registry);
836 return((void *) NULL);
839 MagickExport void DistributePixelCacheServer(const int port,
840 ExceptionInfo *exception)
842 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
844 service[MaxTextExtent];
856 register struct addrinfo
867 Launch distributed pixel cache server.
869 (void) ResetMagickMemory(&hint,0,sizeof(hint));
870 hint.ai_family=AF_INET;
871 hint.ai_socktype=SOCK_STREAM;
872 hint.ai_flags=AI_PASSIVE;
873 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
874 status=getaddrinfo((const char *) NULL,service,&hint,&result);
876 ThrowFatalException(CacheFatalError,"UnableToListen");
878 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
883 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
884 if (server_socket == -1)
887 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
891 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
894 (void) close(status);
899 if (p == (struct addrinfo *) NULL)
900 ThrowFatalException(CacheFatalError,"UnableToBind");
901 freeaddrinfo(result);
902 status=listen(server_socket,DPCPendingConnections);
904 ThrowFatalException(CacheFatalError,"UnableToListen");
905 pthread_attr_init(&attributes);
914 length=(socklen_t) sizeof(address);
915 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
916 if (client_socket == -1)
917 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
918 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
919 (void *) &client_socket);
921 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
923 (void) close(server_socket);
925 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 + G e t D i s t r i b u t e C a c h e F i l e %
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 % GetDistributeCacheFile() returns the file associated with this
941 % DistributeCacheInfo structure.
943 % The format of the GetDistributeCacheFile method is:
945 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
947 % A description of each parameter follows:
949 % o server_info: the distributed cache info.
952 MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
954 assert(server_info != (DistributeCacheInfo *) NULL);
955 assert(server_info->signature == MagickSignature);
956 return(server_info->file);
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 + 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 %
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970 % GetDistributeCacheHostname() returns the hostname associated with this
971 % DistributeCacheInfo structure.
973 % The format of the GetDistributeCacheHostname method is:
975 % const char *GetDistributeCacheHostname(
976 % const DistributeCacheInfo *server_info)
978 % A description of each parameter follows:
980 % o server_info: the distributed cache info.
983 MagickPrivate const char *GetDistributeCacheHostname(
984 const DistributeCacheInfo *server_info)
986 assert(server_info != (DistributeCacheInfo *) NULL);
987 assert(server_info->signature == MagickSignature);
988 return(server_info->hostname);
992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 + G e t D i s t r i b u t e C a c h e P o r t %
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 % GetDistributeCachePort() returns the port associated with this
1003 % DistributeCacheInfo structure.
1005 % The format of the GetDistributeCachePort method is:
1007 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1009 % A description of each parameter follows:
1011 % o server_info: the distributed cache info.
1014 MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1016 assert(server_info != (DistributeCacheInfo *) NULL);
1017 assert(server_info->signature == MagickSignature);
1018 return(server_info->port);
1022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 + O p e n D i s t r i b u t e P i x e l C a c h e %
1030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1034 % The format of the OpenDistributePixelCache method is:
1036 % MagickBooleanType *OpenDistributePixelCache(
1037 % DistributeCacheInfo *server_info,Image *image)
1039 % A description of each parameter follows:
1041 % o server_info: the distributed cache info.
1043 % o image: the image.
1046 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1047 DistributeCacheInfo *server_info,Image *image)
1055 register unsigned char
1059 message[MaxTextExtent];
1062 Open distributed pixel cache.
1064 assert(server_info != (DistributeCacheInfo *) NULL);
1065 assert(server_info->signature == MagickSignature);
1066 assert(image != (Image *) NULL);
1067 assert(image->signature == MagickSignature);
1069 *p++='o'; /* open */
1071 Serialize image attributes (see ValidatePixelCacheMorphology()).
1073 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1074 p+=sizeof(server_info->session_key);
1075 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1076 p+=sizeof(image->storage_class);
1077 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1078 p+=sizeof(image->colorspace);
1079 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1080 p+=sizeof(image->alpha_trait);
1081 (void) memcpy(p,&image->mask,sizeof(image->mask));
1082 p+=sizeof(image->mask);
1083 (void) memcpy(p,&image->columns,sizeof(image->columns));
1084 p+=sizeof(image->columns);
1085 (void) memcpy(p,&image->rows,sizeof(image->rows));
1086 p+=sizeof(image->rows);
1087 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1088 p+=sizeof(image->number_channels);
1089 (void) memcpy(p,image->channel_map,MaxPixelChannels*
1090 sizeof(*image->channel_map));
1091 p+=MaxPixelChannels*sizeof(*image->channel_map);
1092 (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1093 p+=sizeof(image->metacontent_extent);
1094 count=dpc_send(server_info->file,p-message,message);
1095 if (count != (MagickOffsetType) (p-message))
1096 return(MagickFalse);
1098 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1099 if (count != (MagickOffsetType) sizeof(status))
1100 return(MagickFalse);
1105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 + 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 %
1113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1115 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1116 % region of the distributed pixel cache.
1118 % The format of the ReadDistributePixelCacheMetacontents method is:
1120 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1121 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1122 % const MagickSizeType length,unsigned char *metacontent)
1124 % A description of each parameter follows:
1126 % o server_info: the distributed cache info.
1128 % o image: the image.
1130 % o region: read the metacontent from this region of the image.
1132 % o length: the length in bytes of the metacontent.
1134 % o metacontent: read these metacontent from the pixel cache.
1137 MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1138 DistributeCacheInfo *server_info,const RectangleInfo *region,
1139 const MagickSizeType length,unsigned char *metacontent)
1144 register unsigned char
1148 message[MaxTextExtent];
1151 Read distributed pixel cache metacontent.
1153 assert(server_info != (DistributeCacheInfo *) NULL);
1154 assert(server_info->signature == MagickSignature);
1155 assert(region != (RectangleInfo *) NULL);
1156 assert(metacontent != (unsigned char *) NULL);
1157 if (length > (MagickSizeType) SSIZE_MAX)
1161 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1162 p+=sizeof(server_info->session_key);
1163 (void) memcpy(p,®ion->width,sizeof(region->width));
1164 p+=sizeof(region->width);
1165 (void) memcpy(p,®ion->height,sizeof(region->height));
1166 p+=sizeof(region->height);
1167 (void) memcpy(p,®ion->x,sizeof(region->x));
1168 p+=sizeof(region->x);
1169 (void) memcpy(p,®ion->y,sizeof(region->y));
1170 p+=sizeof(region->y);
1171 (void) memcpy(p,&length,sizeof(length));
1173 count=dpc_send(server_info->file,p-message,message);
1174 if (count != (MagickOffsetType) (p-message))
1176 return(dpc_read(server_info->file,length,metacontent));
1180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1184 + 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 %
1188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1191 % the distributed pixel cache.
1193 % The format of the ReadDistributePixelCachePixels method is:
1195 % MagickOffsetType ReadDistributePixelCachePixels(
1196 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1197 % const MagickSizeType length,unsigned char *pixels)
1199 % A description of each parameter follows:
1201 % o server_info: the distributed cache info.
1203 % o image: the image.
1205 % o region: read the pixels from this region of the image.
1207 % o length: the length in bytes of the pixels.
1209 % o pixels: read these pixels from the pixel cache.
1212 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1213 DistributeCacheInfo *server_info,const RectangleInfo *region,
1214 const MagickSizeType length,unsigned char *pixels)
1219 register unsigned char
1223 message[MaxTextExtent];
1226 Read distributed pixel cache pixels.
1228 assert(server_info != (DistributeCacheInfo *) NULL);
1229 assert(server_info->signature == MagickSignature);
1230 assert(region != (RectangleInfo *) NULL);
1231 assert(pixels != (unsigned char *) NULL);
1232 if (length > (MagickSizeType) SSIZE_MAX)
1236 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1237 p+=sizeof(server_info->session_key);
1238 (void) memcpy(p,®ion->width,sizeof(region->width));
1239 p+=sizeof(region->width);
1240 (void) memcpy(p,®ion->height,sizeof(region->height));
1241 p+=sizeof(region->height);
1242 (void) memcpy(p,®ion->x,sizeof(region->x));
1243 p+=sizeof(region->x);
1244 (void) memcpy(p,®ion->y,sizeof(region->y));
1245 p+=sizeof(region->y);
1246 (void) memcpy(p,&length,sizeof(length));
1248 count=dpc_send(server_info->file,p-message,message);
1249 if (count != (MagickOffsetType) (p-message))
1251 return(dpc_read(server_info->file,length,pixels));
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 + 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 %
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265 % RelinquishDistributePixelCache() frees resources acquired with
1266 % OpenDistributePixelCache().
1268 % The format of the RelinquishDistributePixelCache method is:
1270 % MagickBooleanType RelinquishDistributePixelCache(
1271 % DistributeCacheInfo *server_info)
1273 % A description of each parameter follows:
1275 % o server_info: the distributed cache info.
1278 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1279 DistributeCacheInfo *server_info)
1287 register unsigned char
1291 message[MaxTextExtent];
1294 Delete distributed pixel cache.
1296 assert(server_info != (DistributeCacheInfo *) NULL);
1297 assert(server_info->signature == MagickSignature);
1300 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1301 p+=sizeof(server_info->session_key);
1302 count=dpc_send(server_info->file,p-message,message);
1303 if (count != (MagickOffsetType) (p-message))
1304 return(MagickFalse);
1305 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1306 if (count != (MagickOffsetType) sizeof(status))
1307 return(MagickFalse);
1312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316 + 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 %
1320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1323 % specified region of the distributed pixel cache.
1325 % The format of the WriteDistributePixelCacheMetacontents method is:
1327 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1328 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1329 % const MagickSizeType length,const unsigned char *metacontent)
1331 % A description of each parameter follows:
1333 % o server_info: the distributed cache info.
1335 % o image: the image.
1337 % o region: write the metacontent to this region of the image.
1339 % o length: the length in bytes of the metacontent.
1341 % o metacontent: write these metacontent to the pixel cache.
1344 MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1345 DistributeCacheInfo *server_info,const RectangleInfo *region,
1346 const MagickSizeType length,const unsigned char *metacontent)
1351 register unsigned char
1355 message[MaxTextExtent];
1358 Write distributed pixel cache metacontent.
1360 assert(server_info != (DistributeCacheInfo *) NULL);
1361 assert(server_info->signature == MagickSignature);
1362 assert(region != (RectangleInfo *) NULL);
1363 assert(metacontent != (unsigned char *) NULL);
1364 if (length > (MagickSizeType) SSIZE_MAX)
1368 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1369 p+=sizeof(server_info->session_key);
1370 (void) memcpy(p,®ion->width,sizeof(region->width));
1371 p+=sizeof(region->width);
1372 (void) memcpy(p,®ion->height,sizeof(region->height));
1373 p+=sizeof(region->height);
1374 (void) memcpy(p,®ion->x,sizeof(region->x));
1375 p+=sizeof(region->x);
1376 (void) memcpy(p,®ion->y,sizeof(region->y));
1377 p+=sizeof(region->y);
1378 (void) memcpy(p,&length,sizeof(length));
1380 count=dpc_send(server_info->file,p-message,message);
1381 if (count != (MagickOffsetType) (p-message))
1383 return(dpc_send(server_info->file,length,metacontent));
1387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1391 + 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 %
1395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397 % WriteDistributePixelCachePixels() writes image pixels to the specified
1398 % region of the distributed pixel cache.
1400 % The format of the WriteDistributePixelCachePixels method is:
1402 % MagickBooleanType WriteDistributePixelCachePixels(
1403 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1404 % const MagickSizeType length,const unsigned char *pixels)
1406 % A description of each parameter follows:
1408 % o server_info: the distributed cache info.
1410 % o image: the image.
1412 % o region: write the pixels to this region of the image.
1414 % o length: the length in bytes of the pixels.
1416 % o pixels: write these pixels to the pixel cache.
1419 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1420 DistributeCacheInfo *server_info,const RectangleInfo *region,
1421 const MagickSizeType length,const unsigned char *pixels)
1426 register unsigned char
1430 message[MaxTextExtent];
1433 Write distributed pixel cache pixels.
1435 assert(server_info != (DistributeCacheInfo *) NULL);
1436 assert(server_info->signature == MagickSignature);
1437 assert(region != (RectangleInfo *) NULL);
1438 assert(pixels != (const unsigned char *) NULL);
1439 if (length > (MagickSizeType) SSIZE_MAX)
1443 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1444 p+=sizeof(server_info->session_key);
1445 (void) memcpy(p,®ion->width,sizeof(region->width));
1446 p+=sizeof(region->width);
1447 (void) memcpy(p,®ion->height,sizeof(region->height));
1448 p+=sizeof(region->height);
1449 (void) memcpy(p,®ion->x,sizeof(region->x));
1450 p+=sizeof(region->x);
1451 (void) memcpy(p,®ion->y,sizeof(region->y));
1452 p+=sizeof(region->y);
1453 (void) memcpy(p,&length,sizeof(length));
1455 count=dpc_send(server_info->file,p-message,message);
1456 if (count != (MagickOffsetType) (p-message))
1458 return(dpc_send(server_info->file,length,pixels));