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 #if defined(MAGICKCORE_HAVE_SOCKET)
75 #include <netinet/in.h>
77 #include <sys/socket.h>
78 #include <arpa/inet.h>
84 #define DPCHostname "127.0.0.1"
85 #define DPCPendingConnections 10
87 #define DPCSessionKeyLength 8
89 # define MSG_NOSIGNAL 0
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 + 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 %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
105 % The format of the AcquireDistributeCacheInfo method is:
107 % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
109 % A description of each parameter follows:
111 % o exception: return any errors or warnings in this structure.
115 static inline MagickSizeType MagickMin(const MagickSizeType x,
116 const MagickSizeType y)
123 static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
124 unsigned char *restrict message)
126 register MagickOffsetType
133 for (i=0; i < (MagickOffsetType) length; i+=count)
135 count=recv(file,message+i,(size_t) MagickMin(length-i,(MagickSizeType)
147 static int ConnectPixelCacheServer(const char *hostname,const int port,
148 size_t *session_key,ExceptionInfo *exception)
150 #if defined(MAGICKCORE_HAVE_SOCKET)
152 service[MaxTextExtent];
169 secret[MaxTextExtent];
172 Connect to distributed pixel cache and get session key.
175 shared_secret=GetPolicyValue("shared-secret");
176 if (shared_secret == (const char *) NULL)
178 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
179 "DistributedPixelCache","'%s'","shared secret expected");
182 (void) ResetMagickMemory(&hint,0,sizeof(hint));
183 hint.ai_family=AF_INET;
184 hint.ai_socktype=SOCK_STREAM;
185 hint.ai_flags=AI_PASSIVE;
186 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
187 status=getaddrinfo(hostname,service,&hint,&result);
190 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
191 "DistributedPixelCache","'%s'",hostname);
194 client_socket=socket(result->ai_family,result->ai_socktype,
195 result->ai_protocol);
196 if (client_socket == -1)
198 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
199 "DistributedPixelCache","'%s'",hostname);
202 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
205 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
206 "DistributedPixelCache","'%s'",hostname);
209 count=recv(client_socket,secret,MaxTextExtent,0);
215 nonce=AcquireStringInfo(count);
216 (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
217 *session_key=GetMagickSignature(nonce);
218 nonce=DestroyStringInfo(nonce);
220 if (*session_key == 0)
222 close(client_socket);
225 return(client_socket);
227 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
228 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
233 static char *GetHostname(int *port,ExceptionInfo *exception)
250 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
252 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",
254 if (hosts == (char *) NULL)
257 return(AcquireString(DPCHostname));
259 (void) SubstituteString(&hosts,","," ");
260 hostlist=StringToArgv(hosts,&argc);
261 hosts=DestroyString(hosts);
262 if (hostlist == (char **) NULL)
265 return(AcquireString(DPCHostname));
267 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
268 for (i=0; i < (ssize_t) argc; i++)
269 hostlist[i]=DestroyString(hostlist[i]);
270 hostlist=(char **) RelinquishMagickMemory(hostlist);
271 (void) SubstituteString(&hosts,":"," ");
272 hostlist=StringToArgv(hosts,&argc);
273 if (hostlist == (char **) NULL)
276 return(AcquireString(DPCHostname));
278 host=AcquireString(hostlist[1]);
279 if (hostlist[2] == (char *) NULL)
282 *port=StringToLong(hostlist[2]);
283 for (i=0; i < (ssize_t) argc; i++)
284 hostlist[i]=DestroyString(hostlist[i]);
285 hostlist=(char **) RelinquishMagickMemory(hostlist);
289 MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
290 ExceptionInfo *exception)
302 Connect to the distributed pixel cache server.
304 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
305 if (server_info == (DistributeCacheInfo *) NULL)
306 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
307 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
308 server_info->signature=MagickSignature;
310 hostname=GetHostname(&server_info->port,exception);
312 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
313 &session_key,exception);
314 server_info->session_key=session_key;
315 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
316 hostname=DestroyString(hostname);
317 if (server_info->file == -1)
318 server_info=DestroyDistributeCacheInfo(server_info);
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327 + 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 %
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % DestroyDistributeCacheInfo() deallocates memory associated with an
334 % DistributeCacheInfo structure.
336 % The format of the DestroyDistributeCacheInfo method is:
338 % DistributeCacheInfo *DestroyDistributeCacheInfo(
339 % DistributeCacheInfo *server_info)
341 % A description of each parameter follows:
343 % o server_info: the distributed cache info.
346 MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
347 DistributeCacheInfo *server_info)
349 assert(server_info != (DistributeCacheInfo *) NULL);
350 assert(server_info->signature == MagickSignature);
351 if (server_info->file > 0)
352 (void) close(server_info->file);
353 server_info->signature=(~MagickSignature);
354 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 + 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 %
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % DistributePixelCacheServer() waits on the specified port for commands to
370 % create, read, update, or destroy a pixel cache.
372 % The format of the DistributePixelCacheServer() method is:
374 % void DistributePixelCacheServer(const int port)
376 % A description of each parameter follows:
378 % o port: connect the distributed pixel cache at this port.
380 % o exception: return any errors or warnings in this structure.
384 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
385 int file,const size_t session_key)
388 Destroy distributed pixel cache.
390 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
393 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
394 const unsigned char *restrict message)
399 register MagickOffsetType
403 Ensure a complete message is sent.
406 for (i=0; i < (MagickOffsetType) length; i+=count)
408 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
409 (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
420 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
421 int file,const size_t session_key,ExceptionInfo *exception)
435 register unsigned char
439 message[MaxTextExtent];
442 Open distributed pixel cache.
444 image=AcquireImage((ImageInfo *) NULL,exception);
445 if (image == (Image *) NULL)
447 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
448 sizeof(image->alpha_trait)+sizeof(image->mask)+sizeof(image->columns)+
449 sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels*
450 sizeof(*image->channel_map)+sizeof(image->metacontent_extent);
451 count=dpc_read(file,length,message);
452 if (count != (MagickOffsetType) length)
455 Deserialize the image attributes.
458 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
459 p+=sizeof(image->storage_class);
460 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
461 p+=sizeof(image->colorspace);
462 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
463 p+=sizeof(image->alpha_trait);
464 (void) memcpy(&image->mask,p,sizeof(image->mask));
465 p+=sizeof(image->mask);
466 (void) memcpy(&image->columns,p,sizeof(image->columns));
467 p+=sizeof(image->columns);
468 (void) memcpy(&image->rows,p,sizeof(image->rows));
469 p+=sizeof(image->rows);
470 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
471 p+=sizeof(image->number_channels);
472 (void) memcpy(image->channel_map,p,MaxPixelChannels*
473 sizeof(*image->channel_map));
474 p+=MaxPixelChannels*sizeof(*image->channel_map);
475 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
476 p+=sizeof(image->metacontent_extent);
477 if (SyncImagePixelCache(image,exception) == MagickFalse)
479 status=AddValueToSplayTree(registry,(const void *) session_key,image);
483 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
484 int file,const size_t session_key,ExceptionInfo *exception)
501 register const Quantum
504 register unsigned char
508 message[MaxTextExtent];
511 Read distributed pixel cache metacontent.
513 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
514 if (image == (Image *) NULL)
516 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
517 sizeof(region.y)+sizeof(length);
518 count=dpc_read(file,length,message);
519 if (count != (MagickOffsetType) length)
522 (void) memcpy(®ion.width,q,sizeof(region.width));
523 q+=sizeof(region.width);
524 (void) memcpy(®ion.height,q,sizeof(region.height));
525 q+=sizeof(region.height);
526 (void) memcpy(®ion.x,q,sizeof(region.x));
528 (void) memcpy(®ion.y,q,sizeof(region.y));
530 (void) memcpy(&length,q,sizeof(length));
532 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
534 if (p == (const Quantum *) NULL)
536 metacontent=GetVirtualMetacontent(image);
537 count=dpc_send(file,length,metacontent);
538 if (count != (MagickOffsetType) length)
543 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
544 int file,const size_t session_key,ExceptionInfo *exception)
558 register const Quantum
561 register unsigned char
565 message[MaxTextExtent];
568 Read distributed pixel cache pixels.
570 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
571 if (image == (Image *) NULL)
573 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
574 sizeof(region.y)+sizeof(length);
575 count=dpc_read(file,length,message);
576 if (count != (MagickOffsetType) length)
579 (void) memcpy(®ion.width,q,sizeof(region.width));
580 q+=sizeof(region.width);
581 (void) memcpy(®ion.height,q,sizeof(region.height));
582 q+=sizeof(region.height);
583 (void) memcpy(®ion.x,q,sizeof(region.x));
585 (void) memcpy(®ion.y,q,sizeof(region.y));
587 (void) memcpy(&length,q,sizeof(length));
589 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
591 if (p == (const Quantum *) NULL)
593 count=dpc_send(file,length,(unsigned char *) p);
594 if (count != (MagickOffsetType) length)
599 static void *RelinquishImageRegistry(void *image)
601 return((void *) DestroyImageList((Image *) image));
604 static MagickBooleanType WriteDistributeCacheMetacontent(
605 SplayTreeInfo *registry,int file,const size_t session_key,
606 ExceptionInfo *exception)
623 register unsigned char
627 message[MaxTextExtent],
631 Write distributed pixel cache metacontent.
633 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
634 if (image == (Image *) NULL)
636 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
637 sizeof(region.y)+sizeof(length);
638 count=dpc_read(file,length,message);
639 if (count != (MagickOffsetType) length)
642 (void) memcpy(®ion.width,p,sizeof(region.width));
643 p+=sizeof(region.width);
644 (void) memcpy(®ion.height,p,sizeof(region.height));
645 p+=sizeof(region.height);
646 (void) memcpy(®ion.x,p,sizeof(region.x));
648 (void) memcpy(®ion.y,p,sizeof(region.y));
650 (void) memcpy(&length,p,sizeof(length));
652 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
654 if (q == (Quantum *) NULL)
656 metacontent=GetAuthenticMetacontent(image);
657 count=dpc_read(file,length,metacontent);
658 if (count != (MagickOffsetType) length)
660 return(SyncAuthenticPixels(image,exception));
663 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
664 int file,const size_t session_key,ExceptionInfo *exception)
681 register unsigned char
685 message[MaxTextExtent];
688 Write distributed pixel cache pixels.
690 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
691 if (image == (Image *) NULL)
693 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
694 sizeof(region.y)+sizeof(length);
695 count=dpc_read(file,length,message);
696 if (count != (MagickOffsetType) length)
699 (void) memcpy(®ion.width,p,sizeof(region.width));
700 p+=sizeof(region.width);
701 (void) memcpy(®ion.height,p,sizeof(region.height));
702 p+=sizeof(region.height);
703 (void) memcpy(®ion.x,p,sizeof(region.x));
705 (void) memcpy(®ion.y,p,sizeof(region.y));
707 (void) memcpy(&length,p,sizeof(length));
709 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
711 if (q == (Quantum *) NULL)
713 count=dpc_read(file,length,(unsigned char *) q);
714 if (count != (MagickOffsetType) length)
716 return(SyncAuthenticPixels(image,exception));
719 static void *DistributePixelCacheClient(void *socket)
736 register unsigned char
754 session[2*MaxTextExtent];
757 Distributed pixel cache client.
759 shared_secret=GetPolicyValue("shared-secret");
760 if (shared_secret == (const char *) NULL)
761 ThrowFatalException(CacheFatalError,"shared secret expected");
763 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
764 p+=strlen(shared_secret);
765 random_info=AcquireRandomInfo();
766 secret=GetRandomKey(random_info,DPCSessionKeyLength);
767 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
768 session_key=GetMagickSignature(secret);
769 random_info=DestroyRandomInfo(random_info);
770 exception=AcquireExceptionInfo();
771 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
772 (void *(*)(void *)) NULL,RelinquishImageRegistry);
773 client_socket=(*(int *) socket);
774 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
775 secret=DestroyStringInfo(secret);
778 count=dpc_read(client_socket,1,(unsigned char *) &command);
781 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
782 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
789 status=OpenDistributeCache(registry,client_socket,session_key,
791 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
796 status=ReadDistributeCachePixels(registry,client_socket,session_key,
802 status=ReadDistributeCacheMetacontent(registry,client_socket,
803 session_key,exception);
808 status=WriteDistributeCachePixels(registry,client_socket,session_key,
814 status=WriteDistributeCacheMetacontent(registry,client_socket,
815 session_key,exception);
820 status=DestroyDistributeCache(registry,client_socket,session_key);
826 if (status == MagickFalse)
831 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
832 (void) close(client_socket);
833 exception=DestroyExceptionInfo(exception);
834 registry=DestroySplayTree(registry);
835 return((void *) NULL);
838 MagickExport void DistributePixelCacheServer(const int port,
839 ExceptionInfo *exception)
841 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
843 service[MaxTextExtent];
855 register struct addrinfo
866 Launch distributed pixel cache server.
868 (void) ResetMagickMemory(&hint,0,sizeof(hint));
869 hint.ai_family=AF_INET;
870 hint.ai_socktype=SOCK_STREAM;
871 hint.ai_flags=AI_PASSIVE;
872 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
873 status=getaddrinfo((const char *) NULL,service,&hint,&result);
875 ThrowFatalException(CacheFatalError,"UnableToListen");
877 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
882 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
883 if (server_socket == -1)
886 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
890 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
893 (void) close(status);
898 if (p == (struct addrinfo *) NULL)
899 ThrowFatalException(CacheFatalError,"UnableToBind");
900 freeaddrinfo(result);
901 status=listen(server_socket,DPCPendingConnections);
903 ThrowFatalException(CacheFatalError,"UnableToListen");
904 pthread_attr_init(&attributes);
913 length=(socklen_t) sizeof(address);
914 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
915 if (client_socket == -1)
916 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
917 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
918 (void *) &client_socket);
920 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
922 (void) close(server_socket);
924 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
933 + G e t D i s t r i b u t e C a c h e F i l e %
937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939 % GetDistributeCacheFile() returns the file associated with this
940 % DistributeCacheInfo structure.
942 % The format of the GetDistributeCacheFile method is:
944 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
946 % A description of each parameter follows:
948 % o server_info: the distributed cache info.
951 MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
953 assert(server_info != (DistributeCacheInfo *) NULL);
954 assert(server_info->signature == MagickSignature);
955 return(server_info->file);
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 + 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 %
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 % GetDistributeCacheHostname() returns the hostname associated with this
970 % DistributeCacheInfo structure.
972 % The format of the GetDistributeCacheHostname method is:
974 % const char *GetDistributeCacheHostname(
975 % const DistributeCacheInfo *server_info)
977 % A description of each parameter follows:
979 % o server_info: the distributed cache info.
982 MagickPrivate const char *GetDistributeCacheHostname(
983 const DistributeCacheInfo *server_info)
985 assert(server_info != (DistributeCacheInfo *) NULL);
986 assert(server_info->signature == MagickSignature);
987 return(server_info->hostname);
991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 + G e t D i s t r i b u t e C a c h e P o r t %
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 % GetDistributeCachePort() returns the port associated with this
1002 % DistributeCacheInfo structure.
1004 % The format of the GetDistributeCachePort method is:
1006 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1008 % A description of each parameter follows:
1010 % o server_info: the distributed cache info.
1013 MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1015 assert(server_info != (DistributeCacheInfo *) NULL);
1016 assert(server_info->signature == MagickSignature);
1017 return(server_info->port);
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 + O p e n D i s t r i b u t e P i x e l C a c h e %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1033 % The format of the OpenDistributePixelCache method is:
1035 % MagickBooleanType *OpenDistributePixelCache(
1036 % DistributeCacheInfo *server_info,Image *image)
1038 % A description of each parameter follows:
1040 % o server_info: the distributed cache info.
1042 % o image: the image.
1045 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1046 DistributeCacheInfo *server_info,Image *image)
1054 register unsigned char
1058 message[MaxTextExtent];
1061 Open distributed pixel cache.
1063 assert(server_info != (DistributeCacheInfo *) NULL);
1064 assert(server_info->signature == MagickSignature);
1065 assert(image != (Image *) NULL);
1066 assert(image->signature == MagickSignature);
1068 *p++='o'; /* open */
1070 Serialize image attributes (see ValidatePixelCacheMorphology()).
1072 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1073 p+=sizeof(server_info->session_key);
1074 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1075 p+=sizeof(image->storage_class);
1076 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1077 p+=sizeof(image->colorspace);
1078 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1079 p+=sizeof(image->alpha_trait);
1080 (void) memcpy(p,&image->mask,sizeof(image->mask));
1081 p+=sizeof(image->mask);
1082 (void) memcpy(p,&image->columns,sizeof(image->columns));
1083 p+=sizeof(image->columns);
1084 (void) memcpy(p,&image->rows,sizeof(image->rows));
1085 p+=sizeof(image->rows);
1086 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1087 p+=sizeof(image->number_channels);
1088 (void) memcpy(p,image->channel_map,MaxPixelChannels*
1089 sizeof(*image->channel_map));
1090 p+=MaxPixelChannels*sizeof(*image->channel_map);
1091 (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1092 p+=sizeof(image->metacontent_extent);
1093 count=dpc_send(server_info->file,p-message,message);
1094 if (count != (MagickOffsetType) (p-message))
1095 return(MagickFalse);
1097 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1098 if (count != (MagickOffsetType) sizeof(status))
1099 return(MagickFalse);
1104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108 + 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 %
1112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1115 % region of the distributed pixel cache.
1117 % The format of the ReadDistributePixelCacheMetacontents method is:
1119 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1120 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1121 % const MagickSizeType length,unsigned char *metacontent)
1123 % A description of each parameter follows:
1125 % o server_info: the distributed cache info.
1127 % o image: the image.
1129 % o region: read the metacontent from this region of the image.
1131 % o length: the length in bytes of the metacontent.
1133 % o metacontent: read these metacontent from the pixel cache.
1136 MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1137 DistributeCacheInfo *server_info,const RectangleInfo *region,
1138 const MagickSizeType length,unsigned char *metacontent)
1143 register unsigned char
1147 message[MaxTextExtent];
1150 Read distributed pixel cache metacontent.
1152 assert(server_info != (DistributeCacheInfo *) NULL);
1153 assert(server_info->signature == MagickSignature);
1154 assert(region != (RectangleInfo *) NULL);
1155 assert(metacontent != (unsigned char *) NULL);
1156 if (length > (MagickSizeType) SSIZE_MAX)
1160 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1161 p+=sizeof(server_info->session_key);
1162 (void) memcpy(p,®ion->width,sizeof(region->width));
1163 p+=sizeof(region->width);
1164 (void) memcpy(p,®ion->height,sizeof(region->height));
1165 p+=sizeof(region->height);
1166 (void) memcpy(p,®ion->x,sizeof(region->x));
1167 p+=sizeof(region->x);
1168 (void) memcpy(p,®ion->y,sizeof(region->y));
1169 p+=sizeof(region->y);
1170 (void) memcpy(p,&length,sizeof(length));
1172 count=dpc_send(server_info->file,p-message,message);
1173 if (count != (MagickOffsetType) (p-message))
1175 return(dpc_read(server_info->file,length,metacontent));
1179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1183 + 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 %
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1190 % the distributed pixel cache.
1192 % The format of the ReadDistributePixelCachePixels method is:
1194 % MagickOffsetType ReadDistributePixelCachePixels(
1195 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1196 % const MagickSizeType length,unsigned char *pixels)
1198 % A description of each parameter follows:
1200 % o server_info: the distributed cache info.
1202 % o image: the image.
1204 % o region: read the pixels from this region of the image.
1206 % o length: the length in bytes of the pixels.
1208 % o pixels: read these pixels from the pixel cache.
1211 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1212 DistributeCacheInfo *server_info,const RectangleInfo *region,
1213 const MagickSizeType length,unsigned char *pixels)
1218 register unsigned char
1222 message[MaxTextExtent];
1225 Read distributed pixel cache pixels.
1227 assert(server_info != (DistributeCacheInfo *) NULL);
1228 assert(server_info->signature == MagickSignature);
1229 assert(region != (RectangleInfo *) NULL);
1230 assert(pixels != (unsigned char *) NULL);
1231 if (length > (MagickSizeType) SSIZE_MAX)
1235 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1236 p+=sizeof(server_info->session_key);
1237 (void) memcpy(p,®ion->width,sizeof(region->width));
1238 p+=sizeof(region->width);
1239 (void) memcpy(p,®ion->height,sizeof(region->height));
1240 p+=sizeof(region->height);
1241 (void) memcpy(p,®ion->x,sizeof(region->x));
1242 p+=sizeof(region->x);
1243 (void) memcpy(p,®ion->y,sizeof(region->y));
1244 p+=sizeof(region->y);
1245 (void) memcpy(p,&length,sizeof(length));
1247 count=dpc_send(server_info->file,p-message,message);
1248 if (count != (MagickOffsetType) (p-message))
1250 return(dpc_read(server_info->file,length,pixels));
1254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 + 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 %
1262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 % RelinquishDistributePixelCache() frees resources acquired with
1265 % OpenDistributePixelCache().
1267 % The format of the RelinquishDistributePixelCache method is:
1269 % MagickBooleanType RelinquishDistributePixelCache(
1270 % DistributeCacheInfo *server_info)
1272 % A description of each parameter follows:
1274 % o server_info: the distributed cache info.
1277 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1278 DistributeCacheInfo *server_info)
1286 register unsigned char
1290 message[MaxTextExtent];
1293 Delete distributed pixel cache.
1295 assert(server_info != (DistributeCacheInfo *) NULL);
1296 assert(server_info->signature == MagickSignature);
1299 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1300 p+=sizeof(server_info->session_key);
1301 count=dpc_send(server_info->file,p-message,message);
1302 if (count != (MagickOffsetType) (p-message))
1303 return(MagickFalse);
1304 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1305 if (count != (MagickOffsetType) sizeof(status))
1306 return(MagickFalse);
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315 + 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 %
1319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1322 % specified region of the distributed pixel cache.
1324 % The format of the WriteDistributePixelCacheMetacontents method is:
1326 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1327 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1328 % const MagickSizeType length,const unsigned char *metacontent)
1330 % A description of each parameter follows:
1332 % o server_info: the distributed cache info.
1334 % o image: the image.
1336 % o region: write the metacontent to this region of the image.
1338 % o length: the length in bytes of the metacontent.
1340 % o metacontent: write these metacontent to the pixel cache.
1343 MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1344 DistributeCacheInfo *server_info,const RectangleInfo *region,
1345 const MagickSizeType length,const unsigned char *metacontent)
1350 register unsigned char
1354 message[MaxTextExtent];
1357 Write distributed pixel cache metacontent.
1359 assert(server_info != (DistributeCacheInfo *) NULL);
1360 assert(server_info->signature == MagickSignature);
1361 assert(region != (RectangleInfo *) NULL);
1362 assert(metacontent != (unsigned char *) NULL);
1363 if (length > (MagickSizeType) SSIZE_MAX)
1367 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1368 p+=sizeof(server_info->session_key);
1369 (void) memcpy(p,®ion->width,sizeof(region->width));
1370 p+=sizeof(region->width);
1371 (void) memcpy(p,®ion->height,sizeof(region->height));
1372 p+=sizeof(region->height);
1373 (void) memcpy(p,®ion->x,sizeof(region->x));
1374 p+=sizeof(region->x);
1375 (void) memcpy(p,®ion->y,sizeof(region->y));
1376 p+=sizeof(region->y);
1377 (void) memcpy(p,&length,sizeof(length));
1379 count=dpc_send(server_info->file,p-message,message);
1380 if (count != (MagickOffsetType) (p-message))
1382 return(dpc_send(server_info->file,length,metacontent));
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1390 + 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 %
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1396 % WriteDistributePixelCachePixels() writes image pixels to the specified
1397 % region of the distributed pixel cache.
1399 % The format of the WriteDistributePixelCachePixels method is:
1401 % MagickBooleanType WriteDistributePixelCachePixels(
1402 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1403 % const MagickSizeType length,const unsigned char *pixels)
1405 % A description of each parameter follows:
1407 % o server_info: the distributed cache info.
1409 % o image: the image.
1411 % o region: write the pixels to this region of the image.
1413 % o length: the length in bytes of the pixels.
1415 % o pixels: write these pixels to the pixel cache.
1418 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1419 DistributeCacheInfo *server_info,const RectangleInfo *region,
1420 const MagickSizeType length,const unsigned char *pixels)
1425 register unsigned char
1429 message[MaxTextExtent];
1432 Write distributed pixel cache pixels.
1434 assert(server_info != (DistributeCacheInfo *) NULL);
1435 assert(server_info->signature == MagickSignature);
1436 assert(region != (RectangleInfo *) NULL);
1437 assert(pixels != (const unsigned char *) NULL);
1438 if (length > (MagickSizeType) SSIZE_MAX)
1442 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1443 p+=sizeof(server_info->session_key);
1444 (void) memcpy(p,®ion->width,sizeof(region->width));
1445 p+=sizeof(region->width);
1446 (void) memcpy(p,®ion->height,sizeof(region->height));
1447 p+=sizeof(region->height);
1448 (void) memcpy(p,®ion->x,sizeof(region->x));
1449 p+=sizeof(region->x);
1450 (void) memcpy(p,®ion->y,sizeof(region->y));
1451 p+=sizeof(region->y);
1452 (void) memcpy(p,&length,sizeof(length));
1454 count=dpc_send(server_info->file,p-message,message);
1455 if (count != (MagickOffsetType) (p-message))
1457 return(dpc_send(server_info->file,length,pixels));