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