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/policy.h"
67 #include "MagickCore/random_.h"
68 #include "MagickCore/registry.h"
69 #include "MagickCore/splay-tree.h"
70 #include "MagickCore/string_.h"
71 #include "MagickCore/string-private.h"
72 #if defined(MAGICKCORE_HAVE_SOCKET)
73 #include <netinet/in.h>
75 #include <sys/socket.h>
76 #include <arpa/inet.h>
82 #define DPCHostname "127.0.0.1"
83 #define DPCPendingConnections 10
85 #define DPCSessionKeyLength 8
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92 + 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 %
96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
100 % The format of the AcquireDistributeCacheInfo method is:
102 % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
104 % A description of each parameter follows:
106 % o exception: return any errors or warnings in this structure.
110 static MagickSizeType CRC64(const unsigned char *message,
111 const MagickSizeType length)
116 register MagickOffsetType
119 static MagickBooleanType
120 crc_initial = MagickFalse;
122 static MagickSizeType
126 Generate a 64-bit cyclic redundancy check for the message.
128 if (crc_initial == MagickFalse)
133 for (i=0; i < 256; i++)
135 register MagickOffsetType
138 alpha=(MagickSizeType) i;
139 for (j=0; j < 8; j++)
141 if ((alpha & 0x01) == 0)
144 alpha=(MagickSizeType) ((alpha >> 1) ^
145 MagickULLConstant(0xd800000000000000));
149 crc_initial=MagickTrue;
152 for (i=0; i < (MagickOffsetType) length; i++)
153 crc=crc_xor[(crc ^ message[i]) & 0xff] ^ (crc >> 8);
157 static inline MagickSizeType MagickMin(const MagickSizeType x,
158 const MagickSizeType y)
165 static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
166 unsigned char *restrict message)
171 count=(MagickOffsetType) recv(file,message,(size_t) MagickMin(length,
172 (MagickSizeType) SSIZE_MAX),0);
176 static int ConnectPixelCacheServer(const char *hostname,const int port,
177 MagickSizeType *session_key,ExceptionInfo *exception)
179 #if defined(MAGICKCORE_HAVE_SOCKET)
181 service[MaxTextExtent];
193 register unsigned char
201 secret[MaxTextExtent],
202 session[2*MaxTextExtent];
205 Connect to distributed pixel cache and get session key.
208 shared_secret=GetPolicyValue("shared-secret");
209 if (shared_secret == (const char *) NULL)
211 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
212 "DistributedPixelCache","'%s'","shared secret expected");
216 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
217 p+=strlen(shared_secret);
218 (void) ResetMagickMemory(&hint,0,sizeof(hint));
219 hint.ai_family=AF_INET;
220 hint.ai_socktype=SOCK_STREAM;
221 hint.ai_flags=AI_PASSIVE;
222 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
223 status=getaddrinfo(hostname,service,&hint,&result);
226 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
227 "DistributedPixelCache","'%s'",hostname);
230 client_socket=socket(result->ai_family,result->ai_socktype,
231 result->ai_protocol);
232 if (client_socket == -1)
234 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
235 "DistributedPixelCache","'%s'",hostname);
238 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
241 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
242 "DistributedPixelCache","'%s'",hostname);
245 count=dpc_read(client_socket,MaxTextExtent,secret);
252 (void) memcpy(p,secret,(size_t) count);
254 quantum_depth=MAGICKCORE_QUANTUM_DEPTH;
255 (void) memcpy(p,&quantum_depth,sizeof(quantum_depth));
256 p+=sizeof(quantum_depth);
257 hdri=MAGICKCORE_HDRI_ENABLE;
258 (void) memcpy(p,&hdri,sizeof(hdri));
260 *session_key=CRC64(session,p-session);
262 if (*session_key == 0)
264 close(client_socket);
267 return(client_socket);
269 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
270 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
275 static char *GetHostname(int *port,ExceptionInfo *exception)
292 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
294 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",
296 if (hosts == (char *) NULL)
299 return(AcquireString(DPCHostname));
301 (void) SubstituteString(&hosts,","," ");
302 hostlist=StringToArgv(hosts,&argc);
303 hosts=DestroyString(hosts);
304 if (hostlist == (char **) NULL)
307 return(AcquireString(DPCHostname));
309 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
310 for (i=0; i < (ssize_t) argc; i++)
311 hostlist[i]=DestroyString(hostlist[i]);
312 hostlist=(char **) RelinquishMagickMemory(hostlist);
313 (void) SubstituteString(&hosts,":"," ");
314 hostlist=StringToArgv(hosts,&argc);
315 if (hostlist == (char **) NULL)
318 return(AcquireString(DPCHostname));
320 host=AcquireString(hostlist[1]);
321 if (hostlist[2] == (char *) NULL)
324 *port=StringToLong(hostlist[2]);
325 for (i=0; i < (ssize_t) argc; i++)
326 hostlist[i]=DestroyString(hostlist[i]);
327 hostlist=(char **) RelinquishMagickMemory(hostlist);
331 MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
332 ExceptionInfo *exception)
344 Connect to the distributed pixel cache server.
346 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
347 if (server_info == (DistributeCacheInfo *) NULL)
348 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
349 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
350 server_info->signature=MagickSignature;
352 hostname=GetHostname(&server_info->port,exception);
354 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
355 &session_key,exception);
356 server_info->session_key=session_key;
357 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
358 hostname=DestroyString(hostname);
359 if (server_info->file == -1)
360 server_info=DestroyDistributeCacheInfo(server_info);
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 + 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 %
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 % DestroyDistributeCacheInfo() deallocates memory associated with an
376 % DistributeCacheInfo structure.
378 % The format of the DestroyDistributeCacheInfo method is:
380 % DistributeCacheInfo *DestroyDistributeCacheInfo(
381 % DistributeCacheInfo *server_info)
383 % A description of each parameter follows:
385 % o server_info: the distributed cache info.
388 MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
389 DistributeCacheInfo *server_info)
391 assert(server_info != (DistributeCacheInfo *) NULL);
392 assert(server_info->signature == MagickSignature);
393 if (server_info->file > 0)
394 (void) close(server_info->file);
395 server_info->signature=(~MagickSignature);
396 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 + 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 %
409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 % DistributePixelCacheServer() waits on the specified port for commands to
412 % create, read, update, or destroy a pixel cache.
414 % The format of the DistributePixelCacheServer() method is:
416 % void DistributePixelCacheServer(const int port)
418 % A description of each parameter follows:
420 % o port: connect the distributed pixel cache at this port.
422 % o exception: return any errors or warnings in this structure.
426 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
427 int file,const MagickSizeType session_key)
430 Destroy distributed pixel cache.
432 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
435 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
436 const unsigned char *restrict message)
441 register MagickOffsetType
445 Ensure a complete message is sent.
448 for (i=0; i < (MagickOffsetType) length; i+=count)
450 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
451 (MagickSizeType) SSIZE_MAX),0);
462 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
463 int file,const MagickSizeType session_key,ExceptionInfo *exception)
477 register unsigned char
481 message[MaxTextExtent];
484 Open distributed pixel cache.
486 image=AcquireImage((ImageInfo *) NULL,exception);
487 if (image == (Image *) NULL)
489 length=sizeof(image->columns)+sizeof(image->rows)+
490 sizeof(image->number_channels);
491 count=dpc_read(file,length,message);
492 if (count != (MagickOffsetType) length)
495 (void) memcpy(&image->columns,p,sizeof(image->columns));
496 p+=sizeof(image->columns);
497 (void) memcpy(&image->rows,p,sizeof(image->rows));
498 p+=sizeof(image->rows);
499 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
500 p+=sizeof(image->number_channels);
501 status=AddValueToSplayTree(registry,(const void *) session_key,image);
505 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
506 int file,const MagickSizeType session_key,ExceptionInfo *exception)
523 register const Quantum
526 register unsigned char
530 message[MaxTextExtent];
533 Read distributed pixel cache metacontent.
535 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
536 if (image == (Image *) NULL)
538 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
539 sizeof(region.y)+sizeof(length);
540 count=dpc_read(file,length,message);
541 if (count != (MagickOffsetType) length)
544 (void) memcpy(®ion.width,q,sizeof(region.width));
545 q+=sizeof(region.width);
546 (void) memcpy(®ion.height,q,sizeof(region.height));
547 q+=sizeof(region.width);
548 (void) memcpy(®ion.x,q,sizeof(region.x));
549 q+=sizeof(region.width);
550 (void) memcpy(®ion.y,q,sizeof(region.y));
551 q+=sizeof(region.width);
552 (void) memcpy(&length,q,sizeof(length));
554 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
556 if (p == (const Quantum *) NULL)
558 metacontent=GetVirtualMetacontent(image);
559 count=dpc_send(file,length,metacontent);
560 if (count != (MagickOffsetType) length)
565 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
566 int file,const MagickSizeType session_key,ExceptionInfo *exception)
580 register const Quantum
583 register unsigned char
587 message[MaxTextExtent];
590 Read distributed pixel cache pixels.
592 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
593 if (image == (Image *) NULL)
595 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
596 sizeof(region.y)+sizeof(length);
597 count=dpc_read(file,length,message);
598 if (count != (MagickOffsetType) length)
601 (void) memcpy(®ion.width,q,sizeof(region.width));
602 q+=sizeof(region.width);
603 (void) memcpy(®ion.height,q,sizeof(region.height));
604 q+=sizeof(region.width);
605 (void) memcpy(®ion.x,q,sizeof(region.x));
606 q+=sizeof(region.width);
607 (void) memcpy(®ion.y,q,sizeof(region.y));
608 q+=sizeof(region.width);
609 (void) memcpy(&length,q,sizeof(length));
611 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
613 if (p == (const Quantum *) NULL)
615 count=dpc_send(file,length,(unsigned char *) p);
616 if (count != (MagickOffsetType) length)
621 static void *RelinquishImageRegistry(void *image)
623 return((void *) DestroyImageList((Image *) image));
626 static MagickBooleanType WriteDistributeCacheMetacontent(
627 SplayTreeInfo *registry,int file,const MagickSizeType session_key,
628 ExceptionInfo *exception)
648 register unsigned char
652 message[MaxTextExtent],
656 Write distributed pixel cache metacontent.
658 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
659 if (image == (Image *) NULL)
661 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
662 sizeof(region.y)+sizeof(length);
663 count=dpc_read(file,length,message);
664 if (count != (MagickOffsetType) length)
667 (void) memcpy(®ion.width,p,sizeof(region.width));
668 p+=sizeof(region.width);
669 (void) memcpy(®ion.height,p,sizeof(region.height));
670 p+=sizeof(region.width);
671 (void) memcpy(®ion.x,p,sizeof(region.x));
672 p+=sizeof(region.width);
673 (void) memcpy(®ion.y,p,sizeof(region.y));
674 p+=sizeof(region.width);
675 (void) memcpy(&length,p,sizeof(length));
677 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
679 if (q == (Quantum *) NULL)
681 metacontent=GetAuthenticMetacontent(image);
682 count=dpc_read(file,length,metacontent);
683 if (count != (MagickOffsetType) length)
685 status=SyncAuthenticPixels(image,exception);
689 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
690 int file,const MagickSizeType session_key,ExceptionInfo *exception)
710 register unsigned char
714 message[MaxTextExtent];
717 Write distributed pixel cache pixels.
719 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
720 if (image == (Image *) NULL)
722 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
723 sizeof(region.y)+sizeof(length);
724 count=dpc_read(file,length,message);
725 if (count != (MagickOffsetType) length)
728 (void) memcpy(®ion.width,p,sizeof(region.width));
729 p+=sizeof(region.width);
730 (void) memcpy(®ion.height,p,sizeof(region.height));
731 p+=sizeof(region.width);
732 (void) memcpy(®ion.x,p,sizeof(region.x));
733 p+=sizeof(region.width);
734 (void) memcpy(®ion.y,p,sizeof(region.y));
735 p+=sizeof(region.width);
736 (void) memcpy(&length,p,sizeof(length));
738 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
740 if (q == (Quantum *) NULL)
742 count=dpc_read(file,length,(unsigned char *) q);
743 if (count != (MagickOffsetType) length)
745 status=SyncAuthenticPixels(image,exception);
749 static void *DistributePixelCacheClient(void *socket)
772 register unsigned char
786 session[2*MaxTextExtent];
789 Distributed pixel cache client.
791 shared_secret=GetPolicyValue("shared-secret");
792 if (shared_secret == (const char *) NULL)
793 ThrowFatalException(CacheFatalError,"shared secret expected");
795 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
796 p+=strlen(shared_secret);
797 random_info=AcquireRandomInfo();
798 secret=GetRandomKey(random_info,DPCSessionKeyLength);
799 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
800 p+=DPCSessionKeyLength;
801 quantum_depth=MAGICKCORE_QUANTUM_DEPTH;
802 (void) memcpy(p,&quantum_depth,sizeof(quantum_depth));
803 p+=sizeof(quantum_depth);
804 hdri=MAGICKCORE_HDRI_ENABLE;
805 (void) memcpy(p,&hdri,sizeof(hdri));
807 session_key=CRC64(session,p-session);
808 random_info=DestroyRandomInfo(random_info);
809 exception=AcquireExceptionInfo();
810 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
811 (void *(*)(void *)) NULL,RelinquishImageRegistry);
812 client_socket=(*(int *) socket);
813 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
814 secret=DestroyStringInfo(secret);
817 count=dpc_read(client_socket,1,(unsigned char *) &command);
820 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
821 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
828 status=OpenDistributeCache(registry,client_socket,session_key,
834 status=ReadDistributeCachePixels(registry,client_socket,session_key,
840 status=ReadDistributeCacheMetacontent(registry,client_socket,
841 session_key,exception);
846 status=WriteDistributeCachePixels(registry,client_socket,session_key,
852 status=WriteDistributeCacheMetacontent(registry,client_socket,
853 session_key,exception);
858 status=DestroyDistributeCache(registry,client_socket,session_key);
864 if (status == MagickFalse)
869 (void) close(client_socket);
870 exception=DestroyExceptionInfo(exception);
871 registry=DestroySplayTree(registry);
872 return((void *) NULL);
875 MagickExport void DistributePixelCacheServer(const int port,
876 ExceptionInfo *exception)
878 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
880 service[MaxTextExtent];
892 register struct addrinfo
903 Launch distributed pixel cache server.
905 (void) ResetMagickMemory(&hint,0,sizeof(hint));
906 hint.ai_family=AF_INET;
907 hint.ai_socktype=SOCK_STREAM;
908 hint.ai_flags=AI_PASSIVE;
909 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
910 status=getaddrinfo((const char *) NULL,service,&hint,&result);
912 ThrowFatalException(CacheFatalError,"UnableToListen");
913 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
918 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
919 if (server_socket == -1)
922 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
926 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
929 (void) close(status);
934 if (p == (struct addrinfo *) NULL)
935 ThrowFatalException(CacheFatalError,"UnableToBind");
936 freeaddrinfo(result);
937 status=listen(server_socket,DPCPendingConnections);
939 ThrowFatalException(CacheFatalError,"UnableToListen");
940 pthread_attr_init(&attributes);
949 length=(socklen_t) sizeof(address);
950 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
951 if (client_socket == -1)
952 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
953 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
954 (void *) &client_socket);
956 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
958 (void) close(server_socket);
960 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 + G e t D i s t r i b u t e C a c h e F i l e %
973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 % GetDistributeCacheFile() returns the file associated with this
976 % DistributeCacheInfo structure.
978 % The format of the GetDistributeCacheFile method is:
980 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
982 % A description of each parameter follows:
984 % o server_info: the distributed cache info.
987 MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
989 assert(server_info != (DistributeCacheInfo *) NULL);
990 assert(server_info->signature == MagickSignature);
991 return(server_info->file);
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999 + 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 %
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 % GetDistributeCacheHostname() returns the hostname associated with this
1006 % DistributeCacheInfo structure.
1008 % The format of the GetDistributeCacheHostname method is:
1010 % const char *GetDistributeCacheHostname(
1011 % const DistributeCacheInfo *server_info)
1013 % A description of each parameter follows:
1015 % o server_info: the distributed cache info.
1018 MagickPrivate const char *GetDistributeCacheHostname(
1019 const DistributeCacheInfo *server_info)
1021 assert(server_info != (DistributeCacheInfo *) NULL);
1022 assert(server_info->signature == MagickSignature);
1023 return(server_info->hostname);
1027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031 + G e t D i s t r i b u t e C a c h e P o r t %
1035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 % GetDistributeCachePort() returns the port associated with this
1038 % DistributeCacheInfo structure.
1040 % The format of the GetDistributeCachePort method is:
1042 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1044 % A description of each parameter follows:
1046 % o server_info: the distributed cache info.
1049 MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1051 assert(server_info != (DistributeCacheInfo *) NULL);
1052 assert(server_info->signature == MagickSignature);
1053 return(server_info->port);
1057 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 + O p e n D i s t r i b u t e P i x e l C a c h e %
1065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1069 % The format of the OpenDistributePixelCache method is:
1071 % MagickBooleanType *OpenDistributePixelCache(
1072 % DistributeCacheInfo *server_info,Image *image)
1074 % A description of each parameter follows:
1076 % o server_info: the distributed cache info.
1078 % o image: the image.
1081 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1082 DistributeCacheInfo *server_info,Image *image)
1087 register unsigned char
1091 message[MaxTextExtent];
1094 Open distributed pixel cache.
1096 assert(server_info != (DistributeCacheInfo *) NULL);
1097 assert(server_info->signature == MagickSignature);
1098 assert(image != (Image *) NULL);
1099 assert(image->signature == MagickSignature);
1101 *p++='o'; /* open */
1102 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1103 p+=sizeof(server_info->session_key);
1104 (void) memcpy(p,&image->columns,sizeof(image->columns));
1105 p+=sizeof(image->columns);
1106 (void) memcpy(p,&image->rows,sizeof(image->rows));
1107 p+=sizeof(image->rows);
1108 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1109 p+=sizeof(image->number_channels);
1110 count=dpc_send(server_info->file,p-message,message);
1111 if (count != (MagickOffsetType) (p-message))
1112 return(MagickFalse);
1117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1121 + 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 %
1125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1127 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1128 % region of the distributed pixel cache.
1130 % The format of the ReadDistributePixelCacheMetacontents method is:
1132 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1133 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1134 % const MagickSizeType length,unsigned char *metacontent)
1136 % A description of each parameter follows:
1138 % o server_info: the distributed cache info.
1140 % o image: the image.
1142 % o region: read the metacontent from this region of the image.
1144 % o length: the length in bytes of the metacontent.
1146 % o metacontent: read these metacontent from the pixel cache.
1149 MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1150 DistributeCacheInfo *server_info,const RectangleInfo *region,
1151 const MagickSizeType length,unsigned char *metacontent)
1156 register unsigned char
1160 message[MaxTextExtent];
1163 Read distributed pixel cache metacontent.
1165 assert(server_info != (DistributeCacheInfo *) NULL);
1166 assert(server_info->signature == MagickSignature);
1167 assert(region != (RectangleInfo *) NULL);
1168 assert(metacontent != (unsigned char *) NULL);
1169 if (length != (size_t) length)
1173 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1174 p+=sizeof(server_info->session_key);
1175 (void) memcpy(p,®ion->width,sizeof(region->width));
1176 p+=sizeof(region->width);
1177 (void) memcpy(p,®ion->height,sizeof(region->height));
1178 p+=sizeof(region->height);
1179 (void) memcpy(p,®ion->x,sizeof(region->x));
1180 p+=sizeof(region->x);
1181 (void) memcpy(p,®ion->y,sizeof(region->y));
1182 p+=sizeof(region->y);
1183 (void) memcpy(p,&length,sizeof(length));
1185 count=dpc_send(server_info->file,p-message,message);
1186 if (count != (MagickOffsetType) (p-message))
1188 return(dpc_read(server_info->file,length,metacontent));
1192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 + 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 %
1200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1203 % the distributed pixel cache.
1205 % The format of the ReadDistributePixelCachePixels method is:
1207 % MagickOffsetType ReadDistributePixelCachePixels(
1208 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1209 % const MagickSizeType length,unsigned char *pixels)
1211 % A description of each parameter follows:
1213 % o server_info: the distributed cache info.
1215 % o image: the image.
1217 % o region: read the pixels from this region of the image.
1219 % o length: the length in bytes of the pixels.
1221 % o pixels: read these pixels from the pixel cache.
1224 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1225 DistributeCacheInfo *server_info,const RectangleInfo *region,
1226 const MagickSizeType length,unsigned char *pixels)
1231 register unsigned char
1235 message[MaxTextExtent];
1238 Read distributed pixel cache pixels.
1240 assert(server_info != (DistributeCacheInfo *) NULL);
1241 assert(server_info->signature == MagickSignature);
1242 assert(region != (RectangleInfo *) NULL);
1243 assert(pixels != (unsigned char *) NULL);
1244 if (length != (size_t) length)
1248 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1249 p+=sizeof(server_info->session_key);
1250 (void) memcpy(p,®ion->width,sizeof(region->width));
1251 p+=sizeof(region->width);
1252 (void) memcpy(p,®ion->height,sizeof(region->height));
1253 p+=sizeof(region->height);
1254 (void) memcpy(p,®ion->x,sizeof(region->x));
1255 p+=sizeof(region->x);
1256 (void) memcpy(p,®ion->y,sizeof(region->y));
1257 p+=sizeof(region->y);
1258 (void) memcpy(p,&length,sizeof(length));
1260 count=dpc_send(server_info->file,p-message,message);
1261 if (count != (MagickOffsetType) (p-message))
1263 return(dpc_read(server_info->file,length,pixels));
1267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1271 + 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 %
1275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1277 % RelinquishDistributePixelCache() frees resources acquired with
1278 % OpenDistributePixelCache().
1280 % The format of the RelinquishDistributePixelCache method is:
1282 % MagickBooleanType RelinquishDistributePixelCache(
1283 % DistributeCacheInfo *server_info)
1285 % A description of each parameter follows:
1287 % o server_info: the distributed cache info.
1290 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1291 DistributeCacheInfo *server_info)
1296 register unsigned char
1300 message[MaxTextExtent];
1303 Delete distributed pixel cache.
1305 assert(server_info != (DistributeCacheInfo *) NULL);
1306 assert(server_info->signature == MagickSignature);
1309 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1310 p+=sizeof(server_info->session_key);
1311 count=dpc_send(server_info->file,p-message,message);
1312 if (count != (MagickOffsetType) (p-message))
1313 return(MagickFalse);
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1322 + 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 %
1326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1329 % specified region of the distributed pixel cache.
1331 % The format of the WriteDistributePixelCacheMetacontents method is:
1333 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1334 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1335 % const MagickSizeType length,const unsigned char *metacontent)
1337 % A description of each parameter follows:
1339 % o server_info: the distributed cache info.
1341 % o image: the image.
1343 % o region: write the metacontent to this region of the image.
1345 % o length: the length in bytes of the metacontent.
1347 % o metacontent: write these metacontent to the pixel cache.
1350 MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1351 DistributeCacheInfo *server_info,const RectangleInfo *region,
1352 const MagickSizeType length,const unsigned char *metacontent)
1357 register unsigned char
1361 message[MaxTextExtent];
1364 Write distributed pixel cache metacontent.
1366 assert(server_info != (DistributeCacheInfo *) NULL);
1367 assert(server_info->signature == MagickSignature);
1368 assert(region != (RectangleInfo *) NULL);
1369 assert(metacontent != (unsigned char *) NULL);
1370 if (length != (size_t) length)
1374 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1375 p+=sizeof(server_info->session_key);
1376 (void) memcpy(p,®ion->width,sizeof(region->width));
1377 p+=sizeof(region->width);
1378 (void) memcpy(p,®ion->height,sizeof(region->height));
1379 p+=sizeof(region->height);
1380 (void) memcpy(p,®ion->x,sizeof(region->x));
1381 p+=sizeof(region->x);
1382 (void) memcpy(p,®ion->y,sizeof(region->y));
1383 p+=sizeof(region->y);
1384 (void) memcpy(p,&length,sizeof(length));
1386 count=dpc_send(server_info->file,p-message,message);
1387 if (count != (MagickOffsetType) (p-message))
1389 return(dpc_send(server_info->file,length,metacontent));
1393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1397 + 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 %
1401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403 % WriteDistributePixelCachePixels() writes image pixels to the specified
1404 % region of the distributed pixel cache.
1406 % The format of the WriteDistributePixelCachePixels method is:
1408 % MagickBooleanType WriteDistributePixelCachePixels(
1409 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1410 % const MagickSizeType length,const unsigned char *pixels)
1412 % A description of each parameter follows:
1414 % o server_info: the distributed cache info.
1416 % o image: the image.
1418 % o region: write the pixels to this region of the image.
1420 % o length: the length in bytes of the pixels.
1422 % o pixels: write these pixels to the pixel cache.
1425 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1426 DistributeCacheInfo *server_info,const RectangleInfo *region,
1427 const MagickSizeType length,const unsigned char *pixels)
1432 register unsigned char
1436 message[MaxTextExtent];
1439 Write distributed pixel cache pixels.
1441 assert(server_info != (DistributeCacheInfo *) NULL);
1442 assert(server_info->signature == MagickSignature);
1443 assert(region != (RectangleInfo *) NULL);
1444 assert(pixels != (const unsigned char *) NULL);
1445 if (length != (size_t) length)
1449 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1450 p+=sizeof(server_info->session_key);
1451 (void) memcpy(p,®ion->width,sizeof(region->width));
1452 p+=sizeof(region->width);
1453 (void) memcpy(p,®ion->height,sizeof(region->height));
1454 p+=sizeof(region->height);
1455 (void) memcpy(p,®ion->x,sizeof(region->x));
1456 p+=sizeof(region->x);
1457 (void) memcpy(p,®ion->y,sizeof(region->y));
1458 p+=sizeof(region->y);
1459 (void) memcpy(p,&length,sizeof(length));
1461 count=dpc_send(server_info->file,p-message,message);
1462 if (count != (MagickOffsetType) (p-message))
1464 return(dpc_send(server_info->file,length,pixels));