blob: d0ee6f2ceb0d025c3f46a563e653eaf11bf81a4e [file] [log] [blame]
Cristy9125cd52015-09-17 20:16:13 -04001/*
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-2015 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% http://www.imagemagick.org/script/license.php %
32% %
33% Unless required by applicable law or agreed to in writing, software %
34% distributed under the License is distributed on an "AS IS" BASIS, %
35% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
36% See the License for the specific language governing permissions and %
37% limitations under the License. %
38% %
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40%
41% A distributed pixel cache is an extension of the traditional pixel cache
42% available on a single host. The distributed pixel cache may span multiple
43% servers so that it can grow in size and transactional capacity to support
44% very large images. Start up the pixel cache server on one or more machines.
45% When you read or operate on an image and the local pixel cache resources are
46% exhausted, ImageMagick contacts one or more of these remote pixel servers to
47% store or retrieve pixels.
48%
49*/
50
51/*
52 Include declarations.
53*/
54#include "MagickCore/studio.h"
55#include "MagickCore/cache.h"
56#include "MagickCore/cache-private.h"
57#include "MagickCore/distribute-cache.h"
58#include "MagickCore/distribute-cache-private.h"
59#include "MagickCore/exception.h"
60#include "MagickCore/exception-private.h"
61#include "MagickCore/geometry.h"
62#include "MagickCore/image.h"
63#include "MagickCore/image-private.h"
64#include "MagickCore/list.h"
65#include "MagickCore/locale_.h"
66#include "MagickCore/memory_.h"
67#include "MagickCore/nt-base-private.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"
74#include "MagickCore/string-private.h"
75#include "MagickCore/version.h"
76#include "MagickCore/version-private.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
90#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
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
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
147static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
dirk05d2ff72015-11-18 23:13:43 +0100148 unsigned char *magick_restrict message)
Cristy9125cd52015-09-17 20:16:13 -0400149{
150 register MagickOffsetType
151 i;
152
153 ssize_t
154 count;
155
156#if !defined(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
176static int ConnectPixelCacheServer(const char *hostname,const int port,
177 size_t *session_key,ExceptionInfo *exception)
178{
179#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
180 char
181 service[MagickPathExtent];
182
183 const char
184 *shared_secret;
185
186 int
187 status;
188
189 SOCKET_TYPE
190 client_socket;
191
192 ssize_t
193 count;
194
195 struct addrinfo
196 hint,
197 *result;
198
199 unsigned char
200 secret[MagickPathExtent];
201
202 /*
203 Connect to distributed pixel cache and get session key.
204 */
205 *session_key=0;
206 shared_secret=GetPolicyValue("shared-secret");
207 if (shared_secret == (const char *) NULL)
208 {
209 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
210 "DistributedPixelCache","'%s'","shared secret expected");
211 return(-1);
212 }
213#if defined(MAGICKCORE_WINDOWS_SUPPORT)
214 NTInitializeWinsock(MagickTrue);
215#endif
216 (void) ResetMagickMemory(&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 {
224 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
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);
233 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
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);
242 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
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(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
265 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
266 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
267 return(MagickFalse);
268#endif
269}
270
271static 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
326MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
327 ExceptionInfo *exception)
328{
329 char
330 *hostname;
331
332 DistributeCacheInfo
333 *server_info;
334
335 size_t
336 session_key;
337
338 /*
339 Connect to the distributed pixel cache server.
340 */
341 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
342 if (server_info == (DistributeCacheInfo *) NULL)
343 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
344 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
345 server_info->signature=MagickCoreSignature;
346 server_info->port=0;
347 hostname=GetHostname(&server_info->port,exception);
348 session_key=0;
349 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
350 &session_key,exception);
351 if (server_info->file == -1)
352 server_info=DestroyDistributeCacheInfo(server_info);
353 else
354 {
355 server_info->session_key=session_key;
356 (void) CopyMagickString(server_info->hostname,hostname,MagickPathExtent);
357 server_info->debug=IsEventLogging();
358 }
359 hostname=DestroyString(hostname);
360 return(server_info);
361}
362
363/*
364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365% %
366% %
367% %
368+ D e s t r o y D i s t r i b u t e C a c h e I n f o %
369% %
370% %
371% %
372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373%
374% DestroyDistributeCacheInfo() deallocates memory associated with an
375% DistributeCacheInfo structure.
376%
377% The format of the DestroyDistributeCacheInfo method is:
378%
379% DistributeCacheInfo *DestroyDistributeCacheInfo(
380% DistributeCacheInfo *server_info)
381%
382% A description of each parameter follows:
383%
384% o server_info: the distributed cache info.
385%
386*/
387MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
388 DistributeCacheInfo *server_info)
389{
390 assert(server_info != (DistributeCacheInfo *) NULL);
391 assert(server_info->signature == MagickCoreSignature);
392 if (server_info->file > 0)
393 CLOSE_SOCKET(server_info->file);
394 server_info->signature=(~MagickCoreSignature);
395 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
396 return(server_info);
397}
398
399/*
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401% %
402% %
403% %
404+ D i s t r i b u t e P i x e l C a c h e S e r v e r %
405% %
406% %
407% %
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%
410% DistributePixelCacheServer() waits on the specified port for commands to
411% create, read, update, or destroy a pixel cache.
412%
413% The format of the DistributePixelCacheServer() method is:
414%
415% void DistributePixelCacheServer(const int port)
416%
417% A description of each parameter follows:
418%
419% o port: connect the distributed pixel cache at this port.
420%
421% o exception: return any errors or warnings in this structure.
422%
423*/
424
425static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
426 const size_t session_key)
427{
428 /*
429 Destroy distributed pixel cache.
430 */
431 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
432}
433
434static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
dirk05d2ff72015-11-18 23:13:43 +0100435 const unsigned char *magick_restrict message)
Cristy9125cd52015-09-17 20:16:13 -0400436{
437 MagickOffsetType
438 count;
439
440 register MagickOffsetType
441 i;
442
443#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
444 magick_unreferenced(file);
445 magick_unreferenced(message);
446#endif
447
448 /*
449 Ensure a complete message is sent.
450 */
451 count=0;
452 for (i=0; i < (MagickOffsetType) length; i+=count)
453 {
454 count=(MagickOffsetType) send(file,CHAR_TYPE_CAST message+i,(LENGTH_TYPE)
455 MagickMin(length-i,(MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
456 if (count <= 0)
457 {
458 count=0;
459 if (errno != EINTR)
460 break;
461 }
462 }
463 return(i);
464}
465
466static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file,
467 const size_t session_key,ExceptionInfo *exception)
468{
469 Image
470 *image;
471
472 MagickBooleanType
473 status;
474
475 MagickOffsetType
476 count;
477
478 MagickSizeType
479 length;
480
481 register unsigned char
482 *p;
483
484 unsigned char
485 message[MagickPathExtent];
486
487 /*
488 Open distributed pixel cache.
489 */
490 image=AcquireImage((ImageInfo *) NULL,exception);
491 if (image == (Image *) NULL)
492 return(MagickFalse);
493 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
494 sizeof(image->alpha_trait)+sizeof(image->read_mask)+
495 sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+
496 sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+
497 sizeof(image->metacontent_extent);
498 count=dpc_read(file,length,message);
499 if (count != (MagickOffsetType) length)
500 return(MagickFalse);
501 /*
502 Deserialize the image attributes.
503 */
504 p=message;
505 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
506 p+=sizeof(image->storage_class);
507 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
508 p+=sizeof(image->colorspace);
509 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
510 p+=sizeof(image->alpha_trait);
511 (void) memcpy(&image->read_mask,p,sizeof(image->read_mask));
512 p+=sizeof(image->read_mask);
513 (void) memcpy(&image->write_mask,p,sizeof(image->write_mask));
514 p+=sizeof(image->write_mask);
515 (void) memcpy(&image->columns,p,sizeof(image->columns));
516 p+=sizeof(image->columns);
517 (void) memcpy(&image->rows,p,sizeof(image->rows));
518 p+=sizeof(image->rows);
519 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
520 p+=sizeof(image->number_channels);
521 (void) memcpy(image->channel_map,p,MaxPixelChannels*
522 sizeof(*image->channel_map));
523 p+=MaxPixelChannels*sizeof(*image->channel_map);
524 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
525 p+=sizeof(image->metacontent_extent);
526 if (SyncImagePixelCache(image,exception) == MagickFalse)
527 return(MagickFalse);
528 status=AddValueToSplayTree(registry,(const void *) session_key,image);
529 return(status);
530}
531
532static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
533 int file,const size_t session_key,ExceptionInfo *exception)
534{
535 const unsigned char
536 *metacontent;
537
538 Image
539 *image;
540
541 MagickOffsetType
542 count;
543
544 MagickSizeType
545 length;
546
547 RectangleInfo
548 region;
549
550 register const Quantum
551 *p;
552
553 register unsigned char
554 *q;
555
556 unsigned char
557 message[MagickPathExtent];
558
559 /*
560 Read distributed pixel cache metacontent.
561 */
562 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
563 if (image == (Image *) NULL)
564 return(MagickFalse);
565 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
566 sizeof(region.y)+sizeof(length);
567 count=dpc_read(file,length,message);
568 if (count != (MagickOffsetType) length)
569 return(MagickFalse);
570 q=message;
571 (void) memcpy(&region.width,q,sizeof(region.width));
572 q+=sizeof(region.width);
573 (void) memcpy(&region.height,q,sizeof(region.height));
574 q+=sizeof(region.height);
575 (void) memcpy(&region.x,q,sizeof(region.x));
576 q+=sizeof(region.x);
577 (void) memcpy(&region.y,q,sizeof(region.y));
578 q+=sizeof(region.y);
579 (void) memcpy(&length,q,sizeof(length));
580 q+=sizeof(length);
581 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
582 exception);
583 if (p == (const Quantum *) NULL)
584 return(MagickFalse);
585 metacontent=(const unsigned char *) GetVirtualMetacontent(image);
586 count=dpc_send(file,length,metacontent);
587 if (count != (MagickOffsetType) length)
588 return(MagickFalse);
589 return(MagickTrue);
590}
591
592static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
593 int file,const size_t session_key,ExceptionInfo *exception)
594{
595 Image
596 *image;
597
598 MagickOffsetType
599 count;
600
601 MagickSizeType
602 length;
603
604 RectangleInfo
605 region;
606
607 register const Quantum
608 *p;
609
610 register unsigned char
611 *q;
612
613 unsigned char
614 message[MagickPathExtent];
615
616 /*
617 Read distributed pixel cache pixels.
618 */
619 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
620 if (image == (Image *) NULL)
621 return(MagickFalse);
622 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
623 sizeof(region.y)+sizeof(length);
624 count=dpc_read(file,length,message);
625 if (count != (MagickOffsetType) length)
626 return(MagickFalse);
627 q=message;
628 (void) memcpy(&region.width,q,sizeof(region.width));
629 q+=sizeof(region.width);
630 (void) memcpy(&region.height,q,sizeof(region.height));
631 q+=sizeof(region.height);
632 (void) memcpy(&region.x,q,sizeof(region.x));
633 q+=sizeof(region.x);
634 (void) memcpy(&region.y,q,sizeof(region.y));
635 q+=sizeof(region.y);
636 (void) memcpy(&length,q,sizeof(length));
637 q+=sizeof(length);
638 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
639 exception);
640 if (p == (const Quantum *) NULL)
641 return(MagickFalse);
642 count=dpc_send(file,length,(unsigned char *) p);
643 if (count != (MagickOffsetType) length)
644 return(MagickFalse);
645 return(MagickTrue);
646}
647
648static void *RelinquishImageRegistry(void *image)
649{
650 return((void *) DestroyImageList((Image *) image));
651}
652
653static MagickBooleanType WriteDistributeCacheMetacontent(
654 SplayTreeInfo *registry,int file,const size_t session_key,
655 ExceptionInfo *exception)
656{
657 Image
658 *image;
659
660 MagickOffsetType
661 count;
662
663 MagickSizeType
664 length;
665
666 RectangleInfo
667 region;
668
669 register Quantum
670 *q;
671
672 register unsigned char
673 *p;
674
675 unsigned char
676 message[MagickPathExtent],
677 *metacontent;
678
679 /*
680 Write distributed pixel cache metacontent.
681 */
682 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
683 if (image == (Image *) NULL)
684 return(MagickFalse);
685 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
686 sizeof(region.y)+sizeof(length);
687 count=dpc_read(file,length,message);
688 if (count != (MagickOffsetType) length)
689 return(MagickFalse);
690 p=message;
691 (void) memcpy(&region.width,p,sizeof(region.width));
692 p+=sizeof(region.width);
693 (void) memcpy(&region.height,p,sizeof(region.height));
694 p+=sizeof(region.height);
695 (void) memcpy(&region.x,p,sizeof(region.x));
696 p+=sizeof(region.x);
697 (void) memcpy(&region.y,p,sizeof(region.y));
698 p+=sizeof(region.y);
699 (void) memcpy(&length,p,sizeof(length));
700 p+=sizeof(length);
701 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
702 exception);
703 if (q == (Quantum *) NULL)
704 return(MagickFalse);
705 metacontent=(unsigned char *) GetAuthenticMetacontent(image);
706 count=dpc_read(file,length,metacontent);
707 if (count != (MagickOffsetType) length)
708 return(MagickFalse);
709 return(SyncAuthenticPixels(image,exception));
710}
711
712static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
713 int file,const size_t session_key,ExceptionInfo *exception)
714{
715 Image
716 *image;
717
718 MagickOffsetType
719 count;
720
721 MagickSizeType
722 length;
723
724 RectangleInfo
725 region;
726
727 register Quantum
728 *q;
729
730 register unsigned char
731 *p;
732
733 unsigned char
734 message[MagickPathExtent];
735
736 /*
737 Write distributed pixel cache pixels.
738 */
739 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
740 if (image == (Image *) NULL)
741 return(MagickFalse);
742 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
743 sizeof(region.y)+sizeof(length);
744 count=dpc_read(file,length,message);
745 if (count != (MagickOffsetType) length)
746 return(MagickFalse);
747 p=message;
748 (void) memcpy(&region.width,p,sizeof(region.width));
749 p+=sizeof(region.width);
750 (void) memcpy(&region.height,p,sizeof(region.height));
751 p+=sizeof(region.height);
752 (void) memcpy(&region.x,p,sizeof(region.x));
753 p+=sizeof(region.x);
754 (void) memcpy(&region.y,p,sizeof(region.y));
755 p+=sizeof(region.y);
756 (void) memcpy(&length,p,sizeof(length));
757 p+=sizeof(length);
758 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
759 exception);
760 if (q == (Quantum *) NULL)
761 return(MagickFalse);
762 count=dpc_read(file,length,(unsigned char *) q);
763 if (count != (MagickOffsetType) length)
764 return(MagickFalse);
765 return(SyncAuthenticPixels(image,exception));
766}
767
768static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket)
769{
770 const char
771 *shared_secret;
772
773 ExceptionInfo
774 *exception;
775
776 MagickBooleanType
777 status;
778
779 MagickOffsetType
780 count;
781
782 register unsigned char
783 *p;
784
785 RandomInfo
786 *random_info;
787
788 size_t
789 key,
790 session_key;
791
792 SOCKET_TYPE
793 client_socket;
794
795 SplayTreeInfo
796 *registry;
797
798 StringInfo
799 *secret;
800
801 unsigned char
802 command,
803 session[2*MagickPathExtent];
804
805 /*
806 Distributed pixel cache client.
807 */
808 shared_secret=GetPolicyValue("shared-secret");
809 if (shared_secret == (const char *) NULL)
810 ThrowFatalException(CacheFatalError,"shared secret expected");
811 p=session;
812 (void) CopyMagickString((char *) p,shared_secret,MagickPathExtent);
813 p+=strlen(shared_secret);
814 random_info=AcquireRandomInfo();
815 secret=GetRandomKey(random_info,DPCSessionKeyLength);
816 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
817 session_key=GetMagickSignature(secret);
818 random_info=DestroyRandomInfo(random_info);
819 exception=AcquireExceptionInfo();
820 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
821 (void *(*)(void *)) NULL,RelinquishImageRegistry);
822 client_socket=(*(SOCKET_TYPE *) socket);
823 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
824 secret=DestroyStringInfo(secret);
825 for ( ; ; )
826 {
827 count=dpc_read(client_socket,1,(unsigned char *) &command);
828 if (count <= 0)
829 break;
830 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
831 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
832 break;
833 status=MagickFalse;
834 switch (command)
835 {
836 case 'o':
837 {
838 status=OpenDistributeCache(registry,client_socket,session_key,
839 exception);
840 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
841 break;
842 }
843 case 'r':
844 {
845 status=ReadDistributeCachePixels(registry,client_socket,session_key,
846 exception);
847 break;
848 }
849 case 'R':
850 {
851 status=ReadDistributeCacheMetacontent(registry,client_socket,
852 session_key,exception);
853 break;
854 }
855 case 'w':
856 {
857 status=WriteDistributeCachePixels(registry,client_socket,session_key,
858 exception);
859 break;
860 }
861 case 'W':
862 {
863 status=WriteDistributeCacheMetacontent(registry,client_socket,
864 session_key,exception);
865 break;
866 }
867 case 'd':
868 {
869 status=DestroyDistributeCache(registry,session_key);
870 break;
871 }
872 default:
873 break;
874 }
875 if (status == MagickFalse)
876 break;
877 if (command == 'd')
878 break;
879 }
880 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
881 CLOSE_SOCKET(client_socket);
882 exception=DestroyExceptionInfo(exception);
883 registry=DestroySplayTree(registry);
884 return(HANDLER_RETURN_VALUE);
885}
886
887MagickExport void DistributePixelCacheServer(const int port,
888 ExceptionInfo *exception)
889{
890#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
891 char
892 service[MagickPathExtent];
893
894 int
895 status;
896
897#if defined(MAGICKCORE_THREAD_SUPPORT)
898 pthread_attr_t
899 attributes;
900
901 pthread_t
902 threads;
903#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
904 DWORD
905 threadID;
906#else
907 Not implemented!
908#endif
909
910 register struct addrinfo
911 *p;
912
913 SOCKET_TYPE
914 server_socket;
915
916 struct addrinfo
917 hint,
918 *result;
919
920 struct sockaddr_in
921 address;
922
923 /*
924 Launch distributed pixel cache server.
925 */
926 assert(exception != (ExceptionInfo *) NULL);
927 assert(exception->signature == MagickCoreSignature);
928#if defined(MAGICKCORE_WINDOWS_SUPPORT)
929 NTInitializeWinsock(MagickFalse);
930#endif
931 (void) ResetMagickMemory(&hint,0,sizeof(hint));
932 hint.ai_family=AF_INET;
933 hint.ai_socktype=SOCK_STREAM;
934 hint.ai_flags=AI_PASSIVE;
935 (void) FormatLocaleString(service,MagickPathExtent,"%d",port);
936 status=getaddrinfo((const char *) NULL,service,&hint,&result);
937 if (status != 0)
938 ThrowFatalException(CacheFatalError,"UnableToListen");
939 server_socket=(SOCKET_TYPE) 0;
940 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
941 {
942 int
943 one;
944
945 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
946 if (server_socket == -1)
947 continue;
948 one=1;
949 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,
950 CHAR_TYPE_CAST &one,(socklen_t) sizeof(one));
951 if (status == -1)
952 {
953 CLOSE_SOCKET(server_socket);
954 continue;
955 }
956 status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
957 if (status == -1)
958 {
959 CLOSE_SOCKET(server_socket);
960 continue;
961 }
962 break;
963 }
964 if (p == (struct addrinfo *) NULL)
965 ThrowFatalException(CacheFatalError,"UnableToBind");
966 freeaddrinfo(result);
967 status=listen(server_socket,DPCPendingConnections);
968 if (status != 0)
969 ThrowFatalException(CacheFatalError,"UnableToListen");
970#if defined(MAGICKCORE_THREAD_SUPPORT)
971 pthread_attr_init(&attributes);
972#endif
973 for ( ; ; )
974 {
975 SOCKET_TYPE
976 client_socket;
977
978 socklen_t
979 length;
980
981 length=(socklen_t) sizeof(address);
982 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
983 if (client_socket == -1)
984 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
985#if defined(MAGICKCORE_THREAD_SUPPORT)
986 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
987 (void *) &client_socket);
988 if (status == -1)
989 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
990#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
991 if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0,
992 &threadID) == (HANDLE) NULL)
993 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
994#else
995 Not implemented!
996#endif
997 }
998#else
999 magick_unreferenced(port);
1000 magick_unreferenced(exception);
1001 ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn");
1002#endif
1003}
1004
1005/*
1006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1007% %
1008% %
1009% %
1010+ G e t D i s t r i b u t e C a c h e F i l e %
1011% %
1012% %
1013% %
1014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1015%
1016% GetDistributeCacheFile() returns the file associated with this
1017% DistributeCacheInfo structure.
1018%
1019% The format of the GetDistributeCacheFile method is:
1020%
1021% int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
1022%
1023% A description of each parameter follows:
1024%
1025% o server_info: the distributed cache info.
1026%
1027*/
1028MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
1029{
1030 assert(server_info != (DistributeCacheInfo *) NULL);
1031 assert(server_info->signature == MagickCoreSignature);
1032 return(server_info->file);
1033}
1034
1035/*
1036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037% %
1038% %
1039% %
1040+ G e t D i s t r i b u t e C a c h e H o s t n a m e %
1041% %
1042% %
1043% %
1044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045%
1046% GetDistributeCacheHostname() returns the hostname associated with this
1047% DistributeCacheInfo structure.
1048%
1049% The format of the GetDistributeCacheHostname method is:
1050%
1051% const char *GetDistributeCacheHostname(
1052% const DistributeCacheInfo *server_info)
1053%
1054% A description of each parameter follows:
1055%
1056% o server_info: the distributed cache info.
1057%
1058*/
1059MagickPrivate const char *GetDistributeCacheHostname(
1060 const DistributeCacheInfo *server_info)
1061{
1062 assert(server_info != (DistributeCacheInfo *) NULL);
1063 assert(server_info->signature == MagickCoreSignature);
1064 return(server_info->hostname);
1065}
1066
1067/*
1068%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069% %
1070% %
1071% %
1072+ G e t D i s t r i b u t e C a c h e P o r t %
1073% %
1074% %
1075% %
1076%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1077%
1078% GetDistributeCachePort() returns the port associated with this
1079% DistributeCacheInfo structure.
1080%
1081% The format of the GetDistributeCachePort method is:
1082%
1083% int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1084%
1085% A description of each parameter follows:
1086%
1087% o server_info: the distributed cache info.
1088%
1089*/
1090MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
1091{
1092 assert(server_info != (DistributeCacheInfo *) NULL);
1093 assert(server_info->signature == MagickCoreSignature);
1094 return(server_info->port);
1095}
1096
1097/*
1098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099% %
1100% %
1101% %
1102+ O p e n D i s t r i b u t e P i x e l C a c h e %
1103% %
1104% %
1105% %
1106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107%
1108% OpenDistributePixelCache() opens a pixel cache on a remote server.
1109%
1110% The format of the OpenDistributePixelCache method is:
1111%
1112% MagickBooleanType *OpenDistributePixelCache(
1113% DistributeCacheInfo *server_info,Image *image)
1114%
1115% A description of each parameter follows:
1116%
1117% o server_info: the distributed cache info.
1118%
1119% o image: the image.
1120%
1121*/
1122MagickPrivate MagickBooleanType OpenDistributePixelCache(
1123 DistributeCacheInfo *server_info,Image *image)
1124{
1125 MagickBooleanType
1126#ifdef __VMS
1127 status=MagickTrue;
1128#else
1129 status;
1130#endif
1131
1132 MagickOffsetType
1133 count;
1134
1135 register unsigned char
1136 *p;
1137
1138 unsigned char
1139 message[MagickPathExtent];
1140
1141 /*
1142 Open distributed pixel cache.
1143 */
1144 assert(server_info != (DistributeCacheInfo *) NULL);
1145 assert(server_info->signature == MagickCoreSignature);
1146 assert(image != (Image *) NULL);
1147 assert(image->signature == MagickCoreSignature);
1148 p=message;
1149 *p++='o'; /* open */
1150 /*
1151 Serialize image attributes (see ValidatePixelCacheMorphology()).
1152 */
1153 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1154 p+=sizeof(server_info->session_key);
1155 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1156 p+=sizeof(image->storage_class);
1157 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1158 p+=sizeof(image->colorspace);
1159 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1160 p+=sizeof(image->alpha_trait);
1161 (void) memcpy(p,&image->read_mask,sizeof(image->read_mask));
1162 p+=sizeof(image->read_mask);
1163 (void) memcpy(p,&image->write_mask,sizeof(image->write_mask));
1164 p+=sizeof(image->write_mask);
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*/
1219MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
1220 DistributeCacheInfo *server_info,const RectangleInfo *region,
1221 const MagickSizeType length,unsigned char *metacontent)
1222{
1223 MagickOffsetType
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,
dirk05d2ff72015-11-18 23:13:43 +01001279% const MagickSizeType length,unsigned char *magick_restrict pixels)
Cristy9125cd52015-09-17 20:16:13 -04001280%
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*/
1294MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1295 DistributeCacheInfo *server_info,const RectangleInfo *region,
dirk05d2ff72015-11-18 23:13:43 +01001296 const MagickSizeType length,unsigned char *magick_restrict pixels)
Cristy9125cd52015-09-17 20:16:13 -04001297{
1298 MagickOffsetType
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*/
1360MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1361 DistributeCacheInfo *server_info)
1362{
1363 MagickBooleanType
1364#ifdef __VMS
1365 status = MagickTrue;
1366#else
1367 status;
1368#endif
1369
1370 MagickOffsetType
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*/
1430MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
1431 DistributeCacheInfo *server_info,const RectangleInfo *region,
1432 const MagickSizeType length,const unsigned char *metacontent)
1433{
1434 MagickOffsetType
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,
dirk05d2ff72015-11-18 23:13:43 +01001490% const MagickSizeType length,
1491% const unsigned char *magick_restrict pixels)
Cristy9125cd52015-09-17 20:16:13 -04001492%
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*/
1506MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1507 DistributeCacheInfo *server_info,const RectangleInfo *region,
dirk05d2ff72015-11-18 23:13:43 +01001508 const MagickSizeType length,const unsigned char *magick_restrict pixels)
Cristy9125cd52015-09-17 20:16:13 -04001509{
1510 MagickOffsetType
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}