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