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