MagickCore  7.1.0
Convert, Edit, Or Compose Bitmap Images
distribute-cache.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
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 %
10 % %
11 % CCCC AAA CCCC H H EEEEE %
12 % C A A C H H E %
13 % C AAAAA C HHHHH EEE %
14 % C A A C H H E %
15 % CCCC A A CCCC H H EEEEE %
16 % %
17 % %
18 % MagickCore Distributed Pixel Cache Methods %
19 % %
20 % Software Design %
21 % Cristy %
22 % January 2013 %
23 % %
24 % %
25 % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
27 % %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
30 % %
31 % https://imagemagick.org/script/license.php %
32 % %
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. %
38 % %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 %
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.
48 %
49 */
50 
51 /*
52  Include declarations.
53 */
54 #include "MagickCore/studio.h"
55 #include "MagickCore/cache.h"
59 #include "MagickCore/exception.h"
61 #include "MagickCore/geometry.h"
62 #include "MagickCore/image.h"
64 #include "MagickCore/list.h"
65 #include "MagickCore/locale_.h"
66 #include "MagickCore/memory_.h"
68 #include "MagickCore/pixel.h"
69 #include "MagickCore/policy.h"
70 #include "MagickCore/random_.h"
71 #include "MagickCore/registry.h"
72 #include "MagickCore/splay-tree.h"
73 #include "MagickCore/string_.h"
75 #include "MagickCore/version.h"
77 #undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE
78 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
79 #include <netinet/in.h>
80 #include <netdb.h>
81 #include <sys/socket.h>
82 #include <arpa/inet.h>
83 #define CHAR_TYPE_CAST
84 #define CLOSE_SOCKET(socket) (void) close(socket)
85 #define HANDLER_RETURN_TYPE void *
86 #define HANDLER_RETURN_VALUE (void *) NULL
87 #define SOCKET_TYPE int
88 #define LENGTH_TYPE size_t
89 #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1
90 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
91 #define CHAR_TYPE_CAST (char *)
92 #define CLOSE_SOCKET(socket) (void) closesocket(socket)
93 #define HANDLER_RETURN_TYPE DWORD WINAPI
94 #define HANDLER_RETURN_VALUE 0
95 #define SOCKET_TYPE SOCKET
96 #define LENGTH_TYPE int
97 #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1
98 #else
99 #ifdef __VMS
100 #define CLOSE_SOCKET(socket) (void) close(socket)
101 #else
102 #define CLOSE_SOCKET(socket)
103 #endif
104 #define HANDLER_RETURN_TYPE void *
105 #define HANDLER_RETURN_VALUE (void *) NULL
106 #define SOCKET_TYPE int
107 #undef send
108 #undef recv
109 #define send(file,buffer,length,flags) 0
110 #define recv(file,buffer,length,flags) 0
111 #endif
112 
113 /*
114  Define declarations.
115 */
116 #define DPCHostname "127.0.0.1"
117 #define DPCPendingConnections 10
118 #define DPCPort 6668
119 #define DPCSessionKeyLength 8
120 #ifndef MSG_NOSIGNAL
121 # define MSG_NOSIGNAL 0
122 #endif
123 
124 /*
125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126 % %
127 % %
128 % %
129 + 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 %
130 % %
131 % %
132 % %
133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134 %
135 % AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
136 %
137 % The format of the AcquireDistributeCacheInfo method is:
138 %
139 % DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
140 %
141 % A description of each parameter follows:
142 %
143 % o exception: return any errors or warnings in this structure.
144 %
145 */
146 
147 static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
148  unsigned char *magick_restrict message)
149 {
151  i;
152 
153  ssize_t
154  count;
155 
156 #if !MAGICKCORE_HAVE_DISTRIBUTE_CACHE
157  magick_unreferenced(file);
158  magick_unreferenced(message);
159 #endif
160  count=0;
161  for (i=0; i < (MagickOffsetType) length; i+=count)
162  {
163  count=recv(file,CHAR_TYPE_CAST message+i,(LENGTH_TYPE) MagickMin(length-i,
165  if (count <= 0)
166  {
167  count=0;
168  if (errno != EINTR)
169  break;
170  }
171  }
172  return(i);
173 }
174 
175 static int ConnectPixelCacheServer(const char *hostname,const int port,
176  size_t *session_key,ExceptionInfo *exception)
177 {
178 #if MAGICKCORE_HAVE_DISTRIBUTE_CACHE
179  char
180  service[MagickPathExtent],
181  *shared_secret;
182 
183  int
184  status;
185 
187  client_socket;
188 
189  ssize_t
190  count;
191 
192  struct addrinfo
193  hint,
194  *result;
195 
196  unsigned char
197  secret[MagickPathExtent];
198 
199  /*
200  Connect to distributed pixel cache and get session key.
201  */
202  *session_key=0;
203  shared_secret=GetPolicyValue("cache:shared-secret");
204  if (shared_secret == (char *) NULL)
205  {
207  "DistributedPixelCache","'%s'","shared secret expected");
208  return(-1);
209  }
210  shared_secret=DestroyString(shared_secret);
211 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
212  NTInitializeWinsock(MagickTrue);
213 #endif
214  (void) memset(&hint,0,sizeof(hint));
215  hint.ai_family=AF_INET;
216  hint.ai_socktype=SOCK_STREAM;
217  hint.ai_flags=AI_PASSIVE;
218  (void) FormatLocaleString(service,MagickPathExtent,"%d",port);
219  status=getaddrinfo(hostname,service,&hint,&result);
220  if (status != 0)
221  {
223  "DistributedPixelCache","'%s'",hostname);
224  return(-1);
225  }
226  client_socket=socket(result->ai_family,result->ai_socktype,
227  result->ai_protocol);
228  if (client_socket == -1)
229  {
230  freeaddrinfo(result);
232  "DistributedPixelCache","'%s'",hostname);
233  return(-1);
234  }
235  status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen);
236  if (status == -1)
237  {
238  CLOSE_SOCKET(client_socket);
239  freeaddrinfo(result);
241  "DistributedPixelCache","'%s'",hostname);
242  return(-1);
243  }
244  count=recv(client_socket,CHAR_TYPE_CAST secret,MagickPathExtent,0);
245  if (count != -1)
246  {
247  StringInfo
248  *nonce;
249 
250  nonce=AcquireStringInfo((size_t) count);
251  (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
252  *session_key=GetMagickSignature(nonce);
253  nonce=DestroyStringInfo(nonce);
254  }
255  if (*session_key == 0)
256  {
257  CLOSE_SOCKET(client_socket);
258  client_socket=(SOCKET_TYPE) (-1);
259  }
260  freeaddrinfo(result);
261  return(client_socket);
262 #else
264  "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
265  return(MagickFalse);
266 #endif
267 }
268 
269 static char *GetHostname(int *port,ExceptionInfo *exception)
270 {
271  char
272  *host,
273  *hosts,
274  **hostlist;
275 
276  int
277  argc;
278 
279  ssize_t
280  i;
281 
282  static size_t
283  id = 0;
284 
285  /*
286  Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
287  */
288  hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",exception);
289  if (hosts == (char *) NULL)
290  {
291  *port=DPCPort;
292  return(AcquireString(DPCHostname));
293  }
294  (void) SubstituteString(&hosts,","," ");
295  hostlist=StringToArgv(hosts,&argc);
296  hosts=DestroyString(hosts);
297  if (hostlist == (char **) NULL)
298  {
299  *port=DPCPort;
300  return(AcquireString(DPCHostname));
301  }
302  hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
303  for (i=0; i < (ssize_t) argc; i++)
304  hostlist[i]=DestroyString(hostlist[i]);
305  hostlist=(char **) RelinquishMagickMemory(hostlist);
306  (void) SubstituteString(&hosts,":"," ");
307  hostlist=StringToArgv(hosts,&argc);
308  if (hostlist == (char **) NULL)
309  {
310  *port=DPCPort;
311  return(AcquireString(DPCHostname));
312  }
313  host=AcquireString(hostlist[1]);
314  if (hostlist[2] == (char *) NULL)
315  *port=DPCPort;
316  else
317  *port=StringToLong(hostlist[2]);
318  for (i=0; i < (ssize_t) argc; i++)
319  hostlist[i]=DestroyString(hostlist[i]);
320  hostlist=(char **) RelinquishMagickMemory(hostlist);
321  return(host);
322 }
323 
325  ExceptionInfo *exception)
326 {
327  char
328  *hostname;
329 
331  *server_info;
332 
333  size_t
334  session_key;
335 
336  /*
337  Connect to the distributed pixel cache server.
338  */
340  sizeof(*server_info));
341  (void) memset(server_info,0,sizeof(*server_info));
342  server_info->signature=MagickCoreSignature;
343  server_info->port=0;
344  hostname=GetHostname(&server_info->port,exception);
345  session_key=0;
346  server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
347  &session_key,exception);
348  if (server_info->file == -1)
349  server_info=DestroyDistributeCacheInfo(server_info);
350  else
351  {
352  server_info->session_key=session_key;
353  (void) CopyMagickString(server_info->hostname,hostname,MagickPathExtent);
354  server_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
355  MagickFalse;
356  }
357  hostname=DestroyString(hostname);
358  return(server_info);
359 }
360 
361 /*
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 % %
364 % %
365 % %
366 + 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 %
367 % %
368 % %
369 % %
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 %
372 % DestroyDistributeCacheInfo() deallocates memory associated with an
373 % DistributeCacheInfo structure.
374 %
375 % The format of the DestroyDistributeCacheInfo method is:
376 %
377 % DistributeCacheInfo *DestroyDistributeCacheInfo(
378 % DistributeCacheInfo *server_info)
379 %
380 % A description of each parameter follows:
381 %
382 % o server_info: the distributed cache info.
383 %
384 */
386  DistributeCacheInfo *server_info)
387 {
388  assert(server_info != (DistributeCacheInfo *) NULL);
389  assert(server_info->signature == MagickCoreSignature);
390  if (server_info->file > 0)
391  CLOSE_SOCKET(server_info->file);
392  server_info->signature=(~MagickCoreSignature);
393  server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
394  return(server_info);
395 }
396 
397 /*
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % %
400 % %
401 % %
402 + 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 %
403 % %
404 % %
405 % %
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 %
408 % DistributePixelCacheServer() waits on the specified port for commands to
409 % create, read, update, or destroy a pixel cache.
410 %
411 % The format of the DistributePixelCacheServer() method is:
412 %
413 % void DistributePixelCacheServer(const int port)
414 %
415 % A description of each parameter follows:
416 %
417 % o port: connect the distributed pixel cache at this port.
418 %
419 % o exception: return any errors or warnings in this structure.
420 %
421 */
422 
423 static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
424  const unsigned char *magick_restrict message)
425 {
427  count,
428  i;
429 
430 #if !MAGICKCORE_HAVE_DISTRIBUTE_CACHE
431  magick_unreferenced(file);
432  magick_unreferenced(message);
433 #endif
434 
435  /*
436  Ensure a complete message is sent.
437  */
438  count=0;
439  for (i=0; i < (MagickOffsetType) length; i+=count)
440  {
441  count=(MagickOffsetType) send(file,CHAR_TYPE_CAST message+i,(LENGTH_TYPE)
443  if (count <= 0)
444  {
445  count=0;
446  if (errno != EINTR)
447  break;
448  }
449  }
450  return(i);
451 }
452 
453 #if !MAGICKCORE_HAVE_DISTRIBUTE_CACHE
455  ExceptionInfo *Exception)
456 {
457  magick_unreferenced(port);
458  ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn");
459 }
460 #else
461 static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
462  const size_t session_key)
463 {
464  /*
465  Destroy distributed pixel cache.
466  */
467  return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
468 }
469 
470 static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file,
471  const size_t session_key,ExceptionInfo *exception)
472 {
473  Image
474  *image;
475 
477  status;
478 
480  count;
481 
483  length;
484 
485  unsigned char
486  message[MagickPathExtent],
487  *p;
488 
489  /*
490  Open distributed pixel cache.
491  */
492  image=AcquireImage((ImageInfo *) NULL,exception);
493  if (image == (Image *) NULL)
494  return(MagickFalse);
495  length=sizeof(image->storage_class)+sizeof(image->colorspace)+
496  sizeof(image->alpha_trait)+sizeof(image->channels)+sizeof(image->columns)+
497  sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels*
498  sizeof(*image->channel_map)+sizeof(image->metacontent_extent);
499  count=dpc_read(file,length,message);
500  if (count != (MagickOffsetType) length)
501  return(MagickFalse);
502  /*
503  Deserialize the image attributes.
504  */
505  p=message;
506  (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
507  p+=sizeof(image->storage_class);
508  (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
509  p+=sizeof(image->colorspace);
510  (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
511  p+=sizeof(image->alpha_trait);
512  (void) memcpy(&image->channels,p,sizeof(image->channels));
513  p+=sizeof(image->channels);
514  (void) memcpy(&image->columns,p,sizeof(image->columns));
515  p+=sizeof(image->columns);
516  (void) memcpy(&image->rows,p,sizeof(image->rows));
517  p+=sizeof(image->rows);
518  (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
519  p+=sizeof(image->number_channels);
520  (void) memcpy(image->channel_map,p,MaxPixelChannels*
521  sizeof(*image->channel_map));
522  p+=MaxPixelChannels*sizeof(*image->channel_map);
523  (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
524  p+=sizeof(image->metacontent_extent);
525  if (SyncImagePixelCache(image,exception) == MagickFalse)
526  return(MagickFalse);
527  status=AddValueToSplayTree(registry,(const void *) session_key,image);
528  return(status);
529 }
530 
531 static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
532  int file,const size_t session_key,ExceptionInfo *exception)
533 {
534  const Quantum
535  *p;
536 
537  const unsigned char
538  *metacontent;
539 
540  Image
541  *image;
542 
544  count;
545 
547  length;
548 
550  region;
551 
552  unsigned char
553  message[MagickPathExtent],
554  *q;
555 
556  /*
557  Read distributed pixel cache metacontent.
558  */
559  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
560  if (image == (Image *) NULL)
561  return(MagickFalse);
562  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
563  sizeof(region.y)+sizeof(length);
564  count=dpc_read(file,length,message);
565  if (count != (MagickOffsetType) length)
566  return(MagickFalse);
567  q=message;
568  (void) memcpy(&region.width,q,sizeof(region.width));
569  q+=sizeof(region.width);
570  (void) memcpy(&region.height,q,sizeof(region.height));
571  q+=sizeof(region.height);
572  (void) memcpy(&region.x,q,sizeof(region.x));
573  q+=sizeof(region.x);
574  (void) memcpy(&region.y,q,sizeof(region.y));
575  q+=sizeof(region.y);
576  (void) memcpy(&length,q,sizeof(length));
577  q+=sizeof(length);
578  p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
579  exception);
580  if (p == (const Quantum *) NULL)
581  return(MagickFalse);
582  metacontent=(const unsigned char *) GetVirtualMetacontent(image);
583  count=dpc_send(file,length,metacontent);
584  if (count != (MagickOffsetType) length)
585  return(MagickFalse);
586  return(MagickTrue);
587 }
588 
589 static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
590  int file,const size_t session_key,ExceptionInfo *exception)
591 {
592  const Quantum
593  *p;
594 
595  Image
596  *image;
597 
599  count;
600 
602  length;
603 
605  region;
606 
607  unsigned char
608  message[MagickPathExtent],
609  *q;
610 
611  /*
612  Read distributed pixel cache pixels.
613  */
614  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
615  if (image == (Image *) NULL)
616  return(MagickFalse);
617  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
618  sizeof(region.y)+sizeof(length);
619  count=dpc_read(file,length,message);
620  if (count != (MagickOffsetType) length)
621  return(MagickFalse);
622  q=message;
623  (void) memcpy(&region.width,q,sizeof(region.width));
624  q+=sizeof(region.width);
625  (void) memcpy(&region.height,q,sizeof(region.height));
626  q+=sizeof(region.height);
627  (void) memcpy(&region.x,q,sizeof(region.x));
628  q+=sizeof(region.x);
629  (void) memcpy(&region.y,q,sizeof(region.y));
630  q+=sizeof(region.y);
631  (void) memcpy(&length,q,sizeof(length));
632  q+=sizeof(length);
633  p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
634  exception);
635  if (p == (const Quantum *) NULL)
636  return(MagickFalse);
637  count=dpc_send(file,length,(unsigned char *) p);
638  if (count != (MagickOffsetType) length)
639  return(MagickFalse);
640  return(MagickTrue);
641 }
642 
643 static void *RelinquishImageRegistry(void *image)
644 {
645  return((void *) DestroyImageList((Image *) image));
646 }
647 
648 static MagickBooleanType WriteDistributeCacheMetacontent(
649  SplayTreeInfo *registry,int file,const size_t session_key,
650  ExceptionInfo *exception)
651 {
652  Image
653  *image;
654 
656  count;
657 
659  length;
660 
661  Quantum
662  *q;
663 
665  region;
666 
667  unsigned char
668  message[MagickPathExtent],
669  *metacontent,
670  *p;
671 
672  /*
673  Write distributed pixel cache metacontent.
674  */
675  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
676  if (image == (Image *) NULL)
677  return(MagickFalse);
678  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
679  sizeof(region.y)+sizeof(length);
680  count=dpc_read(file,length,message);
681  if (count != (MagickOffsetType) length)
682  return(MagickFalse);
683  p=message;
684  (void) memcpy(&region.width,p,sizeof(region.width));
685  p+=sizeof(region.width);
686  (void) memcpy(&region.height,p,sizeof(region.height));
687  p+=sizeof(region.height);
688  (void) memcpy(&region.x,p,sizeof(region.x));
689  p+=sizeof(region.x);
690  (void) memcpy(&region.y,p,sizeof(region.y));
691  p+=sizeof(region.y);
692  (void) memcpy(&length,p,sizeof(length));
693  p+=sizeof(length);
694  q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
695  exception);
696  if (q == (Quantum *) NULL)
697  return(MagickFalse);
698  metacontent=(unsigned char *) GetAuthenticMetacontent(image);
699  count=dpc_read(file,length,metacontent);
700  if (count != (MagickOffsetType) length)
701  return(MagickFalse);
702  return(SyncAuthenticPixels(image,exception));
703 }
704 
705 static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
706  int file,const size_t session_key,ExceptionInfo *exception)
707 {
708  Image
709  *image;
710 
712  count;
713 
715  length;
716 
717  Quantum
718  *q;
719 
721  region;
722 
723  unsigned char
724  message[MagickPathExtent],
725  *p;
726 
727  /*
728  Write distributed pixel cache pixels.
729  */
730  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
731  if (image == (Image *) NULL)
732  return(MagickFalse);
733  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
734  sizeof(region.y)+sizeof(length);
735  count=dpc_read(file,length,message);
736  if (count != (MagickOffsetType) length)
737  return(MagickFalse);
738  p=message;
739  (void) memcpy(&region.width,p,sizeof(region.width));
740  p+=sizeof(region.width);
741  (void) memcpy(&region.height,p,sizeof(region.height));
742  p+=sizeof(region.height);
743  (void) memcpy(&region.x,p,sizeof(region.x));
744  p+=sizeof(region.x);
745  (void) memcpy(&region.y,p,sizeof(region.y));
746  p+=sizeof(region.y);
747  (void) memcpy(&length,p,sizeof(length));
748  p+=sizeof(length);
749  q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
750  exception);
751  if (q == (Quantum *) NULL)
752  return(MagickFalse);
753  count=dpc_read(file,length,(unsigned char *) q);
754  if (count != (MagickOffsetType) length)
755  return(MagickFalse);
756  return(SyncAuthenticPixels(image,exception));
757 }
758 
759 static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket)
760 {
761  char
762  *shared_secret;
763 
765  *exception;
766 
768  status = MagickFalse;
769 
771  count;
772 
773  RandomInfo
774  *random_info;
775 
776  size_t
777  key,
778  session_key;
779 
781  client_socket;
782 
784  *registry;
785 
786  StringInfo
787  *secret;
788 
789  unsigned char
790  command,
791  *p,
792  session[2*MagickPathExtent];
793 
794  /*
795  Distributed pixel cache client.
796  */
797  shared_secret=GetPolicyValue("cache:shared-secret");
798  if (shared_secret == (char *) NULL)
799  ThrowFatalException(CacheFatalError,"shared secret expected");
800  p=session;
801  (void) CopyMagickString((char *) p,shared_secret,MagickPathExtent);
802  p+=strlen(shared_secret);
803  shared_secret=DestroyString(shared_secret);
806  (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
807  session_key=GetMagickSignature(secret);
809  exception=AcquireExceptionInfo();
810  registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
811  (void *(*)(void *)) NULL,RelinquishImageRegistry);
812  client_socket=(*(SOCKET_TYPE *) socket);
813  count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
814  secret=DestroyStringInfo(secret);
815  for (status=MagickFalse; ; )
816  {
817  count=dpc_read(client_socket,1,(unsigned char *) &command);
818  if (count <= 0)
819  break;
820  count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
821  if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
822  break;
823  switch (command)
824  {
825  case 'o':
826  {
827  status=OpenDistributeCache(registry,client_socket,session_key,
828  exception);
829  count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
830  break;
831  }
832  case 'r':
833  {
834  status=ReadDistributeCachePixels(registry,client_socket,session_key,
835  exception);
836  break;
837  }
838  case 'R':
839  {
840  status=ReadDistributeCacheMetacontent(registry,client_socket,
841  session_key,exception);
842  break;
843  }
844  case 'w':
845  {
846  status=WriteDistributeCachePixels(registry,client_socket,session_key,
847  exception);
848  break;
849  }
850  case 'W':
851  {
852  status=WriteDistributeCacheMetacontent(registry,client_socket,
853  session_key,exception);
854  break;
855  }
856  case 'd':
857  {
858  status=DestroyDistributeCache(registry,session_key);
859  break;
860  }
861  default:
862  break;
863  }
864  if (status == MagickFalse)
865  break;
866  if (command == 'd')
867  break;
868  }
869  count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
870  CLOSE_SOCKET(client_socket);
871  exception=DestroyExceptionInfo(exception);
873  return(HANDLER_RETURN_VALUE);
874 }
875 
876 MagickExport void DistributePixelCacheServer(const int port,
877  ExceptionInfo *exception)
878 {
879  char
880  service[MagickPathExtent];
881 
882  int
883  status;
884 
885 #if defined(MAGICKCORE_THREAD_SUPPORT)
886  pthread_attr_t
887  attributes;
888 
889  pthread_t
890  threads;
891 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
892  DWORD
893  threadID;
894 #else
895  Not implemented!
896 #endif
897 
898  struct addrinfo
899  *p;
900 
902  server_socket;
903 
904  struct addrinfo
905  hint,
906  *result;
907 
908  struct sockaddr_in
909  address;
910 
911  /*
912  Launch distributed pixel cache server.
913  */
914  assert(exception != (ExceptionInfo *) NULL);
915  assert(exception->signature == MagickCoreSignature);
916  magick_unreferenced(exception);
917 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
918  NTInitializeWinsock(MagickFalse);
919 #endif
920  (void) memset(&hint,0,sizeof(hint));
921  hint.ai_family=AF_INET;
922  hint.ai_socktype=SOCK_STREAM;
923  hint.ai_flags=AI_PASSIVE;
924  (void) FormatLocaleString(service,MagickPathExtent,"%d",port);
925  status=getaddrinfo((const char *) NULL,service,&hint,&result);
926  if (status != 0)
927  ThrowFatalException(CacheFatalError,"UnableToListen");
928  server_socket=(SOCKET_TYPE) 0;
929  for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
930  {
931  int
932  one;
933 
934  server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
935  if (server_socket == -1)
936  continue;
937  one=1;
938  status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,
939  CHAR_TYPE_CAST &one,(socklen_t) sizeof(one));
940  if (status == -1)
941  {
942  CLOSE_SOCKET(server_socket);
943  continue;
944  }
945  status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
946  if (status == -1)
947  {
948  CLOSE_SOCKET(server_socket);
949  continue;
950  }
951  break;
952  }
953  if (p == (struct addrinfo *) NULL)
954  ThrowFatalException(CacheFatalError,"UnableToBind");
955  freeaddrinfo(result);
956  status=listen(server_socket,DPCPendingConnections);
957  if (status != 0)
958  ThrowFatalException(CacheFatalError,"UnableToListen");
959 #if defined(MAGICKCORE_THREAD_SUPPORT)
960  pthread_attr_init(&attributes);
961 #endif
962  for ( ; ; )
963  {
965  client_socket;
966 
967  socklen_t
968  length;
969 
970  length=(socklen_t) sizeof(address);
971  client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
972  if (client_socket == -1)
973  ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
974 #if defined(MAGICKCORE_THREAD_SUPPORT)
975  status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
976  (void *) &client_socket);
977  if (status == -1)
978  ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
979 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
980  if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0,
981  &threadID) == (HANDLE) NULL)
982  ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
983 #else
984  Not implemented!
985 #endif
986  }
987 }
988 #endif
989 
990 /*
991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 % %
993 % %
994 % %
995 + G e t D i s t r i b u t e C a c h e F i l e %
996 % %
997 % %
998 % %
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 %
1001 % GetDistributeCacheFile() returns the file associated with this
1002 % DistributeCacheInfo structure.
1003 %
1004 % The format of the GetDistributeCacheFile method is:
1005 %
1006 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
1007 %
1008 % A description of each parameter follows:
1009 %
1010 % o server_info: the distributed cache info.
1011 %
1012 */
1014 {
1015  assert(server_info != (DistributeCacheInfo *) NULL);
1016  assert(server_info->signature == MagickCoreSignature);
1017  return(server_info->file);
1018 }
1019 
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 % %
1023 % %
1024 % %
1025 + 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 %
1026 % %
1027 % %
1028 % %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 % GetDistributeCacheHostname() returns the hostname associated with this
1032 % DistributeCacheInfo structure.
1033 %
1034 % The format of the GetDistributeCacheHostname method is:
1035 %
1036 % const char *GetDistributeCacheHostname(
1037 % const DistributeCacheInfo *server_info)
1038 %
1039 % A description of each parameter follows:
1040 %
1041 % o server_info: the distributed cache info.
1042 %
1043 */
1045  const DistributeCacheInfo *server_info)
1046 {
1047  assert(server_info != (DistributeCacheInfo *) NULL);
1048  assert(server_info->signature == MagickCoreSignature);
1049  return(server_info->hostname);
1050 }
1051 
1052 /*
1053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 % %
1055 % %
1056 % %
1057 + G e t D i s t r i b u t e C a c h e P o r t %
1058 % %
1059 % %
1060 % %
1061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 %
1063 % GetDistributeCachePort() returns the port associated with this
1064 % DistributeCacheInfo structure.
1065 %
1066 % The format of the GetDistributeCachePort method is:
1067 %
1068 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1069 %
1070 % A description of each parameter follows:
1071 %
1072 % o server_info: the distributed cache info.
1073 %
1074 */
1076 {
1077  assert(server_info != (DistributeCacheInfo *) NULL);
1078  assert(server_info->signature == MagickCoreSignature);
1079  return(server_info->port);
1080 }
1081 
1082 /*
1083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084 % %
1085 % %
1086 % %
1087 + O p e n D i s t r i b u t e P i x e l C a c h e %
1088 % %
1089 % %
1090 % %
1091 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092 %
1093 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1094 %
1095 % The format of the OpenDistributePixelCache method is:
1096 %
1097 % MagickBooleanType *OpenDistributePixelCache(
1098 % DistributeCacheInfo *server_info,Image *image)
1099 %
1100 % A description of each parameter follows:
1101 %
1102 % o server_info: the distributed cache info.
1103 %
1104 % o image: the image.
1105 %
1106 */
1108  DistributeCacheInfo *server_info,Image *image)
1109 {
1111  status;
1112 
1114  count;
1115 
1116  unsigned char
1117  message[MagickPathExtent],
1118  *p;
1119 
1120  /*
1121  Open distributed pixel cache.
1122  */
1123  assert(server_info != (DistributeCacheInfo *) NULL);
1124  assert(server_info->signature == MagickCoreSignature);
1125  assert(image != (Image *) NULL);
1126  assert(image->signature == MagickCoreSignature);
1127  p=message;
1128  *p++='o'; /* open */
1129  /*
1130  Serialize image attributes (see ValidatePixelCacheMorphology()).
1131  */
1132  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1133  p+=sizeof(server_info->session_key);
1134  (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1135  p+=sizeof(image->storage_class);
1136  (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1137  p+=sizeof(image->colorspace);
1138  (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1139  p+=sizeof(image->alpha_trait);
1140  (void) memcpy(p,&image->channels,sizeof(image->channels));
1141  p+=sizeof(image->channels);
1142  (void) memcpy(p,&image->columns,sizeof(image->columns));
1143  p+=sizeof(image->columns);
1144  (void) memcpy(p,&image->rows,sizeof(image->rows));
1145  p+=sizeof(image->rows);
1146  (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1147  p+=sizeof(image->number_channels);
1148  (void) memcpy(p,image->channel_map,MaxPixelChannels*
1149  sizeof(*image->channel_map));
1150  p+=MaxPixelChannels*sizeof(*image->channel_map);
1151  (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1152  p+=sizeof(image->metacontent_extent);
1153  count=dpc_send(server_info->file,p-message,message);
1154  if (count != (MagickOffsetType) (p-message))
1155  return(MagickFalse);
1156  status=MagickFalse;
1157  count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1158  if (count != (MagickOffsetType) sizeof(status))
1159  return(MagickFalse);
1160  return(status);
1161 }
1162 
1163 /*
1164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 % %
1166 % %
1167 % %
1168 + 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 %
1169 % %
1170 % %
1171 % %
1172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173 %
1174 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1175 % region of the distributed pixel cache.
1176 %
1177 % The format of the ReadDistributePixelCacheMetacontents method is:
1178 %
1179 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1180 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1181 % const MagickSizeType length,unsigned char *metacontent)
1182 %
1183 % A description of each parameter follows:
1184 %
1185 % o server_info: the distributed cache info.
1186 %
1187 % o image: the image.
1188 %
1189 % o region: read the metacontent from this region of the image.
1190 %
1191 % o length: the length in bytes of the metacontent.
1192 %
1193 % o metacontent: read these metacontent from the pixel cache.
1194 %
1195 */
1197  DistributeCacheInfo *server_info,const RectangleInfo *region,
1198  const MagickSizeType length,unsigned char *metacontent)
1199 {
1201  count;
1202 
1203  unsigned char
1204  message[MagickPathExtent],
1205  *p;
1206 
1207  /*
1208  Read distributed pixel cache metacontent.
1209  */
1210  assert(server_info != (DistributeCacheInfo *) NULL);
1211  assert(server_info->signature == MagickCoreSignature);
1212  assert(region != (RectangleInfo *) NULL);
1213  assert(metacontent != (unsigned char *) NULL);
1214  if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1215  return(-1);
1216  p=message;
1217  *p++='R';
1218  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1219  p+=sizeof(server_info->session_key);
1220  (void) memcpy(p,&region->width,sizeof(region->width));
1221  p+=sizeof(region->width);
1222  (void) memcpy(p,&region->height,sizeof(region->height));
1223  p+=sizeof(region->height);
1224  (void) memcpy(p,&region->x,sizeof(region->x));
1225  p+=sizeof(region->x);
1226  (void) memcpy(p,&region->y,sizeof(region->y));
1227  p+=sizeof(region->y);
1228  (void) memcpy(p,&length,sizeof(length));
1229  p+=sizeof(length);
1230  count=dpc_send(server_info->file,p-message,message);
1231  if (count != (MagickOffsetType) (p-message))
1232  return(-1);
1233  return(dpc_read(server_info->file,length,metacontent));
1234 }
1235 
1236 /*
1237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1238 % %
1239 % %
1240 % %
1241 + 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 %
1242 % %
1243 % %
1244 % %
1245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246 %
1247 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1248 % the distributed pixel cache.
1249 %
1250 % The format of the ReadDistributePixelCachePixels method is:
1251 %
1252 % MagickOffsetType ReadDistributePixelCachePixels(
1253 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1254 % const MagickSizeType length,unsigned char *magick_restrict pixels)
1255 %
1256 % A description of each parameter follows:
1257 %
1258 % o server_info: the distributed cache info.
1259 %
1260 % o image: the image.
1261 %
1262 % o region: read the pixels from this region of the image.
1263 %
1264 % o length: the length in bytes of the pixels.
1265 %
1266 % o pixels: read these pixels from the pixel cache.
1267 %
1268 */
1270  DistributeCacheInfo *server_info,const RectangleInfo *region,
1271  const MagickSizeType length,unsigned char *magick_restrict pixels)
1272 {
1274  count;
1275 
1276  unsigned char
1277  message[MagickPathExtent],
1278  *p;
1279 
1280  /*
1281  Read distributed pixel cache pixels.
1282  */
1283  assert(server_info != (DistributeCacheInfo *) NULL);
1284  assert(server_info->signature == MagickCoreSignature);
1285  assert(region != (RectangleInfo *) NULL);
1286  assert(pixels != (unsigned char *) NULL);
1287  if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1288  return(-1);
1289  p=message;
1290  *p++='r';
1291  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1292  p+=sizeof(server_info->session_key);
1293  (void) memcpy(p,&region->width,sizeof(region->width));
1294  p+=sizeof(region->width);
1295  (void) memcpy(p,&region->height,sizeof(region->height));
1296  p+=sizeof(region->height);
1297  (void) memcpy(p,&region->x,sizeof(region->x));
1298  p+=sizeof(region->x);
1299  (void) memcpy(p,&region->y,sizeof(region->y));
1300  p+=sizeof(region->y);
1301  (void) memcpy(p,&length,sizeof(length));
1302  p+=sizeof(length);
1303  count=dpc_send(server_info->file,p-message,message);
1304  if (count != (MagickOffsetType) (p-message))
1305  return(-1);
1306  return(dpc_read(server_info->file,length,pixels));
1307 }
1308 
1309 /*
1310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1311 % %
1312 % %
1313 % %
1314 + 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 %
1315 % %
1316 % %
1317 % %
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 %
1320 % RelinquishDistributePixelCache() frees resources acquired with
1321 % OpenDistributePixelCache().
1322 %
1323 % The format of the RelinquishDistributePixelCache method is:
1324 %
1325 % MagickBooleanType RelinquishDistributePixelCache(
1326 % DistributeCacheInfo *server_info)
1327 %
1328 % A description of each parameter follows:
1329 %
1330 % o server_info: the distributed cache info.
1331 %
1332 */
1334  DistributeCacheInfo *server_info)
1335 {
1337  status;
1338 
1340  count;
1341 
1342  unsigned char
1343  message[MagickPathExtent],
1344  *p;
1345 
1346  /*
1347  Delete distributed pixel cache.
1348  */
1349  assert(server_info != (DistributeCacheInfo *) NULL);
1350  assert(server_info->signature == MagickCoreSignature);
1351  p=message;
1352  *p++='d';
1353  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1354  p+=sizeof(server_info->session_key);
1355  count=dpc_send(server_info->file,p-message,message);
1356  if (count != (MagickOffsetType) (p-message))
1357  return(MagickFalse);
1358  status=MagickFalse;
1359  count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1360  if (count != (MagickOffsetType) sizeof(status))
1361  return(MagickFalse);
1362  return(status);
1363 }
1364 
1365 /*
1366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367 % %
1368 % %
1369 % %
1370 + 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 %
1371 % %
1372 % %
1373 % %
1374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1375 %
1376 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1377 % specified region of the distributed pixel cache.
1378 %
1379 % The format of the WriteDistributePixelCacheMetacontents method is:
1380 %
1381 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1382 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1383 % const MagickSizeType length,const unsigned char *metacontent)
1384 %
1385 % A description of each parameter follows:
1386 %
1387 % o server_info: the distributed cache info.
1388 %
1389 % o image: the image.
1390 %
1391 % o region: write the metacontent to this region of the image.
1392 %
1393 % o length: the length in bytes of the metacontent.
1394 %
1395 % o metacontent: write these metacontent to the pixel cache.
1396 %
1397 */
1399  DistributeCacheInfo *server_info,const RectangleInfo *region,
1400  const MagickSizeType length,const unsigned char *metacontent)
1401 {
1403  count;
1404 
1405  unsigned char
1406  message[MagickPathExtent],
1407  *p;
1408 
1409  /*
1410  Write distributed pixel cache metacontent.
1411  */
1412  assert(server_info != (DistributeCacheInfo *) NULL);
1413  assert(server_info->signature == MagickCoreSignature);
1414  assert(region != (RectangleInfo *) NULL);
1415  assert(metacontent != (unsigned char *) NULL);
1416  if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1417  return(-1);
1418  p=message;
1419  *p++='W';
1420  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1421  p+=sizeof(server_info->session_key);
1422  (void) memcpy(p,&region->width,sizeof(region->width));
1423  p+=sizeof(region->width);
1424  (void) memcpy(p,&region->height,sizeof(region->height));
1425  p+=sizeof(region->height);
1426  (void) memcpy(p,&region->x,sizeof(region->x));
1427  p+=sizeof(region->x);
1428  (void) memcpy(p,&region->y,sizeof(region->y));
1429  p+=sizeof(region->y);
1430  (void) memcpy(p,&length,sizeof(length));
1431  p+=sizeof(length);
1432  count=dpc_send(server_info->file,p-message,message);
1433  if (count != (MagickOffsetType) (p-message))
1434  return(-1);
1435  return(dpc_send(server_info->file,length,metacontent));
1436 }
1437 
1438 /*
1439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1440 % %
1441 % %
1442 % %
1443 + 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 %
1444 % %
1445 % %
1446 % %
1447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448 %
1449 % WriteDistributePixelCachePixels() writes image pixels to the specified
1450 % region of the distributed pixel cache.
1451 %
1452 % The format of the WriteDistributePixelCachePixels method is:
1453 %
1454 % MagickBooleanType WriteDistributePixelCachePixels(
1455 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1456 % const MagickSizeType length,
1457 % const unsigned char *magick_restrict pixels)
1458 %
1459 % A description of each parameter follows:
1460 %
1461 % o server_info: the distributed cache info.
1462 %
1463 % o image: the image.
1464 %
1465 % o region: write the pixels to this region of the image.
1466 %
1467 % o length: the length in bytes of the pixels.
1468 %
1469 % o pixels: write these pixels to the pixel cache.
1470 %
1471 */
1473  DistributeCacheInfo *server_info,const RectangleInfo *region,
1474  const MagickSizeType length,const unsigned char *magick_restrict pixels)
1475 {
1477  count;
1478 
1479  unsigned char
1480  message[MagickPathExtent],
1481  *p;
1482 
1483  /*
1484  Write distributed pixel cache pixels.
1485  */
1486  assert(server_info != (DistributeCacheInfo *) NULL);
1487  assert(server_info->signature == MagickCoreSignature);
1488  assert(region != (RectangleInfo *) NULL);
1489  assert(pixels != (const unsigned char *) NULL);
1490  if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1491  return(-1);
1492  p=message;
1493  *p++='w';
1494  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1495  p+=sizeof(server_info->session_key);
1496  (void) memcpy(p,&region->width,sizeof(region->width));
1497  p+=sizeof(region->width);
1498  (void) memcpy(p,&region->height,sizeof(region->height));
1499  p+=sizeof(region->height);
1500  (void) memcpy(p,&region->x,sizeof(region->x));
1501  p+=sizeof(region->x);
1502  (void) memcpy(p,&region->y,sizeof(region->y));
1503  p+=sizeof(region->y);
1504  (void) memcpy(p,&length,sizeof(length));
1505  p+=sizeof(length);
1506  count=dpc_send(server_info->file,p-message,message);
1507  if (count != (MagickOffsetType) (p-message))
1508  return(-1);
1509  return(dpc_send(server_info->file,length,pixels));
1510 }
size_t rows
Definition: image.h:172
#define magick_restrict
Definition: MagickCore.h:41
MagickExport Quantum * GetAuthenticPixels(Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache.c:1491
#define send(file, buffer, length, flags)
MagickExport MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree, const void *key, const void *value)
Definition: splay-tree.c:154
MagickPrivate const char * GetDistributeCacheHostname(const DistributeCacheInfo *server_info)
char hostname[MagickPathExtent]
#define ThrowFatalException(severity, tag)
#define pthread_attr_init
Definition: vms.h:776
size_t signature
Definition: exception.h:123
static MagickOffsetType dpc_send(int file, const MagickSizeType length, const unsigned char *magick_restrict message)
MagickPrivate MagickBooleanType SyncImagePixelCache(Image *, ExceptionInfo *)
Definition: cache.c:5514
static int ConnectPixelCacheServer(const char *hostname, const int port, size_t *session_key, ExceptionInfo *exception)
#define MAGICK_SSIZE_MAX
Definition: studio.h:339
MagickExport ExceptionInfo * AcquireExceptionInfo(void)
Definition: exception.c:115
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:466
MagickExport size_t CopyMagickString(char *magick_restrict destination, const char *magick_restrict source, const size_t length)
Definition: string.c:731
MagickPrivate DistributeCacheInfo * AcquireDistributeCacheInfo(ExceptionInfo *exception)
static long StringToLong(const char *magick_restrict value)
ClassType storage_class
Definition: image.h:154
size_t width
Definition: geometry.h:132
ssize_t MagickOffsetType
Definition: magick-type.h:133
Definition: image.h:151
MagickExport RandomInfo * DestroyRandomInfo(RandomInfo *random_info)
Definition: random.c:277
MagickExport const void * GetVirtualMetacontent(const Image *image)
Definition: cache.c:2571
MagickExport LogEventType GetLogEventMask(void)
Definition: log.c:399
#define MagickCoreSignature
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1178
MagickPrivate MagickBooleanType OpenDistributePixelCache(DistributeCacheInfo *server_info, Image *image)
MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(DistributeCacheInfo *server_info, const RectangleInfo *region, const MagickSizeType length, const unsigned char *metacontent)
static char * GetHostname(int *port, ExceptionInfo *exception)
MagickBooleanType
Definition: magick-type.h:161
MagickExport char * AcquireString(const char *source)
Definition: string.c:94
MagickExport void * AcquireCriticalMemory(const size_t size)
Definition: memory.c:626
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:815
MagickExport const Quantum * GetVirtualPixels(const Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache.c:3256
#define HANDLER_RETURN_TYPE
MagickExport void DistributePixelCacheServer(const int port, ExceptionInfo *Exception)
MagickExport SplayTreeInfo * DestroySplayTree(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:682
size_t MagickSizeType
Definition: magick-type.h:134
#define MagickPathExtent
MagickPrivate MagickBooleanType RelinquishDistributePixelCache(DistributeCacheInfo *server_info)
PixelTrait alpha_trait
Definition: image.h:280
MagickExport SplayTreeInfo * NewSplayTree(int(*compare)(const void *, const void *), void *(*relinquish_key)(void *), void *(*relinquish_value)(void *))
Definition: splay-tree.c:1141
MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport unsigned int GetMagickSignature(const StringInfo *)
Definition: version.c:545
MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(DistributeCacheInfo *server_info, const RectangleInfo *region, const MagickSizeType length, unsigned char *magick_restrict pixels)
size_t signature
Definition: image.h:354
MagickExport RandomInfo * AcquireRandomInfo(void)
Definition: random.c:166
size_t columns
Definition: image.h:172
MagickExport Image * AcquireImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: image.c:134
MagickExport MagickBooleanType SubstituteString(char **string, const char *search, const char *replace)
Definition: string.c:2585
ssize_t x
Definition: geometry.h:136
#define pthread_create
Definition: vms.h:799
size_t height
Definition: geometry.h:132
Definition: log.h:40
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:477
MagickExport const void * GetValueFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:921
MagickExport StringInfo * AcquireStringInfo(const size_t length)
Definition: string.c:151
#define DPCPendingConnections
#define DPCHostname
#define GetMagickModule()
Definition: log.h:28
MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(DistributeCacheInfo *server_info, const RectangleInfo *region, const MagickSizeType length, const unsigned char *magick_restrict pixels)
#define CLOSE_SOCKET(socket)
#define SOCKET_TYPE
#define recv(file, buffer, length, flags)
static MagickOffsetType dpc_read(int file, const MagickSizeType length, unsigned char *magick_restrict message)
MagickExport MagickBooleanType SyncAuthenticPixels(Image *image, ExceptionInfo *exception)
Definition: cache.c:5458
unsigned short Quantum
Definition: magick-type.h:86
MagickPrivate DistributeCacheInfo * DestroyDistributeCacheInfo(DistributeCacheInfo *server_info)
ChannelType channels
Definition: image.h:366
MagickExport char * DestroyString(char *string)
Definition: string.c:788
MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(DistributeCacheInfo *server_info, const RectangleInfo *region, const MagickSizeType length, unsigned char *metacontent)
size_t number_channels
Definition: image.h:283
#define HANDLER_RETURN_VALUE
MagickExport MagickBooleanType DeleteNodeFromSplayTree(SplayTreeInfo *splay_tree, const void *key)
Definition: splay-tree.c:603
#define MagickMin(x, y)
Definition: image-private.h:39
MagickExport char * GetPolicyValue(const char *name)
Definition: policy.c:533
size_t metacontent_extent
Definition: image.h:283
static RandomInfo * random_info
Definition: resource.c:113
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1162
#define MaxPixelChannels
Definition: pixel.h:27
#define magick_unreferenced(x)
MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
MagickExport void * GetImageRegistry(const RegistryType type, const char *key, ExceptionInfo *exception)
Definition: registry.c:187
#define DPCPort
#define MagickPrivate
#define MagickExport
MagickExport StringInfo * GetRandomKey(RandomInfo *random_info, const size_t length)
Definition: random.c:700
ssize_t y
Definition: geometry.h:136
MagickExport char ** StringToArgv(const char *text, int *argc)
Definition: string.c:2023
MagickExport void * GetAuthenticMetacontent(const Image *image)
Definition: cache.c:1163
static SplayTreeInfo * registry
Definition: registry.c:75
ColorspaceType colorspace
Definition: image.h:157
#define DPCSessionKeyLength
PixelChannelMap * channel_map
Definition: image.h:291
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:418
#define MSG_NOSIGNAL