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
140 for (i=0; i < (MagickOffsetType) length; i+=count)
142 count=recv(file,message+i,(size_t) MagickMin(length-i,(MagickSizeType)
154 static int ConnectPixelCacheServer(const char *hostname,const int port,
155 size_t *session_key,ExceptionInfo *exception)
157 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
159 service[MaxTextExtent];
176 secret[MaxTextExtent];
179 Connect to distributed pixel cache and get session key.
182 shared_secret=GetPolicyValue("shared-secret");
183 if (shared_secret == (const char *) NULL)
185 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
186 "DistributedPixelCache","'%s'","shared secret expected");
189 (void) ResetMagickMemory(&hint,0,sizeof(hint));
190 hint.ai_family=AF_INET;
191 hint.ai_socktype=SOCK_STREAM;
192 hint.ai_flags=AI_PASSIVE;
193 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
194 status=getaddrinfo(hostname,service,&hint,&result);
197 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
198 "DistributedPixelCache","'%s'",hostname);
201 client_socket=socket(result->ai_family,result->ai_socktype,
202 result->ai_protocol);
203 if (client_socket == -1)
205 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
206 "DistributedPixelCache","'%s'",hostname);
209 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
212 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
213 "DistributedPixelCache","'%s'",hostname);
216 count=recv(client_socket,secret,MaxTextExtent,0);
222 nonce=AcquireStringInfo(count);
223 (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
224 *session_key=GetMagickSignature(nonce);
225 nonce=DestroyStringInfo(nonce);
227 if (*session_key == 0)
229 close(client_socket);
232 return(client_socket);
234 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
235 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
240 static char *GetHostname(int *port,ExceptionInfo *exception)
257 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
259 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",
261 if (hosts == (char *) NULL)
264 return(AcquireString(DPCHostname));
266 (void) SubstituteString(&hosts,","," ");
267 hostlist=StringToArgv(hosts,&argc);
268 hosts=DestroyString(hosts);
269 if (hostlist == (char **) NULL)
272 return(AcquireString(DPCHostname));
274 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
275 for (i=0; i < (ssize_t) argc; i++)
276 hostlist[i]=DestroyString(hostlist[i]);
277 hostlist=(char **) RelinquishMagickMemory(hostlist);
278 (void) SubstituteString(&hosts,":"," ");
279 hostlist=StringToArgv(hosts,&argc);
280 if (hostlist == (char **) NULL)
283 return(AcquireString(DPCHostname));
285 host=AcquireString(hostlist[1]);
286 if (hostlist[2] == (char *) NULL)
289 *port=StringToLong(hostlist[2]);
290 for (i=0; i < (ssize_t) argc; i++)
291 hostlist[i]=DestroyString(hostlist[i]);
292 hostlist=(char **) RelinquishMagickMemory(hostlist);
296 MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
297 ExceptionInfo *exception)
309 Connect to the distributed pixel cache server.
311 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
312 if (server_info == (DistributeCacheInfo *) NULL)
313 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
314 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
315 server_info->signature=MagickSignature;
317 hostname=GetHostname(&server_info->port,exception);
319 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
320 &session_key,exception);
321 server_info->session_key=session_key;
322 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
323 hostname=DestroyString(hostname);
324 if (server_info->file == -1)
325 server_info=DestroyDistributeCacheInfo(server_info);
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 + 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 %
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % DestroyDistributeCacheInfo() deallocates memory associated with an
341 % DistributeCacheInfo structure.
343 % The format of the DestroyDistributeCacheInfo method is:
345 % DistributeCacheInfo *DestroyDistributeCacheInfo(
346 % DistributeCacheInfo *server_info)
348 % A description of each parameter follows:
350 % o server_info: the distributed cache info.
353 MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
354 DistributeCacheInfo *server_info)
356 assert(server_info != (DistributeCacheInfo *) NULL);
357 assert(server_info->signature == MagickSignature);
358 if (server_info->file > 0)
359 (void) close(server_info->file);
360 server_info->signature=(~MagickSignature);
361 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 + 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 %
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376 % DistributePixelCacheServer() waits on the specified port for commands to
377 % create, read, update, or destroy a pixel cache.
379 % The format of the DistributePixelCacheServer() method is:
381 % void DistributePixelCacheServer(const int port)
383 % A description of each parameter follows:
385 % o port: connect the distributed pixel cache at this port.
387 % o exception: return any errors or warnings in this structure.
391 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
392 int magick_unused(file),const size_t session_key)
395 Destroy distributed pixel cache.
397 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
400 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
401 const unsigned char *restrict message)
406 register MagickOffsetType
410 Ensure a complete message is sent.
413 for (i=0; i < (MagickOffsetType) length; i+=count)
415 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
416 (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
427 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
428 int file,const size_t session_key,ExceptionInfo *exception)
442 register unsigned char
446 message[MaxTextExtent];
449 Open distributed pixel cache.
451 image=AcquireImage((ImageInfo *) NULL,exception);
452 if (image == (Image *) NULL)
454 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
455 sizeof(image->alpha_trait)+sizeof(image->read_mask)+
456 sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+
457 sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+
458 sizeof(image->metacontent_extent);
459 count=dpc_read(file,length,message);
460 if (count != (MagickOffsetType) length)
463 Deserialize the image attributes.
466 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
467 p+=sizeof(image->storage_class);
468 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
469 p+=sizeof(image->colorspace);
470 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
471 p+=sizeof(image->alpha_trait);
472 (void) memcpy(&image->read_mask,p,sizeof(image->read_mask));
473 p+=sizeof(image->read_mask);
474 (void) memcpy(&image->write_mask,p,sizeof(image->write_mask));
475 p+=sizeof(image->write_mask);
476 (void) memcpy(&image->columns,p,sizeof(image->columns));
477 p+=sizeof(image->columns);
478 (void) memcpy(&image->rows,p,sizeof(image->rows));
479 p+=sizeof(image->rows);
480 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
481 p+=sizeof(image->number_channels);
482 (void) memcpy(image->channel_map,p,MaxPixelChannels*
483 sizeof(*image->channel_map));
484 p+=MaxPixelChannels*sizeof(*image->channel_map);
485 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
486 p+=sizeof(image->metacontent_extent);
487 if (SyncImagePixelCache(image,exception) == MagickFalse)
489 status=AddValueToSplayTree(registry,(const void *) session_key,image);
493 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
494 int file,const size_t session_key,ExceptionInfo *exception)
511 register const Quantum
514 register unsigned char
518 message[MaxTextExtent];
521 Read distributed pixel cache metacontent.
523 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
524 if (image == (Image *) NULL)
526 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
527 sizeof(region.y)+sizeof(length);
528 count=dpc_read(file,length,message);
529 if (count != (MagickOffsetType) length)
532 (void) memcpy(®ion.width,q,sizeof(region.width));
533 q+=sizeof(region.width);
534 (void) memcpy(®ion.height,q,sizeof(region.height));
535 q+=sizeof(region.height);
536 (void) memcpy(®ion.x,q,sizeof(region.x));
538 (void) memcpy(®ion.y,q,sizeof(region.y));
540 (void) memcpy(&length,q,sizeof(length));
542 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
544 if (p == (const Quantum *) NULL)
546 metacontent=(const unsigned char *) GetVirtualMetacontent(image);
547 count=dpc_send(file,length,metacontent);
548 if (count != (MagickOffsetType) length)
553 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
554 int file,const size_t session_key,ExceptionInfo *exception)
568 register const Quantum
571 register unsigned char
575 message[MaxTextExtent];
578 Read distributed pixel cache pixels.
580 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
581 if (image == (Image *) NULL)
583 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
584 sizeof(region.y)+sizeof(length);
585 count=dpc_read(file,length,message);
586 if (count != (MagickOffsetType) length)
589 (void) memcpy(®ion.width,q,sizeof(region.width));
590 q+=sizeof(region.width);
591 (void) memcpy(®ion.height,q,sizeof(region.height));
592 q+=sizeof(region.height);
593 (void) memcpy(®ion.x,q,sizeof(region.x));
595 (void) memcpy(®ion.y,q,sizeof(region.y));
597 (void) memcpy(&length,q,sizeof(length));
599 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
601 if (p == (const Quantum *) NULL)
603 count=dpc_send(file,length,(unsigned char *) p);
604 if (count != (MagickOffsetType) length)
609 static void *RelinquishImageRegistry(void *image)
611 return((void *) DestroyImageList((Image *) image));
614 static MagickBooleanType WriteDistributeCacheMetacontent(
615 SplayTreeInfo *registry,int file,const size_t session_key,
616 ExceptionInfo *exception)
633 register unsigned char
637 message[MaxTextExtent],
641 Write distributed pixel cache metacontent.
643 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
644 if (image == (Image *) NULL)
646 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
647 sizeof(region.y)+sizeof(length);
648 count=dpc_read(file,length,message);
649 if (count != (MagickOffsetType) length)
652 (void) memcpy(®ion.width,p,sizeof(region.width));
653 p+=sizeof(region.width);
654 (void) memcpy(®ion.height,p,sizeof(region.height));
655 p+=sizeof(region.height);
656 (void) memcpy(®ion.x,p,sizeof(region.x));
658 (void) memcpy(®ion.y,p,sizeof(region.y));
660 (void) memcpy(&length,p,sizeof(length));
662 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
664 if (q == (Quantum *) NULL)
666 metacontent=(unsigned char *) GetAuthenticMetacontent(image);
667 count=dpc_read(file,length,metacontent);
668 if (count != (MagickOffsetType) length)
670 return(SyncAuthenticPixels(image,exception));
673 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
674 int file,const size_t session_key,ExceptionInfo *exception)
691 register unsigned char
695 message[MaxTextExtent];
698 Write distributed pixel cache pixels.
700 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
701 if (image == (Image *) NULL)
703 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
704 sizeof(region.y)+sizeof(length);
705 count=dpc_read(file,length,message);
706 if (count != (MagickOffsetType) length)
709 (void) memcpy(®ion.width,p,sizeof(region.width));
710 p+=sizeof(region.width);
711 (void) memcpy(®ion.height,p,sizeof(region.height));
712 p+=sizeof(region.height);
713 (void) memcpy(®ion.x,p,sizeof(region.x));
715 (void) memcpy(®ion.y,p,sizeof(region.y));
717 (void) memcpy(&length,p,sizeof(length));
719 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
721 if (q == (Quantum *) NULL)
723 count=dpc_read(file,length,(unsigned char *) q);
724 if (count != (MagickOffsetType) length)
726 return(SyncAuthenticPixels(image,exception));
729 static void *DistributePixelCacheClient(void *socket)
746 register unsigned char
764 session[2*MaxTextExtent];
767 Distributed pixel cache client.
769 shared_secret=GetPolicyValue("shared-secret");
770 if (shared_secret == (const char *) NULL)
771 ThrowFatalException(CacheFatalError,"shared secret expected");
773 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
774 p+=strlen(shared_secret);
775 random_info=AcquireRandomInfo();
776 secret=GetRandomKey(random_info,DPCSessionKeyLength);
777 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
778 session_key=GetMagickSignature(secret);
779 random_info=DestroyRandomInfo(random_info);
780 exception=AcquireExceptionInfo();
781 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
782 (void *(*)(void *)) NULL,RelinquishImageRegistry);
783 client_socket=(*(int *) socket);
784 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
785 secret=DestroyStringInfo(secret);
788 count=dpc_read(client_socket,1,(unsigned char *) &command);
791 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
792 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
799 status=OpenDistributeCache(registry,client_socket,session_key,
801 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
806 status=ReadDistributeCachePixels(registry,client_socket,session_key,
812 status=ReadDistributeCacheMetacontent(registry,client_socket,
813 session_key,exception);
818 status=WriteDistributeCachePixels(registry,client_socket,session_key,
824 status=WriteDistributeCacheMetacontent(registry,client_socket,
825 session_key,exception);
830 status=DestroyDistributeCache(registry,client_socket,session_key);
836 if (status == MagickFalse)
841 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
842 (void) close(client_socket);
843 exception=DestroyExceptionInfo(exception);
844 registry=DestroySplayTree(registry);
845 return((void *) NULL);
848 MagickExport void DistributePixelCacheServer(const int port,
849 ExceptionInfo *exception)
851 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
853 service[MaxTextExtent];
865 register struct addrinfo
876 Launch distributed pixel cache server.
878 assert(exception != (ExceptionInfo *) NULL);
879 assert(exception->signature == MagickSignature);
880 (void) ResetMagickMemory(&hint,0,sizeof(hint));
881 hint.ai_family=AF_INET;
882 hint.ai_socktype=SOCK_STREAM;
883 hint.ai_flags=AI_PASSIVE;
884 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
885 status=getaddrinfo((const char *) NULL,service,&hint,&result);
887 ThrowFatalException(CacheFatalError,"UnableToListen");
889 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
894 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
895 if (server_socket == -1)
898 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
902 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
905 (void) close(status);
910 if (p == (struct addrinfo *) NULL)
911 ThrowFatalException(CacheFatalError,"UnableToBind");
912 freeaddrinfo(result);
913 status=listen(server_socket,DPCPendingConnections);
915 ThrowFatalException(CacheFatalError,"UnableToListen");
916 pthread_attr_init(&attributes);
925 length=(socklen_t) sizeof(address);
926 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
927 if (client_socket == -1)
928 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
929 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
930 (void *) &client_socket);
932 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
934 (void) close(server_socket);
936 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 + G e t D i s t r i b u t e C a c h e F i l e %
949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 % GetDistributeCacheFile() returns the file associated with this
952 % DistributeCacheInfo structure.
954 % The format of the GetDistributeCacheFile method is:
956 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
958 % A description of each parameter follows:
960 % o server_info: the distributed cache info.
963 MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
965 assert(server_info != (DistributeCacheInfo *) NULL);
966 assert(server_info->signature == MagickSignature);
967 return(server_info->file);
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 + 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 %
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981 % GetDistributeCacheHostname() returns the hostname associated with this
982 % DistributeCacheInfo structure.
984 % The format of the GetDistributeCacheHostname method is:
986 % const char *GetDistributeCacheHostname(
987 % const DistributeCacheInfo *server_info)
989 % A description of each parameter follows:
991 % o server_info: the distributed cache info.
994 MagickPrivate const char *GetDistributeCacheHostname(
995 const DistributeCacheInfo *server_info)
997 assert(server_info != (DistributeCacheInfo *) NULL);
998 assert(server_info->signature == MagickSignature);
999 return(server_info->hostname);
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1007 + G e t D i s t r i b u t e C a c h e P o r t %
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013 % GetDistributeCachePort() returns the port associated with this
1014 % DistributeCacheInfo structure.
1016 % The format of the GetDistributeCachePort method is:
1018 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1020 % A description of each parameter follows:
1022 % o server_info: the distributed cache info.
1025 MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1027 assert(server_info != (DistributeCacheInfo *) NULL);
1028 assert(server_info->signature == MagickSignature);
1029 return(server_info->port);
1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 + O p e n D i s t r i b u t e P i x e l C a c h e %
1041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1045 % The format of the OpenDistributePixelCache method is:
1047 % MagickBooleanType *OpenDistributePixelCache(
1048 % DistributeCacheInfo *server_info,Image *image)
1050 % A description of each parameter follows:
1052 % o server_info: the distributed cache info.
1054 % o image: the image.
1057 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1058 DistributeCacheInfo *server_info,Image *image)
1066 register unsigned char
1070 message[MaxTextExtent];
1073 Open distributed pixel cache.
1075 assert(server_info != (DistributeCacheInfo *) NULL);
1076 assert(server_info->signature == MagickSignature);
1077 assert(image != (Image *) NULL);
1078 assert(image->signature == MagickSignature);
1080 *p++='o'; /* open */
1082 Serialize image attributes (see ValidatePixelCacheMorphology()).
1084 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1085 p+=sizeof(server_info->session_key);
1086 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1087 p+=sizeof(image->storage_class);
1088 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1089 p+=sizeof(image->colorspace);
1090 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1091 p+=sizeof(image->alpha_trait);
1092 (void) memcpy(p,&image->read_mask,sizeof(image->read_mask));
1093 p+=sizeof(image->read_mask);
1094 (void) memcpy(p,&image->write_mask,sizeof(image->write_mask));
1095 p+=sizeof(image->write_mask);
1096 (void) memcpy(p,&image->columns,sizeof(image->columns));
1097 p+=sizeof(image->columns);
1098 (void) memcpy(p,&image->rows,sizeof(image->rows));
1099 p+=sizeof(image->rows);
1100 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1101 p+=sizeof(image->number_channels);
1102 (void) memcpy(p,image->channel_map,MaxPixelChannels*
1103 sizeof(*image->channel_map));
1104 p+=MaxPixelChannels*sizeof(*image->channel_map);
1105 (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1106 p+=sizeof(image->metacontent_extent);
1107 count=dpc_send(server_info->file,p-message,message);
1108 if (count != (MagickOffsetType) (p-message))
1109 return(MagickFalse);
1111 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1112 if (count != (MagickOffsetType) sizeof(status))
1113 return(MagickFalse);
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1122 + 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 %
1126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1129 % region of the distributed pixel cache.
1131 % The format of the ReadDistributePixelCacheMetacontents method is:
1133 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1134 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1135 % const MagickSizeType length,unsigned char *metacontent)
1137 % A description of each parameter follows:
1139 % o server_info: the distributed cache info.
1141 % o image: the image.
1143 % o region: read the metacontent from this region of the image.
1145 % o length: the length in bytes of the metacontent.
1147 % o metacontent: read these metacontent from the pixel cache.
1150 MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1151 DistributeCacheInfo *server_info,const RectangleInfo *region,
1152 const MagickSizeType length,unsigned char *metacontent)
1157 register unsigned char
1161 message[MaxTextExtent];
1164 Read distributed pixel cache metacontent.
1166 assert(server_info != (DistributeCacheInfo *) NULL);
1167 assert(server_info->signature == MagickSignature);
1168 assert(region != (RectangleInfo *) NULL);
1169 assert(metacontent != (unsigned char *) NULL);
1170 if (length > (MagickSizeType) SSIZE_MAX)
1174 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1175 p+=sizeof(server_info->session_key);
1176 (void) memcpy(p,®ion->width,sizeof(region->width));
1177 p+=sizeof(region->width);
1178 (void) memcpy(p,®ion->height,sizeof(region->height));
1179 p+=sizeof(region->height);
1180 (void) memcpy(p,®ion->x,sizeof(region->x));
1181 p+=sizeof(region->x);
1182 (void) memcpy(p,®ion->y,sizeof(region->y));
1183 p+=sizeof(region->y);
1184 (void) memcpy(p,&length,sizeof(length));
1186 count=dpc_send(server_info->file,p-message,message);
1187 if (count != (MagickOffsetType) (p-message))
1189 return(dpc_read(server_info->file,length,metacontent));
1193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197 + 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 %
1201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1204 % the distributed pixel cache.
1206 % The format of the ReadDistributePixelCachePixels method is:
1208 % MagickOffsetType ReadDistributePixelCachePixels(
1209 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1210 % const MagickSizeType length,unsigned char *restrict pixels)
1212 % A description of each parameter follows:
1214 % o server_info: the distributed cache info.
1216 % o image: the image.
1218 % o region: read the pixels from this region of the image.
1220 % o length: the length in bytes of the pixels.
1222 % o pixels: read these pixels from the pixel cache.
1225 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1226 DistributeCacheInfo *server_info,const RectangleInfo *region,
1227 const MagickSizeType length,unsigned char *restrict pixels)
1232 register unsigned char
1236 message[MaxTextExtent];
1239 Read distributed pixel cache pixels.
1241 assert(server_info != (DistributeCacheInfo *) NULL);
1242 assert(server_info->signature == MagickSignature);
1243 assert(region != (RectangleInfo *) NULL);
1244 assert(pixels != (unsigned char *) NULL);
1245 if (length > (MagickSizeType) SSIZE_MAX)
1249 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1250 p+=sizeof(server_info->session_key);
1251 (void) memcpy(p,®ion->width,sizeof(region->width));
1252 p+=sizeof(region->width);
1253 (void) memcpy(p,®ion->height,sizeof(region->height));
1254 p+=sizeof(region->height);
1255 (void) memcpy(p,®ion->x,sizeof(region->x));
1256 p+=sizeof(region->x);
1257 (void) memcpy(p,®ion->y,sizeof(region->y));
1258 p+=sizeof(region->y);
1259 (void) memcpy(p,&length,sizeof(length));
1261 count=dpc_send(server_info->file,p-message,message);
1262 if (count != (MagickOffsetType) (p-message))
1264 return(dpc_read(server_info->file,length,pixels));
1268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1272 + 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 %
1276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1278 % RelinquishDistributePixelCache() frees resources acquired with
1279 % OpenDistributePixelCache().
1281 % The format of the RelinquishDistributePixelCache method is:
1283 % MagickBooleanType RelinquishDistributePixelCache(
1284 % DistributeCacheInfo *server_info)
1286 % A description of each parameter follows:
1288 % o server_info: the distributed cache info.
1291 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1292 DistributeCacheInfo *server_info)
1300 register unsigned char
1304 message[MaxTextExtent];
1307 Delete distributed pixel cache.
1309 assert(server_info != (DistributeCacheInfo *) NULL);
1310 assert(server_info->signature == MagickSignature);
1313 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1314 p+=sizeof(server_info->session_key);
1315 count=dpc_send(server_info->file,p-message,message);
1316 if (count != (MagickOffsetType) (p-message))
1317 return(MagickFalse);
1318 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1319 if (count != (MagickOffsetType) sizeof(status))
1320 return(MagickFalse);
1325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 + 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 %
1333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1336 % specified region of the distributed pixel cache.
1338 % The format of the WriteDistributePixelCacheMetacontents method is:
1340 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1341 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1342 % const MagickSizeType length,const unsigned char *metacontent)
1344 % A description of each parameter follows:
1346 % o server_info: the distributed cache info.
1348 % o image: the image.
1350 % o region: write the metacontent to this region of the image.
1352 % o length: the length in bytes of the metacontent.
1354 % o metacontent: write these metacontent to the pixel cache.
1357 MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1358 DistributeCacheInfo *server_info,const RectangleInfo *region,
1359 const MagickSizeType length,const unsigned char *metacontent)
1364 register unsigned char
1368 message[MaxTextExtent];
1371 Write distributed pixel cache metacontent.
1373 assert(server_info != (DistributeCacheInfo *) NULL);
1374 assert(server_info->signature == MagickSignature);
1375 assert(region != (RectangleInfo *) NULL);
1376 assert(metacontent != (unsigned char *) NULL);
1377 if (length > (MagickSizeType) SSIZE_MAX)
1381 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1382 p+=sizeof(server_info->session_key);
1383 (void) memcpy(p,®ion->width,sizeof(region->width));
1384 p+=sizeof(region->width);
1385 (void) memcpy(p,®ion->height,sizeof(region->height));
1386 p+=sizeof(region->height);
1387 (void) memcpy(p,®ion->x,sizeof(region->x));
1388 p+=sizeof(region->x);
1389 (void) memcpy(p,®ion->y,sizeof(region->y));
1390 p+=sizeof(region->y);
1391 (void) memcpy(p,&length,sizeof(length));
1393 count=dpc_send(server_info->file,p-message,message);
1394 if (count != (MagickOffsetType) (p-message))
1396 return(dpc_send(server_info->file,length,metacontent));
1400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404 + 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 %
1408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410 % WriteDistributePixelCachePixels() writes image pixels to the specified
1411 % region of the distributed pixel cache.
1413 % The format of the WriteDistributePixelCachePixels method is:
1415 % MagickBooleanType WriteDistributePixelCachePixels(
1416 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1417 % const MagickSizeType length,const unsigned char *restrict pixels)
1419 % A description of each parameter follows:
1421 % o server_info: the distributed cache info.
1423 % o image: the image.
1425 % o region: write the pixels to this region of the image.
1427 % o length: the length in bytes of the pixels.
1429 % o pixels: write these pixels to the pixel cache.
1432 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1433 DistributeCacheInfo *server_info,const RectangleInfo *region,
1434 const MagickSizeType length,const unsigned char *restrict pixels)
1439 register unsigned char
1443 message[MaxTextExtent];
1446 Write distributed pixel cache pixels.
1448 assert(server_info != (DistributeCacheInfo *) NULL);
1449 assert(server_info->signature == MagickSignature);
1450 assert(region != (RectangleInfo *) NULL);
1451 assert(pixels != (const unsigned char *) NULL);
1452 if (length > (MagickSizeType) SSIZE_MAX)
1456 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1457 p+=sizeof(server_info->session_key);
1458 (void) memcpy(p,®ion->width,sizeof(region->width));
1459 p+=sizeof(region->width);
1460 (void) memcpy(p,®ion->height,sizeof(region->height));
1461 p+=sizeof(region->height);
1462 (void) memcpy(p,®ion->x,sizeof(region->x));
1463 p+=sizeof(region->x);
1464 (void) memcpy(p,®ion->y,sizeof(region->y));
1465 p+=sizeof(region->y);
1466 (void) memcpy(p,&length,sizeof(length));
1468 count=dpc_send(server_info->file,p-message,message);
1469 if (count != (MagickOffsetType) (p-message))
1471 return(dpc_send(server_info->file,length,pixels));