MagickCore  7.0.7
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://www.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) ResetMagickMemory(&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(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) ResetMagickMemory(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->read_mask)+
495  sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+
496  sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+
497  sizeof(image->metacontent_extent);
498  count=dpc_read(file,length,message);
499  if (count != (MagickOffsetType) length)
500  return(MagickFalse);
501  /*
502  Deserialize the image attributes.
503  */
504  p=message;
505  (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
506  p+=sizeof(image->storage_class);
507  (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
508  p+=sizeof(image->colorspace);
509  (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
510  p+=sizeof(image->alpha_trait);
511  (void) memcpy(&image->read_mask,p,sizeof(image->read_mask));
512  p+=sizeof(image->read_mask);
513  (void) memcpy(&image->write_mask,p,sizeof(image->write_mask));
514  p+=sizeof(image->write_mask);
515  (void) memcpy(&image->columns,p,sizeof(image->columns));
516  p+=sizeof(image->columns);
517  (void) memcpy(&image->rows,p,sizeof(image->rows));
518  p+=sizeof(image->rows);
519  (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
520  p+=sizeof(image->number_channels);
521  (void) memcpy(image->channel_map,p,MaxPixelChannels*
522  sizeof(*image->channel_map));
523  p+=MaxPixelChannels*sizeof(*image->channel_map);
524  (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
525  p+=sizeof(image->metacontent_extent);
526  if (SyncImagePixelCache(image,exception) == MagickFalse)
527  return(MagickFalse);
528  status=AddValueToSplayTree(registry,(const void *) session_key,image);
529  return(status);
530 }
531 
533  int file,const size_t session_key,ExceptionInfo *exception)
534 {
535  const unsigned char
536  *metacontent;
537 
538  Image
539  *image;
540 
542  count;
543 
545  length;
546 
548  region;
549 
550  register const Quantum
551  *p;
552 
553  register unsigned char
554  *q;
555 
556  unsigned char
557  message[MagickPathExtent];
558 
559  /*
560  Read distributed pixel cache metacontent.
561  */
562  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
563  if (image == (Image *) NULL)
564  return(MagickFalse);
565  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
566  sizeof(region.y)+sizeof(length);
567  count=dpc_read(file,length,message);
568  if (count != (MagickOffsetType) length)
569  return(MagickFalse);
570  q=message;
571  (void) memcpy(&region.width,q,sizeof(region.width));
572  q+=sizeof(region.width);
573  (void) memcpy(&region.height,q,sizeof(region.height));
574  q+=sizeof(region.height);
575  (void) memcpy(&region.x,q,sizeof(region.x));
576  q+=sizeof(region.x);
577  (void) memcpy(&region.y,q,sizeof(region.y));
578  q+=sizeof(region.y);
579  (void) memcpy(&length,q,sizeof(length));
580  q+=sizeof(length);
581  p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
582  exception);
583  if (p == (const Quantum *) NULL)
584  return(MagickFalse);
585  metacontent=(const unsigned char *) GetVirtualMetacontent(image);
586  count=dpc_send(file,length,metacontent);
587  if (count != (MagickOffsetType) length)
588  return(MagickFalse);
589  return(MagickTrue);
590 }
591 
593  int file,const size_t session_key,ExceptionInfo *exception)
594 {
595  Image
596  *image;
597 
599  count;
600 
602  length;
603 
605  region;
606 
607  register const Quantum
608  *p;
609 
610  register unsigned char
611  *q;
612 
613  unsigned char
614  message[MagickPathExtent];
615 
616  /*
617  Read distributed pixel cache pixels.
618  */
619  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
620  if (image == (Image *) NULL)
621  return(MagickFalse);
622  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
623  sizeof(region.y)+sizeof(length);
624  count=dpc_read(file,length,message);
625  if (count != (MagickOffsetType) length)
626  return(MagickFalse);
627  q=message;
628  (void) memcpy(&region.width,q,sizeof(region.width));
629  q+=sizeof(region.width);
630  (void) memcpy(&region.height,q,sizeof(region.height));
631  q+=sizeof(region.height);
632  (void) memcpy(&region.x,q,sizeof(region.x));
633  q+=sizeof(region.x);
634  (void) memcpy(&region.y,q,sizeof(region.y));
635  q+=sizeof(region.y);
636  (void) memcpy(&length,q,sizeof(length));
637  q+=sizeof(length);
638  p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
639  exception);
640  if (p == (const Quantum *) NULL)
641  return(MagickFalse);
642  count=dpc_send(file,length,(unsigned char *) p);
643  if (count != (MagickOffsetType) length)
644  return(MagickFalse);
645  return(MagickTrue);
646 }
647 
648 static void *RelinquishImageRegistry(void *image)
649 {
650  return((void *) DestroyImageList((Image *) image));
651 }
652 
654  SplayTreeInfo *registry,int file,const size_t session_key,
655  ExceptionInfo *exception)
656 {
657  Image
658  *image;
659 
661  count;
662 
664  length;
665 
667  region;
668 
669  register Quantum
670  *q;
671 
672  register unsigned char
673  *p;
674 
675  unsigned char
676  message[MagickPathExtent],
677  *metacontent;
678 
679  /*
680  Write distributed pixel cache metacontent.
681  */
682  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
683  if (image == (Image *) NULL)
684  return(MagickFalse);
685  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
686  sizeof(region.y)+sizeof(length);
687  count=dpc_read(file,length,message);
688  if (count != (MagickOffsetType) length)
689  return(MagickFalse);
690  p=message;
691  (void) memcpy(&region.width,p,sizeof(region.width));
692  p+=sizeof(region.width);
693  (void) memcpy(&region.height,p,sizeof(region.height));
694  p+=sizeof(region.height);
695  (void) memcpy(&region.x,p,sizeof(region.x));
696  p+=sizeof(region.x);
697  (void) memcpy(&region.y,p,sizeof(region.y));
698  p+=sizeof(region.y);
699  (void) memcpy(&length,p,sizeof(length));
700  p+=sizeof(length);
701  q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
702  exception);
703  if (q == (Quantum *) NULL)
704  return(MagickFalse);
705  metacontent=(unsigned char *) GetAuthenticMetacontent(image);
706  count=dpc_read(file,length,metacontent);
707  if (count != (MagickOffsetType) length)
708  return(MagickFalse);
709  return(SyncAuthenticPixels(image,exception));
710 }
711 
713  int file,const size_t session_key,ExceptionInfo *exception)
714 {
715  Image
716  *image;
717 
719  count;
720 
722  length;
723 
725  region;
726 
727  register Quantum
728  *q;
729 
730  register unsigned char
731  *p;
732 
733  unsigned char
734  message[MagickPathExtent];
735 
736  /*
737  Write distributed pixel cache pixels.
738  */
739  image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
740  if (image == (Image *) NULL)
741  return(MagickFalse);
742  length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
743  sizeof(region.y)+sizeof(length);
744  count=dpc_read(file,length,message);
745  if (count != (MagickOffsetType) length)
746  return(MagickFalse);
747  p=message;
748  (void) memcpy(&region.width,p,sizeof(region.width));
749  p+=sizeof(region.width);
750  (void) memcpy(&region.height,p,sizeof(region.height));
751  p+=sizeof(region.height);
752  (void) memcpy(&region.x,p,sizeof(region.x));
753  p+=sizeof(region.x);
754  (void) memcpy(&region.y,p,sizeof(region.y));
755  p+=sizeof(region.y);
756  (void) memcpy(&length,p,sizeof(length));
757  p+=sizeof(length);
758  q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
759  exception);
760  if (q == (Quantum *) NULL)
761  return(MagickFalse);
762  count=dpc_read(file,length,(unsigned char *) q);
763  if (count != (MagickOffsetType) length)
764  return(MagickFalse);
765  return(SyncAuthenticPixels(image,exception));
766 }
767 
769 {
770  char
771  *shared_secret;
772 
774  *exception;
775 
777  status;
778 
780  count;
781 
782  register unsigned char
783  *p;
784 
785  RandomInfo
786  *random_info;
787 
788  size_t
789  key,
790  session_key;
791 
793  client_socket;
794 
796  *registry;
797 
798  StringInfo
799  *secret;
800 
801  unsigned char
802  command,
803  session[2*MagickPathExtent];
804 
805  /*
806  Distributed pixel cache client.
807  */
808  shared_secret=GetPolicyValue("cache:shared-secret");
809  if (shared_secret == (char *) NULL)
810  ThrowFatalException(CacheFatalError,"shared secret expected");
811  p=session;
812  (void) CopyMagickString((char *) p,shared_secret,MagickPathExtent);
813  p+=strlen(shared_secret);
814  shared_secret=DestroyString(shared_secret);
815  random_info=AcquireRandomInfo();
816  secret=GetRandomKey(random_info,DPCSessionKeyLength);
817  (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
818  session_key=GetMagickSignature(secret);
819  random_info=DestroyRandomInfo(random_info);
820  exception=AcquireExceptionInfo();
821  registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
822  (void *(*)(void *)) NULL,RelinquishImageRegistry);
823  client_socket=(*(SOCKET_TYPE *) socket);
824  count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
825  secret=DestroyStringInfo(secret);
826  for ( ; ; )
827  {
828  count=dpc_read(client_socket,1,(unsigned char *) &command);
829  if (count <= 0)
830  break;
831  count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
832  if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
833  break;
834  status=MagickFalse;
835  switch (command)
836  {
837  case 'o':
838  {
839  status=OpenDistributeCache(registry,client_socket,session_key,
840  exception);
841  count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
842  break;
843  }
844  case 'r':
845  {
846  status=ReadDistributeCachePixels(registry,client_socket,session_key,
847  exception);
848  break;
849  }
850  case 'R':
851  {
852  status=ReadDistributeCacheMetacontent(registry,client_socket,
853  session_key,exception);
854  break;
855  }
856  case 'w':
857  {
858  status=WriteDistributeCachePixels(registry,client_socket,session_key,
859  exception);
860  break;
861  }
862  case 'W':
863  {
864  status=WriteDistributeCacheMetacontent(registry,client_socket,
865  session_key,exception);
866  break;
867  }
868  case 'd':
869  {
870  status=DestroyDistributeCache(registry,session_key);
871  break;
872  }
873  default:
874  break;
875  }
876  if (status == MagickFalse)
877  break;
878  if (command == 'd')
879  break;
880  }
881  count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
882  CLOSE_SOCKET(client_socket);
883  exception=DestroyExceptionInfo(exception);
884  registry=DestroySplayTree(registry);
885  return(HANDLER_RETURN_VALUE);
886 }
887 
889  ExceptionInfo *exception)
890 {
891 #if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
892  char
893  service[MagickPathExtent];
894 
895  int
896  status;
897 
898 #if defined(MAGICKCORE_THREAD_SUPPORT)
899  pthread_attr_t
900  attributes;
901 
902  pthread_t
903  threads;
904 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
905  DWORD
906  threadID;
907 #else
908  Not implemented!
909 #endif
910 
911  register struct addrinfo
912  *p;
913 
915  server_socket;
916 
917  struct addrinfo
918  hint,
919  *result;
920 
921  struct sockaddr_in
922  address;
923 
924  /*
925  Launch distributed pixel cache server.
926  */
927  assert(exception != (ExceptionInfo *) NULL);
928  assert(exception->signature == MagickCoreSignature);
929  magick_unreferenced(exception);
930 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
931  NTInitializeWinsock(MagickFalse);
932 #endif
933  (void) ResetMagickMemory(&hint,0,sizeof(hint));
934  hint.ai_family=AF_INET;
935  hint.ai_socktype=SOCK_STREAM;
936  hint.ai_flags=AI_PASSIVE;
937  (void) FormatLocaleString(service,MagickPathExtent,"%d",port);
938  status=getaddrinfo((const char *) NULL,service,&hint,&result);
939  if (status != 0)
940  ThrowFatalException(CacheFatalError,"UnableToListen");
941  server_socket=(SOCKET_TYPE) 0;
942  for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
943  {
944  int
945  one;
946 
947  server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
948  if (server_socket == -1)
949  continue;
950  one=1;
951  status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,
952  CHAR_TYPE_CAST &one,(socklen_t) sizeof(one));
953  if (status == -1)
954  {
955  CLOSE_SOCKET(server_socket);
956  continue;
957  }
958  status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
959  if (status == -1)
960  {
961  CLOSE_SOCKET(server_socket);
962  continue;
963  }
964  break;
965  }
966  if (p == (struct addrinfo *) NULL)
967  ThrowFatalException(CacheFatalError,"UnableToBind");
968  freeaddrinfo(result);
969  status=listen(server_socket,DPCPendingConnections);
970  if (status != 0)
971  ThrowFatalException(CacheFatalError,"UnableToListen");
972 #if defined(MAGICKCORE_THREAD_SUPPORT)
973  pthread_attr_init(&attributes);
974 #endif
975  for ( ; ; )
976  {
978  client_socket;
979 
980  socklen_t
981  length;
982 
983  length=(socklen_t) sizeof(address);
984  client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
985  if (client_socket == -1)
986  ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
987 #if defined(MAGICKCORE_THREAD_SUPPORT)
988  status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
989  (void *) &client_socket);
990  if (status == -1)
991  ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
992 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
993  if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0,
994  &threadID) == (HANDLE) NULL)
995  ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
996 #else
997  Not implemented!
998 #endif
999  }
1000 #else
1001  magick_unreferenced(port);
1002  ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn");
1003 #endif
1004 }
1005 
1006 /*
1007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008 % %
1009 % %
1010 % %
1011 + G e t D i s t r i b u t e C a c h e F i l e %
1012 % %
1013 % %
1014 % %
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 %
1017 % GetDistributeCacheFile() returns the file associated with this
1018 % DistributeCacheInfo structure.
1019 %
1020 % The format of the GetDistributeCacheFile method is:
1021 %
1022 % int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
1023 %
1024 % A description of each parameter follows:
1025 %
1026 % o server_info: the distributed cache info.
1027 %
1028 */
1030 {
1031  assert(server_info != (DistributeCacheInfo *) NULL);
1032  assert(server_info->signature == MagickCoreSignature);
1033  return(server_info->file);
1034 }
1035 
1036 /*
1037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % %
1039 % %
1040 % %
1041 + 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 %
1042 % %
1043 % %
1044 % %
1045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 %
1047 % GetDistributeCacheHostname() returns the hostname associated with this
1048 % DistributeCacheInfo structure.
1049 %
1050 % The format of the GetDistributeCacheHostname method is:
1051 %
1052 % const char *GetDistributeCacheHostname(
1053 % const DistributeCacheInfo *server_info)
1054 %
1055 % A description of each parameter follows:
1056 %
1057 % o server_info: the distributed cache info.
1058 %
1059 */
1061  const DistributeCacheInfo *server_info)
1062 {
1063  assert(server_info != (DistributeCacheInfo *) NULL);
1064  assert(server_info->signature == MagickCoreSignature);
1065  return(server_info->hostname);
1066 }
1067 
1068 /*
1069 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070 % %
1071 % %
1072 % %
1073 + G e t D i s t r i b u t e C a c h e P o r t %
1074 % %
1075 % %
1076 % %
1077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 %
1079 % GetDistributeCachePort() returns the port associated with this
1080 % DistributeCacheInfo structure.
1081 %
1082 % The format of the GetDistributeCachePort method is:
1083 %
1084 % int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1085 %
1086 % A description of each parameter follows:
1087 %
1088 % o server_info: the distributed cache info.
1089 %
1090 */
1092 {
1093  assert(server_info != (DistributeCacheInfo *) NULL);
1094  assert(server_info->signature == MagickCoreSignature);
1095  return(server_info->port);
1096 }
1097 
1098 /*
1099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100 % %
1101 % %
1102 % %
1103 + O p e n D i s t r i b u t e P i x e l C a c h e %
1104 % %
1105 % %
1106 % %
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108 %
1109 % OpenDistributePixelCache() opens a pixel cache on a remote server.
1110 %
1111 % The format of the OpenDistributePixelCache method is:
1112 %
1113 % MagickBooleanType *OpenDistributePixelCache(
1114 % DistributeCacheInfo *server_info,Image *image)
1115 %
1116 % A description of each parameter follows:
1117 %
1118 % o server_info: the distributed cache info.
1119 %
1120 % o image: the image.
1121 %
1122 */
1124  DistributeCacheInfo *server_info,Image *image)
1125 {
1127 #ifdef __VMS
1128  status=MagickTrue;
1129 #else
1130  status;
1131 #endif
1132 
1134  count;
1135 
1136  register unsigned char
1137  *p;
1138 
1139  unsigned char
1140  message[MagickPathExtent];
1141 
1142  /*
1143  Open distributed pixel cache.
1144  */
1145  assert(server_info != (DistributeCacheInfo *) NULL);
1146  assert(server_info->signature == MagickCoreSignature);
1147  assert(image != (Image *) NULL);
1148  assert(image->signature == MagickCoreSignature);
1149  p=message;
1150  *p++='o'; /* open */
1151  /*
1152  Serialize image attributes (see ValidatePixelCacheMorphology()).
1153  */
1154  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1155  p+=sizeof(server_info->session_key);
1156  (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1157  p+=sizeof(image->storage_class);
1158  (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1159  p+=sizeof(image->colorspace);
1160  (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1161  p+=sizeof(image->alpha_trait);
1162  (void) memcpy(p,&image->read_mask,sizeof(image->read_mask));
1163  p+=sizeof(image->read_mask);
1164  (void) memcpy(p,&image->write_mask,sizeof(image->write_mask));
1165  p+=sizeof(image->write_mask);
1166  (void) memcpy(p,&image->columns,sizeof(image->columns));
1167  p+=sizeof(image->columns);
1168  (void) memcpy(p,&image->rows,sizeof(image->rows));
1169  p+=sizeof(image->rows);
1170  (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1171  p+=sizeof(image->number_channels);
1172  (void) memcpy(p,image->channel_map,MaxPixelChannels*
1173  sizeof(*image->channel_map));
1174  p+=MaxPixelChannels*sizeof(*image->channel_map);
1175  (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1176  p+=sizeof(image->metacontent_extent);
1177  count=dpc_send(server_info->file,p-message,message);
1178  if (count != (MagickOffsetType) (p-message))
1179  return(MagickFalse);
1180  status=MagickFalse;
1181  count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1182  if (count != (MagickOffsetType) sizeof(status))
1183  return(MagickFalse);
1184  return(status);
1185 }
1186 
1187 /*
1188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 % %
1190 % %
1191 % %
1192 + 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 %
1193 % %
1194 % %
1195 % %
1196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197 %
1198 % ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1199 % region of the distributed pixel cache.
1200 %
1201 % The format of the ReadDistributePixelCacheMetacontents method is:
1202 %
1203 % MagickOffsetType ReadDistributePixelCacheMetacontents(
1204 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1205 % const MagickSizeType length,unsigned char *metacontent)
1206 %
1207 % A description of each parameter follows:
1208 %
1209 % o server_info: the distributed cache info.
1210 %
1211 % o image: the image.
1212 %
1213 % o region: read the metacontent from this region of the image.
1214 %
1215 % o length: the length in bytes of the metacontent.
1216 %
1217 % o metacontent: read these metacontent from the pixel cache.
1218 %
1219 */
1221  DistributeCacheInfo *server_info,const RectangleInfo *region,
1222  const MagickSizeType length,unsigned char *metacontent)
1223 {
1225  count;
1226 
1227  register unsigned char
1228  *p;
1229 
1230  unsigned char
1231  message[MagickPathExtent];
1232 
1233  /*
1234  Read distributed pixel cache metacontent.
1235  */
1236  assert(server_info != (DistributeCacheInfo *) NULL);
1237  assert(server_info->signature == MagickCoreSignature);
1238  assert(region != (RectangleInfo *) NULL);
1239  assert(metacontent != (unsigned char *) NULL);
1240  if (length > (MagickSizeType) SSIZE_MAX)
1241  return(-1);
1242  p=message;
1243  *p++='R';
1244  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1245  p+=sizeof(server_info->session_key);
1246  (void) memcpy(p,&region->width,sizeof(region->width));
1247  p+=sizeof(region->width);
1248  (void) memcpy(p,&region->height,sizeof(region->height));
1249  p+=sizeof(region->height);
1250  (void) memcpy(p,&region->x,sizeof(region->x));
1251  p+=sizeof(region->x);
1252  (void) memcpy(p,&region->y,sizeof(region->y));
1253  p+=sizeof(region->y);
1254  (void) memcpy(p,&length,sizeof(length));
1255  p+=sizeof(length);
1256  count=dpc_send(server_info->file,p-message,message);
1257  if (count != (MagickOffsetType) (p-message))
1258  return(-1);
1259  return(dpc_read(server_info->file,length,metacontent));
1260 }
1261 
1262 /*
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 % %
1265 % %
1266 % %
1267 + 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 %
1268 % %
1269 % %
1270 % %
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1272 %
1273 % ReadDistributePixelCachePixels() reads pixels from the specified region of
1274 % the distributed pixel cache.
1275 %
1276 % The format of the ReadDistributePixelCachePixels method is:
1277 %
1278 % MagickOffsetType ReadDistributePixelCachePixels(
1279 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1280 % const MagickSizeType length,unsigned char *magick_restrict pixels)
1281 %
1282 % A description of each parameter follows:
1283 %
1284 % o server_info: the distributed cache info.
1285 %
1286 % o image: the image.
1287 %
1288 % o region: read the pixels from this region of the image.
1289 %
1290 % o length: the length in bytes of the pixels.
1291 %
1292 % o pixels: read these pixels from the pixel cache.
1293 %
1294 */
1296  DistributeCacheInfo *server_info,const RectangleInfo *region,
1297  const MagickSizeType length,unsigned char *magick_restrict pixels)
1298 {
1300  count;
1301 
1302  register unsigned char
1303  *p;
1304 
1305  unsigned char
1306  message[MagickPathExtent];
1307 
1308  /*
1309  Read distributed pixel cache pixels.
1310  */
1311  assert(server_info != (DistributeCacheInfo *) NULL);
1312  assert(server_info->signature == MagickCoreSignature);
1313  assert(region != (RectangleInfo *) NULL);
1314  assert(pixels != (unsigned char *) NULL);
1315  if (length > (MagickSizeType) SSIZE_MAX)
1316  return(-1);
1317  p=message;
1318  *p++='r';
1319  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1320  p+=sizeof(server_info->session_key);
1321  (void) memcpy(p,&region->width,sizeof(region->width));
1322  p+=sizeof(region->width);
1323  (void) memcpy(p,&region->height,sizeof(region->height));
1324  p+=sizeof(region->height);
1325  (void) memcpy(p,&region->x,sizeof(region->x));
1326  p+=sizeof(region->x);
1327  (void) memcpy(p,&region->y,sizeof(region->y));
1328  p+=sizeof(region->y);
1329  (void) memcpy(p,&length,sizeof(length));
1330  p+=sizeof(length);
1331  count=dpc_send(server_info->file,p-message,message);
1332  if (count != (MagickOffsetType) (p-message))
1333  return(-1);
1334  return(dpc_read(server_info->file,length,pixels));
1335 }
1336 
1337 /*
1338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339 % %
1340 % %
1341 % %
1342 + 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 %
1343 % %
1344 % %
1345 % %
1346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347 %
1348 % RelinquishDistributePixelCache() frees resources acquired with
1349 % OpenDistributePixelCache().
1350 %
1351 % The format of the RelinquishDistributePixelCache method is:
1352 %
1353 % MagickBooleanType RelinquishDistributePixelCache(
1354 % DistributeCacheInfo *server_info)
1355 %
1356 % A description of each parameter follows:
1357 %
1358 % o server_info: the distributed cache info.
1359 %
1360 */
1362  DistributeCacheInfo *server_info)
1363 {
1365 #ifdef __VMS
1366  status = MagickTrue;
1367 #else
1368  status;
1369 #endif
1370 
1372  count;
1373 
1374  register unsigned char
1375  *p;
1376 
1377  unsigned char
1378  message[MagickPathExtent];
1379 
1380  /*
1381  Delete distributed pixel cache.
1382  */
1383  assert(server_info != (DistributeCacheInfo *) NULL);
1384  assert(server_info->signature == MagickCoreSignature);
1385  p=message;
1386  *p++='d';
1387  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1388  p+=sizeof(server_info->session_key);
1389  count=dpc_send(server_info->file,p-message,message);
1390  if (count != (MagickOffsetType) (p-message))
1391  return(MagickFalse);
1392  count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1393  if (count != (MagickOffsetType) sizeof(status))
1394  return(MagickFalse);
1395  return(status);
1396 }
1397 
1398 /*
1399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400 % %
1401 % %
1402 % %
1403 + 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 %
1404 % %
1405 % %
1406 % %
1407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408 %
1409 % WriteDistributePixelCacheMetacontents() writes image metacontent to the
1410 % specified region of the distributed pixel cache.
1411 %
1412 % The format of the WriteDistributePixelCacheMetacontents method is:
1413 %
1414 % MagickOffsetType WriteDistributePixelCacheMetacontents(
1415 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1416 % const MagickSizeType length,const unsigned char *metacontent)
1417 %
1418 % A description of each parameter follows:
1419 %
1420 % o server_info: the distributed cache info.
1421 %
1422 % o image: the image.
1423 %
1424 % o region: write the metacontent to this region of the image.
1425 %
1426 % o length: the length in bytes of the metacontent.
1427 %
1428 % o metacontent: write these metacontent to the pixel cache.
1429 %
1430 */
1432  DistributeCacheInfo *server_info,const RectangleInfo *region,
1433  const MagickSizeType length,const unsigned char *metacontent)
1434 {
1436  count;
1437 
1438  register unsigned char
1439  *p;
1440 
1441  unsigned char
1442  message[MagickPathExtent];
1443 
1444  /*
1445  Write distributed pixel cache metacontent.
1446  */
1447  assert(server_info != (DistributeCacheInfo *) NULL);
1448  assert(server_info->signature == MagickCoreSignature);
1449  assert(region != (RectangleInfo *) NULL);
1450  assert(metacontent != (unsigned char *) NULL);
1451  if (length > (MagickSizeType) SSIZE_MAX)
1452  return(-1);
1453  p=message;
1454  *p++='W';
1455  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1456  p+=sizeof(server_info->session_key);
1457  (void) memcpy(p,&region->width,sizeof(region->width));
1458  p+=sizeof(region->width);
1459  (void) memcpy(p,&region->height,sizeof(region->height));
1460  p+=sizeof(region->height);
1461  (void) memcpy(p,&region->x,sizeof(region->x));
1462  p+=sizeof(region->x);
1463  (void) memcpy(p,&region->y,sizeof(region->y));
1464  p+=sizeof(region->y);
1465  (void) memcpy(p,&length,sizeof(length));
1466  p+=sizeof(length);
1467  count=dpc_send(server_info->file,p-message,message);
1468  if (count != (MagickOffsetType) (p-message))
1469  return(-1);
1470  return(dpc_send(server_info->file,length,metacontent));
1471 }
1472 
1473 /*
1474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475 % %
1476 % %
1477 % %
1478 + 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 %
1479 % %
1480 % %
1481 % %
1482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483 %
1484 % WriteDistributePixelCachePixels() writes image pixels to the specified
1485 % region of the distributed pixel cache.
1486 %
1487 % The format of the WriteDistributePixelCachePixels method is:
1488 %
1489 % MagickBooleanType WriteDistributePixelCachePixels(
1490 % DistributeCacheInfo *server_info,const RectangleInfo *region,
1491 % const MagickSizeType length,
1492 % const unsigned char *magick_restrict pixels)
1493 %
1494 % A description of each parameter follows:
1495 %
1496 % o server_info: the distributed cache info.
1497 %
1498 % o image: the image.
1499 %
1500 % o region: write the pixels to this region of the image.
1501 %
1502 % o length: the length in bytes of the pixels.
1503 %
1504 % o pixels: write these pixels to the pixel cache.
1505 %
1506 */
1508  DistributeCacheInfo *server_info,const RectangleInfo *region,
1509  const MagickSizeType length,const unsigned char *magick_restrict pixels)
1510 {
1512  count;
1513 
1514  register unsigned char
1515  *p;
1516 
1517  unsigned char
1518  message[MagickPathExtent];
1519 
1520  /*
1521  Write distributed pixel cache pixels.
1522  */
1523  assert(server_info != (DistributeCacheInfo *) NULL);
1524  assert(server_info->signature == MagickCoreSignature);
1525  assert(region != (RectangleInfo *) NULL);
1526  assert(pixels != (const unsigned char *) NULL);
1527  if (length > (MagickSizeType) SSIZE_MAX)
1528  return(-1);
1529  p=message;
1530  *p++='w';
1531  (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1532  p+=sizeof(server_info->session_key);
1533  (void) memcpy(p,&region->width,sizeof(region->width));
1534  p+=sizeof(region->width);
1535  (void) memcpy(p,&region->height,sizeof(region->height));
1536  p+=sizeof(region->height);
1537  (void) memcpy(p,&region->x,sizeof(region->x));
1538  p+=sizeof(region->x);
1539  (void) memcpy(p,&region->y,sizeof(region->y));
1540  p+=sizeof(region->y);
1541  (void) memcpy(p,&length,sizeof(length));
1542  p+=sizeof(length);
1543  count=dpc_send(server_info->file,p-message,message);
1544  if (count != (MagickOffsetType) (p-message))
1545  return(-1);
1546  return(dpc_send(server_info->file,length,pixels));
1547 }
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:1382
#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:5284
static int ConnectPixelCacheServer(const char *hostname, const int port, size_t *session_key, ExceptionInfo *exception)
MagickBooleanType read_mask
Definition: image.h:276
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:473
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:127
Definition: image.h:151
MagickExport RandomInfo * DestroyRandomInfo(RandomInfo *random_info)
Definition: random.c:274
MagickExport const void * GetVirtualMetacontent(const Image *image)
Definition: cache.c:2462
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:1283
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:156
MagickExport char * AcquireString(const char *source)
Definition: string.c:124
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1153
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:837
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:3159
#define HANDLER_RETURN_TYPE
MagickExport SplayTreeInfo * DestroySplayTree(SplayTreeInfo *splay_tree)
Definition: splay-tree.c:682
size_t MagickSizeType
Definition: magick-type.h:128
#define MagickPathExtent
MagickPrivate MagickBooleanType RelinquishDistributePixelCache(DistributeCacheInfo *server_info)
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:716
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:1058
MagickExport unsigned int GetMagickSignature(const StringInfo *)
Definition: version.c:508
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:154
MagickExport MagickBooleanType SubstituteString(char **string, const char *search, const char *replace)
Definition: string.c:2535
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:742
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:442
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:170
#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:5227
unsigned short Quantum
Definition: magick-type.h:82
static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket)
MagickPrivate DistributeCacheInfo * DestroyDistributeCacheInfo(DistributeCacheInfo *server_info)
MagickExport char * DestroyString(char *string)
Definition: string.c:810
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:109
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1027
#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:2029
MagickBooleanType write_mask
Definition: image.h:276
MagickExport void * GetAuthenticMetacontent(const Image *image)
Definition: cache.c:1057
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:417
#define MSG_NOSIGNAL