blob: e65a90825e7b722a71d4a01e84b1176f8c49049b [file] [log] [blame]
cristye80f9cb2013-01-09 01:09:31 +00001/*
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% John Cristy %
22% January 2013 %
23% %
24% %
25% Copyright 1999-2013 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
cristybb31fcd2013-01-15 20:06:37 +000044% very large images. Start up the pixel cache server on one or more machines.
cristye80f9cb2013-01-09 01:09:31 +000045% 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"
cristybb31fcd2013-01-15 20:06:37 +000055#include "MagickCore/cache.h"
56#include "MagickCore/cache-private.h"
cristy1cbaf972013-01-09 02:13:23 +000057#include "MagickCore/distribute-cache.h"
58#include "MagickCore/distribute-cache-private.h"
59#include "MagickCore/exception.h"
60#include "MagickCore/exception-private.h"
cristybb31fcd2013-01-15 20:06:37 +000061#include "MagickCore/geometry.h"
62#include "MagickCore/image.h"
cristy4b4a07e2013-01-22 17:07:56 +000063#include "MagickCore/list.h"
cristy0838a032013-01-11 02:25:29 +000064#include "MagickCore/locale_.h"
cristye80f9cb2013-01-09 01:09:31 +000065#include "MagickCore/memory_.h"
cristy8155c102013-02-06 16:39:01 +000066#include "MagickCore/nt-base-private.h"
cristy766c2f12013-01-25 02:46:26 +000067#include "MagickCore/pixel.h"
cristybb31fcd2013-01-15 20:06:37 +000068#include "MagickCore/policy.h"
69#include "MagickCore/random_.h"
cristy7edca2b2013-01-10 01:55:05 +000070#include "MagickCore/registry.h"
cristye34745c2013-01-16 02:27:04 +000071#include "MagickCore/splay-tree.h"
cristy0838a032013-01-11 02:25:29 +000072#include "MagickCore/string_.h"
cristybb31fcd2013-01-15 20:06:37 +000073#include "MagickCore/string-private.h"
cristy8cca92e2013-01-23 21:00:51 +000074#include "MagickCore/version.h"
cristya371edf2013-02-06 13:42:17 +000075#include "MagickCore/version-private.h"
cristy80b95012013-04-23 16:29:17 +000076#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_HAVE_PTHREAD)
cristybb31fcd2013-01-15 20:06:37 +000077#include <netinet/in.h>
cristy0838a032013-01-11 02:25:29 +000078#include <netdb.h>
cristybb31fcd2013-01-15 20:06:37 +000079#include <sys/socket.h>
80#include <arpa/inet.h>
cristy9d570f02013-03-31 01:08:49 +000081#else
82#undef send
83#undef recv
84#define send(file,buffer,length,flags) 0
85#define recv(file,buffer,length,flags) 0
cristye80f9cb2013-01-09 01:09:31 +000086#endif
87
88/*
cristybb31fcd2013-01-15 20:06:37 +000089 Define declarations.
90*/
91#define DPCHostname "127.0.0.1"
cristyb9120722013-01-20 17:20:50 +000092#define DPCPendingConnections 10
cristybb31fcd2013-01-15 20:06:37 +000093#define DPCPort 6668
94#define DPCSessionKeyLength 8
cristy7fc1b852013-01-27 16:47:26 +000095#ifndef MSG_NOSIGNAL
96# define MSG_NOSIGNAL 0
97#endif
cristybb31fcd2013-01-15 20:06:37 +000098
99/*
cristye80f9cb2013-01-09 01:09:31 +0000100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
cristy43940f42013-01-17 00:24:06 +0000104+ 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 %
cristy1cbaf972013-01-09 02:13:23 +0000105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
110% AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure.
111%
112% The format of the AcquireDistributeCacheInfo method is:
113%
cristy7edca2b2013-01-10 01:55:05 +0000114% DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception)
115%
116% A description of each parameter follows:
117%
118% o exception: return any errors or warnings in this structure.
cristy1cbaf972013-01-09 02:13:23 +0000119%
120*/
cristybb31fcd2013-01-15 20:06:37 +0000121
cristyb9120722013-01-20 17:20:50 +0000122static inline MagickSizeType MagickMin(const MagickSizeType x,
123 const MagickSizeType y)
124{
125 if (x < y)
126 return(x);
127 return(y);
128}
129
130static inline MagickOffsetType dpc_read(int file,const MagickSizeType length,
131 unsigned char *restrict message)
132{
cristy3c928042013-01-26 00:11:04 +0000133 register MagickOffsetType
134 i;
135
136 ssize_t
cristyb9120722013-01-20 17:20:50 +0000137 count;
138
cristy3c928042013-01-26 00:11:04 +0000139 count=0;
140 for (i=0; i < (MagickOffsetType) length; i+=count)
141 {
142 count=recv(file,message+i,(size_t) MagickMin(length-i,(MagickSizeType)
143 SSIZE_MAX),0);
144 if (count <= 0)
145 {
146 count=0;
147 if (errno != EINTR)
148 break;
149 }
150 }
151 return(i);
cristyb9120722013-01-20 17:20:50 +0000152}
153
cristybb31fcd2013-01-15 20:06:37 +0000154static int ConnectPixelCacheServer(const char *hostname,const int port,
cristy2330a752013-01-28 13:19:51 +0000155 size_t *session_key,ExceptionInfo *exception)
cristybb31fcd2013-01-15 20:06:37 +0000156{
cristy80b95012013-04-23 16:29:17 +0000157#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_HAVE_PTHREAD)
cristybb31fcd2013-01-15 20:06:37 +0000158 char
cristyb9120722013-01-20 17:20:50 +0000159 service[MaxTextExtent];
cristybb31fcd2013-01-15 20:06:37 +0000160
161 const char
162 *shared_secret;
163
164 int
165 client_socket,
166 status;
167
cristy90b10932013-01-28 13:26:57 +0000168 ssize_t
cristy5067ec22013-01-27 23:35:56 +0000169 count;
170
cristyb9120722013-01-20 17:20:50 +0000171 struct addrinfo
172 hint,
173 *result;
cristybb31fcd2013-01-15 20:06:37 +0000174
175 unsigned char
cristy410133d2013-02-05 20:06:52 +0000176 secret[MaxTextExtent];
cristybb31fcd2013-01-15 20:06:37 +0000177
178 /*
179 Connect to distributed pixel cache and get session key.
180 */
181 *session_key=0;
182 shared_secret=GetPolicyValue("shared-secret");
183 if (shared_secret == (const char *) NULL)
184 {
185 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
186 "DistributedPixelCache","'%s'","shared secret expected");
187 return(-1);
188 }
cristyb9120722013-01-20 17:20:50 +0000189 (void) ResetMagickMemory(&hint,0,sizeof(hint));
190 hint.ai_family=AF_INET;
191 hint.ai_socktype=SOCK_STREAM;
192 hint.ai_flags=AI_PASSIVE;
193 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
194 status=getaddrinfo(hostname,service,&hint,&result);
195 if (status != 0)
196 {
197 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
198 "DistributedPixelCache","'%s'",hostname);
199 return(-1);
200 }
201 client_socket=socket(result->ai_family,result->ai_socktype,
202 result->ai_protocol);
cristybb31fcd2013-01-15 20:06:37 +0000203 if (client_socket == -1)
204 {
205 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
206 "DistributedPixelCache","'%s'",hostname);
207 return(-1);
208 }
cristyb9120722013-01-20 17:20:50 +0000209 status=connect(client_socket,result->ai_addr,result->ai_addrlen);
cristybb31fcd2013-01-15 20:06:37 +0000210 if (status == -1)
211 {
212 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
213 "DistributedPixelCache","'%s'",hostname);
214 return(-1);
215 }
cristy3c928042013-01-26 00:11:04 +0000216 count=recv(client_socket,secret,MaxTextExtent,0);
cristybb31fcd2013-01-15 20:06:37 +0000217 if (count != -1)
218 {
cristy410133d2013-02-05 20:06:52 +0000219 StringInfo
220 *nonce;
cristyc6c76842013-01-23 18:32:26 +0000221
cristy410133d2013-02-05 20:06:52 +0000222 nonce=AcquireStringInfo(count);
223 (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count);
224 *session_key=GetMagickSignature(nonce);
225 nonce=DestroyStringInfo(nonce);
cristybb31fcd2013-01-15 20:06:37 +0000226 }
227 if (*session_key == 0)
228 {
229 close(client_socket);
230 client_socket=(-1);
231 }
232 return(client_socket);
233#else
234 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
235 "DelegateLibrarySupportNotBuiltIn","distributed pixel cache");
236 return(MagickFalse);
237#endif
238}
239
240static char *GetHostname(int *port,ExceptionInfo *exception)
241{
242 char
243 *host,
244 *hosts,
245 **hostlist;
246
247 int
248 argc;
249
250 register ssize_t
251 i;
252
253 static size_t
254 id = 0;
255
256 /*
257 Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668).
258 */
259 hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",
260 exception);
261 if (hosts == (char *) NULL)
262 {
263 *port=DPCPort;
264 return(AcquireString(DPCHostname));
265 }
266 (void) SubstituteString(&hosts,","," ");
267 hostlist=StringToArgv(hosts,&argc);
268 hosts=DestroyString(hosts);
269 if (hostlist == (char **) NULL)
270 {
271 *port=DPCPort;
272 return(AcquireString(DPCHostname));
273 }
274 hosts=AcquireString(hostlist[(id++ % (argc-1))+1]);
275 for (i=0; i < (ssize_t) argc; i++)
276 hostlist[i]=DestroyString(hostlist[i]);
277 hostlist=(char **) RelinquishMagickMemory(hostlist);
278 (void) SubstituteString(&hosts,":"," ");
279 hostlist=StringToArgv(hosts,&argc);
280 if (hostlist == (char **) NULL)
281 {
282 *port=DPCPort;
283 return(AcquireString(DPCHostname));
284 }
285 host=AcquireString(hostlist[1]);
286 if (hostlist[2] == (char *) NULL)
287 *port=DPCPort;
288 else
289 *port=StringToLong(hostlist[2]);
290 for (i=0; i < (ssize_t) argc; i++)
291 hostlist[i]=DestroyString(hostlist[i]);
292 hostlist=(char **) RelinquishMagickMemory(hostlist);
293 return(host);
294}
295
cristy7edca2b2013-01-10 01:55:05 +0000296MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo(
297 ExceptionInfo *exception)
cristy1cbaf972013-01-09 02:13:23 +0000298{
cristybb31fcd2013-01-15 20:06:37 +0000299 char
300 *hostname;
301
cristy1cbaf972013-01-09 02:13:23 +0000302 DistributeCacheInfo
cristyd9fdd232013-01-19 00:14:59 +0000303 *server_info;
cristy1cbaf972013-01-09 02:13:23 +0000304
cristy2330a752013-01-28 13:19:51 +0000305 size_t
cristybb31fcd2013-01-15 20:06:37 +0000306 session_key;
307
cristyfeb21672013-01-23 00:12:55 +0000308 /*
309 Connect to the distributed pixel cache server.
310 */
cristyd9fdd232013-01-19 00:14:59 +0000311 server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info));
312 if (server_info == (DistributeCacheInfo *) NULL)
cristy1cbaf972013-01-09 02:13:23 +0000313 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristyd9fdd232013-01-19 00:14:59 +0000314 (void) ResetMagickMemory(server_info,0,sizeof(*server_info));
315 server_info->signature=MagickSignature;
cristyd9fdd232013-01-19 00:14:59 +0000316 server_info->port=0;
317 hostname=GetHostname(&server_info->port,exception);
cristybb31fcd2013-01-15 20:06:37 +0000318 session_key=0;
cristyd9fdd232013-01-19 00:14:59 +0000319 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
320 &session_key,exception);
321 server_info->session_key=session_key;
322 (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent);
cristybb31fcd2013-01-15 20:06:37 +0000323 hostname=DestroyString(hostname);
cristyd9fdd232013-01-19 00:14:59 +0000324 if (server_info->file == -1)
325 server_info=DestroyDistributeCacheInfo(server_info);
326 return(server_info);
cristy1cbaf972013-01-09 02:13:23 +0000327}
328
329/*
330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331% %
332% %
333% %
cristy43940f42013-01-17 00:24:06 +0000334+ 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 %
cristy1cbaf972013-01-09 02:13:23 +0000335% %
336% %
337% %
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339%
340% DestroyDistributeCacheInfo() deallocates memory associated with an
341% DistributeCacheInfo structure.
342%
343% The format of the DestroyDistributeCacheInfo method is:
344%
345% DistributeCacheInfo *DestroyDistributeCacheInfo(
cristyd9fdd232013-01-19 00:14:59 +0000346% DistributeCacheInfo *server_info)
cristy1cbaf972013-01-09 02:13:23 +0000347%
348% A description of each parameter follows:
349%
cristyd9fdd232013-01-19 00:14:59 +0000350% o server_info: the distributed cache info.
cristy1cbaf972013-01-09 02:13:23 +0000351%
352*/
353MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo(
cristyd9fdd232013-01-19 00:14:59 +0000354 DistributeCacheInfo *server_info)
cristy1cbaf972013-01-09 02:13:23 +0000355{
cristyd9fdd232013-01-19 00:14:59 +0000356 assert(server_info != (DistributeCacheInfo *) NULL);
357 assert(server_info->signature == MagickSignature);
cristy066c4fb2013-01-19 02:36:14 +0000358 if (server_info->file > 0)
359 (void) close(server_info->file);
cristyd9fdd232013-01-19 00:14:59 +0000360 server_info->signature=(~MagickSignature);
361 server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info);
362 return(server_info);
cristy1cbaf972013-01-09 02:13:23 +0000363}
364
365/*
366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367% %
368% %
369% %
cristybb31fcd2013-01-15 20:06:37 +0000370+ 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 %
cristye80f9cb2013-01-09 01:09:31 +0000371% %
372% %
373% %
374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375%
cristybb31fcd2013-01-15 20:06:37 +0000376% DistributePixelCacheServer() waits on the specified port for commands to
377% create, read, update, or destroy a pixel cache.
cristye80f9cb2013-01-09 01:09:31 +0000378%
cristybb31fcd2013-01-15 20:06:37 +0000379% The format of the DistributePixelCacheServer() method is:
cristye80f9cb2013-01-09 01:09:31 +0000380%
cristyb9120722013-01-20 17:20:50 +0000381% void DistributePixelCacheServer(const int port)
cristye80f9cb2013-01-09 01:09:31 +0000382%
383% A description of each parameter follows:
384%
385% o port: connect the distributed pixel cache at this port.
386%
cristy7675e602013-01-11 12:14:51 +0000387% o exception: return any errors or warnings in this structure.
388%
cristye80f9cb2013-01-09 01:09:31 +0000389*/
cristybb31fcd2013-01-15 20:06:37 +0000390
cristy066c4fb2013-01-19 02:36:14 +0000391static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry,
cristy2330a752013-01-28 13:19:51 +0000392 int file,const size_t session_key)
cristy9c3f05b2013-01-17 18:51:14 +0000393{
cristyfeb21672013-01-23 00:12:55 +0000394 /*
395 Destroy distributed pixel cache.
396 */
cristyb0de93f2013-05-03 13:39:25 +0000397 (void) file;
cristy066c4fb2013-01-19 02:36:14 +0000398 return(DeleteNodeFromSplayTree(registry,(const void *) session_key));
cristy9c3f05b2013-01-17 18:51:14 +0000399}
400
cristyb9120722013-01-20 17:20:50 +0000401static inline MagickOffsetType dpc_send(int file,const MagickSizeType length,
cristyfc7a24a2013-01-22 17:38:31 +0000402 const unsigned char *restrict message)
cristyb9120722013-01-20 17:20:50 +0000403{
404 MagickOffsetType
405 count;
406
407 register MagickOffsetType
408 i;
409
cristyfeb21672013-01-23 00:12:55 +0000410 /*
411 Ensure a complete message is sent.
412 */
cristyb9120722013-01-20 17:20:50 +0000413 count=0;
414 for (i=0; i < (MagickOffsetType) length; i+=count)
415 {
cristyfc7a24a2013-01-22 17:38:31 +0000416 count=(MagickOffsetType) send(file,message+i,(size_t) MagickMin(length-i,
cristybe5d52d2013-01-25 19:40:42 +0000417 (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL);
cristyb9120722013-01-20 17:20:50 +0000418 if (count <= 0)
419 {
420 count=0;
421 if (errno != EINTR)
422 break;
423 }
424 }
425 return(i);
426}
427
cristy066c4fb2013-01-19 02:36:14 +0000428static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
cristy2330a752013-01-28 13:19:51 +0000429 int file,const size_t session_key,ExceptionInfo *exception)
cristye80f9cb2013-01-09 01:09:31 +0000430{
cristybb31fcd2013-01-15 20:06:37 +0000431 Image
432 *image;
433
434 MagickBooleanType
cristye80f9cb2013-01-09 01:09:31 +0000435 status;
436
cristyb9120722013-01-20 17:20:50 +0000437 MagickOffsetType
438 count;
439
440 MagickSizeType
441 length;
442
cristyce9db092013-01-16 22:16:51 +0000443 register unsigned char
444 *p;
445
cristyce9db092013-01-16 22:16:51 +0000446 unsigned char
cristyb9120722013-01-20 17:20:50 +0000447 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +0000448
cristyfeb21672013-01-23 00:12:55 +0000449 /*
450 Open distributed pixel cache.
451 */
cristybb31fcd2013-01-15 20:06:37 +0000452 image=AcquireImage((ImageInfo *) NULL,exception);
cristye27c1962013-01-17 20:16:29 +0000453 if (image == (Image *) NULL)
454 return(MagickFalse);
cristy766c2f12013-01-25 02:46:26 +0000455 length=sizeof(image->storage_class)+sizeof(image->colorspace)+
cristy883fde12013-04-08 00:50:13 +0000456 sizeof(image->alpha_trait)+sizeof(image->read_mask)+
457 sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+
458 sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+
459 sizeof(image->metacontent_extent);
cristyb9120722013-01-20 17:20:50 +0000460 count=dpc_read(file,length,message);
461 if (count != (MagickOffsetType) length)
cristybb31fcd2013-01-15 20:06:37 +0000462 return(MagickFalse);
cristy766c2f12013-01-25 02:46:26 +0000463 /*
cristy90b10932013-01-28 13:26:57 +0000464 Deserialize the image attributes.
cristy766c2f12013-01-25 02:46:26 +0000465 */
cristyb9120722013-01-20 17:20:50 +0000466 p=message;
cristy766c2f12013-01-25 02:46:26 +0000467 (void) memcpy(&image->storage_class,p,sizeof(image->storage_class));
468 p+=sizeof(image->storage_class);
469 (void) memcpy(&image->colorspace,p,sizeof(image->colorspace));
470 p+=sizeof(image->colorspace);
471 (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait));
472 p+=sizeof(image->alpha_trait);
cristy883fde12013-04-08 00:50:13 +0000473 (void) memcpy(&image->read_mask,p,sizeof(image->read_mask));
474 p+=sizeof(image->read_mask);
475 (void) memcpy(&image->write_mask,p,sizeof(image->write_mask));
476 p+=sizeof(image->write_mask);
cristyce9db092013-01-16 22:16:51 +0000477 (void) memcpy(&image->columns,p,sizeof(image->columns));
478 p+=sizeof(image->columns);
479 (void) memcpy(&image->rows,p,sizeof(image->rows));
480 p+=sizeof(image->rows);
481 (void) memcpy(&image->number_channels,p,sizeof(image->number_channels));
482 p+=sizeof(image->number_channels);
cristy766c2f12013-01-25 02:46:26 +0000483 (void) memcpy(image->channel_map,p,MaxPixelChannels*
484 sizeof(*image->channel_map));
485 p+=MaxPixelChannels*sizeof(*image->channel_map);
486 (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent));
487 p+=sizeof(image->metacontent_extent);
cristy6c3bc852013-01-26 13:00:45 +0000488 if (SyncImagePixelCache(image,exception) == MagickFalse)
489 return(MagickFalse);
cristy066c4fb2013-01-19 02:36:14 +0000490 status=AddValueToSplayTree(registry,(const void *) session_key,image);
cristybb31fcd2013-01-15 20:06:37 +0000491 return(status);
492}
493
cristy066c4fb2013-01-19 02:36:14 +0000494static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
cristy2330a752013-01-28 13:19:51 +0000495 int file,const size_t session_key,ExceptionInfo *exception)
cristybb31fcd2013-01-15 20:06:37 +0000496{
cristyb54f26e2013-01-17 01:44:39 +0000497 const unsigned char
498 *metacontent;
499
cristybb31fcd2013-01-15 20:06:37 +0000500 Image
501 *image;
502
cristyb9120722013-01-20 17:20:50 +0000503 MagickOffsetType
504 count;
505
506 MagickSizeType
507 length;
508
cristybb31fcd2013-01-15 20:06:37 +0000509 RectangleInfo
510 region;
511
512 register const Quantum
513 *p;
514
cristyce9db092013-01-16 22:16:51 +0000515 register unsigned char
516 *q;
517
cristyce9db092013-01-16 22:16:51 +0000518 unsigned char
cristyb9120722013-01-20 17:20:50 +0000519 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +0000520
cristyfeb21672013-01-23 00:12:55 +0000521 /*
522 Read distributed pixel cache metacontent.
523 */
cristy066c4fb2013-01-19 02:36:14 +0000524 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
cristybb31fcd2013-01-15 20:06:37 +0000525 if (image == (Image *) NULL)
526 return(MagickFalse);
cristyce9db092013-01-16 22:16:51 +0000527 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
528 sizeof(region.y)+sizeof(length);
cristyb9120722013-01-20 17:20:50 +0000529 count=dpc_read(file,length,message);
530 if (count != (MagickOffsetType) length)
cristybb31fcd2013-01-15 20:06:37 +0000531 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000532 q=message;
cristyce9db092013-01-16 22:16:51 +0000533 (void) memcpy(&region.width,q,sizeof(region.width));
534 q+=sizeof(region.width);
535 (void) memcpy(&region.height,q,sizeof(region.height));
cristyffcb6012013-01-26 02:16:19 +0000536 q+=sizeof(region.height);
cristyce9db092013-01-16 22:16:51 +0000537 (void) memcpy(&region.x,q,sizeof(region.x));
cristyffcb6012013-01-26 02:16:19 +0000538 q+=sizeof(region.x);
cristyce9db092013-01-16 22:16:51 +0000539 (void) memcpy(&region.y,q,sizeof(region.y));
cristyffcb6012013-01-26 02:16:19 +0000540 q+=sizeof(region.y);
cristyce9db092013-01-16 22:16:51 +0000541 (void) memcpy(&length,q,sizeof(length));
542 q+=sizeof(length);
cristybb31fcd2013-01-15 20:06:37 +0000543 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
544 exception);
cristye34745c2013-01-16 02:27:04 +0000545 if (p == (const Quantum *) NULL)
cristybb31fcd2013-01-15 20:06:37 +0000546 return(MagickFalse);
cristy6d501702013-02-08 13:55:27 +0000547 metacontent=(const unsigned char *) GetVirtualMetacontent(image);
cristyb9120722013-01-20 17:20:50 +0000548 count=dpc_send(file,length,metacontent);
549 if (count != (MagickOffsetType) length)
cristybb31fcd2013-01-15 20:06:37 +0000550 return(MagickFalse);
551 return(MagickTrue);
552}
cristye80f9cb2013-01-09 01:09:31 +0000553
cristy066c4fb2013-01-19 02:36:14 +0000554static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
cristy2330a752013-01-28 13:19:51 +0000555 int file,const size_t session_key,ExceptionInfo *exception)
cristyce9db092013-01-16 22:16:51 +0000556{
cristyce9db092013-01-16 22:16:51 +0000557 Image
558 *image;
559
cristyb9120722013-01-20 17:20:50 +0000560 MagickOffsetType
561 count;
562
563 MagickSizeType
564 length;
565
cristyce9db092013-01-16 22:16:51 +0000566 RectangleInfo
567 region;
568
569 register const Quantum
570 *p;
571
572 register unsigned char
573 *q;
574
cristyce9db092013-01-16 22:16:51 +0000575 unsigned char
cristyb9120722013-01-20 17:20:50 +0000576 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +0000577
cristyfeb21672013-01-23 00:12:55 +0000578 /*
579 Read distributed pixel cache pixels.
580 */
cristy066c4fb2013-01-19 02:36:14 +0000581 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
cristyce9db092013-01-16 22:16:51 +0000582 if (image == (Image *) NULL)
583 return(MagickFalse);
584 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
585 sizeof(region.y)+sizeof(length);
cristyb9120722013-01-20 17:20:50 +0000586 count=dpc_read(file,length,message);
587 if (count != (MagickOffsetType) length)
cristyce9db092013-01-16 22:16:51 +0000588 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000589 q=message;
cristyce9db092013-01-16 22:16:51 +0000590 (void) memcpy(&region.width,q,sizeof(region.width));
591 q+=sizeof(region.width);
592 (void) memcpy(&region.height,q,sizeof(region.height));
cristyffcb6012013-01-26 02:16:19 +0000593 q+=sizeof(region.height);
cristyce9db092013-01-16 22:16:51 +0000594 (void) memcpy(&region.x,q,sizeof(region.x));
cristyffcb6012013-01-26 02:16:19 +0000595 q+=sizeof(region.x);
cristyce9db092013-01-16 22:16:51 +0000596 (void) memcpy(&region.y,q,sizeof(region.y));
cristyffcb6012013-01-26 02:16:19 +0000597 q+=sizeof(region.y);
cristyce9db092013-01-16 22:16:51 +0000598 (void) memcpy(&length,q,sizeof(length));
599 q+=sizeof(length);
cristyce9db092013-01-16 22:16:51 +0000600 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
601 exception);
cristyce9db092013-01-16 22:16:51 +0000602 if (p == (const Quantum *) NULL)
603 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000604 count=dpc_send(file,length,(unsigned char *) p);
605 if (count != (MagickOffsetType) length)
cristyce9db092013-01-16 22:16:51 +0000606 return(MagickFalse);
607 return(MagickTrue);
608}
609
cristy4b4a07e2013-01-22 17:07:56 +0000610static void *RelinquishImageRegistry(void *image)
611{
612 return((void *) DestroyImageList((Image *) image));
613}
614
cristyce9db092013-01-16 22:16:51 +0000615static MagickBooleanType WriteDistributeCacheMetacontent(
cristy2330a752013-01-28 13:19:51 +0000616 SplayTreeInfo *registry,int file,const size_t session_key,
cristy81aa8492013-01-18 19:12:43 +0000617 ExceptionInfo *exception)
cristybb31fcd2013-01-15 20:06:37 +0000618{
cristybb31fcd2013-01-15 20:06:37 +0000619 Image
620 *image;
621
cristyb9120722013-01-20 17:20:50 +0000622 MagickOffsetType
623 count;
624
625 MagickSizeType
626 length;
627
cristybb31fcd2013-01-15 20:06:37 +0000628 RectangleInfo
629 region;
630
631 register Quantum
cristyce9db092013-01-16 22:16:51 +0000632 *q;
633
634 register unsigned char
cristybb31fcd2013-01-15 20:06:37 +0000635 *p;
636
cristyce9db092013-01-16 22:16:51 +0000637 unsigned char
cristyb9120722013-01-20 17:20:50 +0000638 message[MaxTextExtent],
cristyb54f26e2013-01-17 01:44:39 +0000639 *metacontent;
cristyce9db092013-01-16 22:16:51 +0000640
cristyfeb21672013-01-23 00:12:55 +0000641 /*
642 Write distributed pixel cache metacontent.
643 */
644 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
cristybb31fcd2013-01-15 20:06:37 +0000645 if (image == (Image *) NULL)
646 return(MagickFalse);
cristyce9db092013-01-16 22:16:51 +0000647 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
648 sizeof(region.y)+sizeof(length);
cristyb9120722013-01-20 17:20:50 +0000649 count=dpc_read(file,length,message);
650 if (count != (MagickOffsetType) length)
cristybb31fcd2013-01-15 20:06:37 +0000651 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000652 p=message;
cristyce9db092013-01-16 22:16:51 +0000653 (void) memcpy(&region.width,p,sizeof(region.width));
654 p+=sizeof(region.width);
655 (void) memcpy(&region.height,p,sizeof(region.height));
cristyffcb6012013-01-26 02:16:19 +0000656 p+=sizeof(region.height);
cristyce9db092013-01-16 22:16:51 +0000657 (void) memcpy(&region.x,p,sizeof(region.x));
cristyffcb6012013-01-26 02:16:19 +0000658 p+=sizeof(region.x);
cristyce9db092013-01-16 22:16:51 +0000659 (void) memcpy(&region.y,p,sizeof(region.y));
cristyffcb6012013-01-26 02:16:19 +0000660 p+=sizeof(region.y);
cristyce9db092013-01-16 22:16:51 +0000661 (void) memcpy(&length,p,sizeof(length));
662 p+=sizeof(length);
cristyce9db092013-01-16 22:16:51 +0000663 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
cristybb31fcd2013-01-15 20:06:37 +0000664 exception);
cristyce9db092013-01-16 22:16:51 +0000665 if (q == (Quantum *) NULL)
cristybb31fcd2013-01-15 20:06:37 +0000666 return(MagickFalse);
cristy6d501702013-02-08 13:55:27 +0000667 metacontent=(unsigned char *) GetAuthenticMetacontent(image);
cristyb9120722013-01-20 17:20:50 +0000668 count=dpc_read(file,length,metacontent);
669 if (count != (MagickOffsetType) length)
cristyce9db092013-01-16 22:16:51 +0000670 return(MagickFalse);
cristy7708b0b2013-01-26 03:03:29 +0000671 return(SyncAuthenticPixels(image,exception));
cristyce9db092013-01-16 22:16:51 +0000672}
673
cristy066c4fb2013-01-19 02:36:14 +0000674static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
cristy2330a752013-01-28 13:19:51 +0000675 int file,const size_t session_key,ExceptionInfo *exception)
cristyce9db092013-01-16 22:16:51 +0000676{
cristyce9db092013-01-16 22:16:51 +0000677 Image
678 *image;
679
cristyb9120722013-01-20 17:20:50 +0000680 MagickOffsetType
681 count;
682
683 MagickSizeType
684 length;
685
cristyce9db092013-01-16 22:16:51 +0000686 RectangleInfo
687 region;
688
689 register Quantum
690 *q;
691
692 register unsigned char
693 *p;
694
cristyce9db092013-01-16 22:16:51 +0000695 unsigned char
cristyb9120722013-01-20 17:20:50 +0000696 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +0000697
cristyfeb21672013-01-23 00:12:55 +0000698 /*
699 Write distributed pixel cache pixels.
700 */
cristy066c4fb2013-01-19 02:36:14 +0000701 image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key);
cristyce9db092013-01-16 22:16:51 +0000702 if (image == (Image *) NULL)
703 return(MagickFalse);
704 length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
705 sizeof(region.y)+sizeof(length);
cristyb9120722013-01-20 17:20:50 +0000706 count=dpc_read(file,length,message);
707 if (count != (MagickOffsetType) length)
cristyce9db092013-01-16 22:16:51 +0000708 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000709 p=message;
cristyce9db092013-01-16 22:16:51 +0000710 (void) memcpy(&region.width,p,sizeof(region.width));
711 p+=sizeof(region.width);
712 (void) memcpy(&region.height,p,sizeof(region.height));
cristyffcb6012013-01-26 02:16:19 +0000713 p+=sizeof(region.height);
cristyce9db092013-01-16 22:16:51 +0000714 (void) memcpy(&region.x,p,sizeof(region.x));
cristyffcb6012013-01-26 02:16:19 +0000715 p+=sizeof(region.x);
cristyce9db092013-01-16 22:16:51 +0000716 (void) memcpy(&region.y,p,sizeof(region.y));
cristyffcb6012013-01-26 02:16:19 +0000717 p+=sizeof(region.y);
cristyce9db092013-01-16 22:16:51 +0000718 (void) memcpy(&length,p,sizeof(length));
719 p+=sizeof(length);
cristyce9db092013-01-16 22:16:51 +0000720 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
721 exception);
cristyce9db092013-01-16 22:16:51 +0000722 if (q == (Quantum *) NULL)
723 return(MagickFalse);
cristyb9120722013-01-20 17:20:50 +0000724 count=dpc_read(file,length,(unsigned char *) q);
725 if (count != (MagickOffsetType) length)
cristybb31fcd2013-01-15 20:06:37 +0000726 return(MagickFalse);
cristy7708b0b2013-01-26 03:03:29 +0000727 return(SyncAuthenticPixels(image,exception));
cristybb31fcd2013-01-15 20:06:37 +0000728}
729
cristy81aa8492013-01-18 19:12:43 +0000730static void *DistributePixelCacheClient(void *socket)
cristybb31fcd2013-01-15 20:06:37 +0000731{
732 const char
733 *shared_secret;
734
cristy81aa8492013-01-18 19:12:43 +0000735 ExceptionInfo
736 *exception;
737
cristybb31fcd2013-01-15 20:06:37 +0000738 int
cristye34745c2013-01-16 02:27:04 +0000739 client_socket;
740
741 MagickBooleanType
cristybb31fcd2013-01-15 20:06:37 +0000742 status;
743
cristyb9120722013-01-20 17:20:50 +0000744 MagickOffsetType
745 count;
746
cristyc6c76842013-01-23 18:32:26 +0000747 register unsigned char
748 *p;
749
cristybb31fcd2013-01-15 20:06:37 +0000750 RandomInfo
751 *random_info;
752
cristy2330a752013-01-28 13:19:51 +0000753 size_t
754 key,
cristy410133d2013-02-05 20:06:52 +0000755 session_key;
cristy2330a752013-01-28 13:19:51 +0000756
cristye34745c2013-01-16 02:27:04 +0000757 SplayTreeInfo
cristy066c4fb2013-01-19 02:36:14 +0000758 *registry;
cristye34745c2013-01-16 02:27:04 +0000759
cristybb31fcd2013-01-15 20:06:37 +0000760 StringInfo
761 *secret;
762
763 unsigned char
764 command,
cristyc6c76842013-01-23 18:32:26 +0000765 session[2*MaxTextExtent];
cristybb31fcd2013-01-15 20:06:37 +0000766
767 /*
cristyfeb21672013-01-23 00:12:55 +0000768 Distributed pixel cache client.
cristybb31fcd2013-01-15 20:06:37 +0000769 */
770 shared_secret=GetPolicyValue("shared-secret");
771 if (shared_secret == (const char *) NULL)
772 ThrowFatalException(CacheFatalError,"shared secret expected");
cristyc6c76842013-01-23 18:32:26 +0000773 p=session;
774 (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent);
775 p+=strlen(shared_secret);
cristybb31fcd2013-01-15 20:06:37 +0000776 random_info=AcquireRandomInfo();
777 secret=GetRandomKey(random_info,DPCSessionKeyLength);
cristyc6c76842013-01-23 18:32:26 +0000778 (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength);
cristy410133d2013-02-05 20:06:52 +0000779 session_key=GetMagickSignature(secret);
cristybb31fcd2013-01-15 20:06:37 +0000780 random_info=DestroyRandomInfo(random_info);
cristy81aa8492013-01-18 19:12:43 +0000781 exception=AcquireExceptionInfo();
cristy066c4fb2013-01-19 02:36:14 +0000782 registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
cristy4b4a07e2013-01-22 17:07:56 +0000783 (void *(*)(void *)) NULL,RelinquishImageRegistry);
cristy81aa8492013-01-18 19:12:43 +0000784 client_socket=(*(int *) socket);
cristyb9120722013-01-20 17:20:50 +0000785 count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret));
cristybb31fcd2013-01-15 20:06:37 +0000786 secret=DestroyStringInfo(secret);
cristye80f9cb2013-01-09 01:09:31 +0000787 for ( ; ; )
788 {
cristyb9120722013-01-20 17:20:50 +0000789 count=dpc_read(client_socket,1,(unsigned char *) &command);
cristybb31fcd2013-01-15 20:06:37 +0000790 if (count <= 0)
791 break;
cristyb9120722013-01-20 17:20:50 +0000792 count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
cristyc6c76842013-01-23 18:32:26 +0000793 if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
cristybb31fcd2013-01-15 20:06:37 +0000794 break;
795 status=MagickFalse;
796 switch (command)
797 {
cristy9c3f05b2013-01-17 18:51:14 +0000798 case 'o':
cristybb31fcd2013-01-15 20:06:37 +0000799 {
cristy066c4fb2013-01-19 02:36:14 +0000800 status=OpenDistributeCache(registry,client_socket,session_key,
cristy81aa8492013-01-18 19:12:43 +0000801 exception);
cristy8cca92e2013-01-23 21:00:51 +0000802 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
cristybb31fcd2013-01-15 20:06:37 +0000803 break;
804 }
805 case 'r':
806 {
cristy066c4fb2013-01-19 02:36:14 +0000807 status=ReadDistributeCachePixels(registry,client_socket,session_key,
808 exception);
cristybb31fcd2013-01-15 20:06:37 +0000809 break;
810 }
cristy9c3f05b2013-01-17 18:51:14 +0000811 case 'R':
812 {
cristy066c4fb2013-01-19 02:36:14 +0000813 status=ReadDistributeCacheMetacontent(registry,client_socket,
cristy81aa8492013-01-18 19:12:43 +0000814 session_key,exception);
cristy9c3f05b2013-01-17 18:51:14 +0000815 break;
816 }
817 case 'w':
cristybb31fcd2013-01-15 20:06:37 +0000818 {
cristy066c4fb2013-01-19 02:36:14 +0000819 status=WriteDistributeCachePixels(registry,client_socket,session_key,
820 exception);
cristye34745c2013-01-16 02:27:04 +0000821 break;
822 }
cristy9c3f05b2013-01-17 18:51:14 +0000823 case 'W':
824 {
cristy066c4fb2013-01-19 02:36:14 +0000825 status=WriteDistributeCacheMetacontent(registry,client_socket,
cristy81aa8492013-01-18 19:12:43 +0000826 session_key,exception);
cristy9c3f05b2013-01-17 18:51:14 +0000827 break;
828 }
cristye34745c2013-01-16 02:27:04 +0000829 case 'd':
830 {
cristy066c4fb2013-01-19 02:36:14 +0000831 status=DestroyDistributeCache(registry,client_socket,session_key);
cristybb31fcd2013-01-15 20:06:37 +0000832 break;
833 }
834 default:
835 break;
836 }
cristyfeb21672013-01-23 00:12:55 +0000837 if (status == MagickFalse)
cristybb31fcd2013-01-15 20:06:37 +0000838 break;
cristy2f0c1f92013-01-18 14:45:19 +0000839 if (command == 'd')
840 break;
cristye80f9cb2013-01-09 01:09:31 +0000841 }
cristy8cca92e2013-01-23 21:00:51 +0000842 count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status);
cristy194e8862013-01-17 01:54:39 +0000843 (void) close(client_socket);
cristy81aa8492013-01-18 19:12:43 +0000844 exception=DestroyExceptionInfo(exception);
cristy066c4fb2013-01-19 02:36:14 +0000845 registry=DestroySplayTree(registry);
cristybb31fcd2013-01-15 20:06:37 +0000846 return((void *) NULL);
847}
848
cristyb9120722013-01-20 17:20:50 +0000849MagickExport void DistributePixelCacheServer(const int port,
cristybb31fcd2013-01-15 20:06:37 +0000850 ExceptionInfo *exception)
851{
cristy80b95012013-04-23 16:29:17 +0000852#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_HAVE_PTHREAD)
cristyb9120722013-01-20 17:20:50 +0000853 char
854 service[MaxTextExtent];
855
cristybb31fcd2013-01-15 20:06:37 +0000856 int
857 server_socket,
858 status;
859
860 pthread_attr_t
861 attributes;
862
863 pthread_t
cristy81aa8492013-01-18 19:12:43 +0000864 threads;
cristybb31fcd2013-01-15 20:06:37 +0000865
cristyb9120722013-01-20 17:20:50 +0000866 register struct addrinfo
867 *p;
868
869 struct addrinfo
870 hint,
871 *result;
872
cristybb31fcd2013-01-15 20:06:37 +0000873 struct sockaddr_in
874 address;
875
876 /*
877 Launch distributed pixel cache server.
878 */
cristyb0de93f2013-05-03 13:39:25 +0000879 assert(exception != (ExceptionInfo *) NULL);
880 assert(exception->signature == MagickSignature);
cristyb9120722013-01-20 17:20:50 +0000881 (void) ResetMagickMemory(&hint,0,sizeof(hint));
882 hint.ai_family=AF_INET;
883 hint.ai_socktype=SOCK_STREAM;
884 hint.ai_flags=AI_PASSIVE;
885 (void) FormatLocaleString(service,MaxTextExtent,"%d",port);
886 status=getaddrinfo((const char *) NULL,service,&hint,&result);
cristybb31fcd2013-01-15 20:06:37 +0000887 if (status != 0)
cristyb9120722013-01-20 17:20:50 +0000888 ThrowFatalException(CacheFatalError,"UnableToListen");
cristy6be62192013-01-29 17:24:22 +0000889 server_socket=0;
cristyb9120722013-01-20 17:20:50 +0000890 for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next)
891 {
892 int
893 one;
894
895 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
896 if (server_socket == -1)
897 continue;
898 one=1;
899 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t)
900 sizeof(one));
901 if (status == -1)
902 continue;
903 status=bind(server_socket,p->ai_addr,p->ai_addrlen);
904 if (status == -1)
905 {
906 (void) close(status);
907 continue;
908 }
909 break;
910 }
911 if (p == (struct addrinfo *) NULL)
cristybb31fcd2013-01-15 20:06:37 +0000912 ThrowFatalException(CacheFatalError,"UnableToBind");
cristyb9120722013-01-20 17:20:50 +0000913 freeaddrinfo(result);
914 status=listen(server_socket,DPCPendingConnections);
cristybb31fcd2013-01-15 20:06:37 +0000915 if (status != 0)
916 ThrowFatalException(CacheFatalError,"UnableToListen");
917 pthread_attr_init(&attributes);
918 for ( ; ; )
919 {
920 int
921 client_socket;
922
923 socklen_t
924 length;
925
926 length=(socklen_t) sizeof(address);
927 client_socket=accept(server_socket,(struct sockaddr *) &address,&length);
928 if (client_socket == -1)
929 ThrowFatalException(CacheFatalError,"UnableToEstablishConnection");
cristy81aa8492013-01-18 19:12:43 +0000930 status=pthread_create(&threads,&attributes,DistributePixelCacheClient,
931 (void *) &client_socket);
cristybb31fcd2013-01-15 20:06:37 +0000932 if (status == -1)
933 ThrowFatalException(CacheFatalError,"UnableToCreateClientThread");
934 }
935 (void) close(server_socket);
cristye80f9cb2013-01-09 01:09:31 +0000936#else
cristybb31fcd2013-01-15 20:06:37 +0000937 ThrowFatalException(MissingDelegateError,"distributed pixel cache");
cristye80f9cb2013-01-09 01:09:31 +0000938#endif
939}
cristybb31fcd2013-01-15 20:06:37 +0000940
941/*
942%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943% %
944% %
945% %
cristyce9db092013-01-16 22:16:51 +0000946+ G e t D i s t r i b u t e C a c h e F i l e %
947% %
948% %
949% %
950%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951%
952% GetDistributeCacheFile() returns the file associated with this
953% DistributeCacheInfo structure.
954%
955% The format of the GetDistributeCacheFile method is:
956%
cristyd9fdd232013-01-19 00:14:59 +0000957% int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +0000958%
959% A description of each parameter follows:
960%
cristyd9fdd232013-01-19 00:14:59 +0000961% o server_info: the distributed cache info.
cristyce9db092013-01-16 22:16:51 +0000962%
963*/
cristyd9fdd232013-01-19 00:14:59 +0000964MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +0000965{
cristyd9fdd232013-01-19 00:14:59 +0000966 assert(server_info != (DistributeCacheInfo *) NULL);
967 assert(server_info->signature == MagickSignature);
968 return(server_info->file);
cristyce9db092013-01-16 22:16:51 +0000969}
970
971/*
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973% %
974% %
975% %
976+ 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 %
977% %
978% %
979% %
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981%
982% GetDistributeCacheHostname() returns the hostname associated with this
983% DistributeCacheInfo structure.
984%
985% The format of the GetDistributeCacheHostname method is:
986%
987% const char *GetDistributeCacheHostname(
cristyd9fdd232013-01-19 00:14:59 +0000988% const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +0000989%
990% A description of each parameter follows:
991%
cristyd9fdd232013-01-19 00:14:59 +0000992% o server_info: the distributed cache info.
cristyce9db092013-01-16 22:16:51 +0000993%
994*/
995MagickPrivate const char *GetDistributeCacheHostname(
cristyd9fdd232013-01-19 00:14:59 +0000996 const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +0000997{
cristyd9fdd232013-01-19 00:14:59 +0000998 assert(server_info != (DistributeCacheInfo *) NULL);
999 assert(server_info->signature == MagickSignature);
1000 return(server_info->hostname);
cristyce9db092013-01-16 22:16:51 +00001001}
1002
1003/*
1004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005% %
1006% %
1007% %
1008+ G e t D i s t r i b u t e C a c h e P o r t %
1009% %
1010% %
1011% %
1012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013%
1014% GetDistributeCachePort() returns the port associated with this
1015% DistributeCacheInfo structure.
1016%
1017% The format of the GetDistributeCachePort method is:
1018%
cristy066c4fb2013-01-19 02:36:14 +00001019% int GetDistributeCachePort(const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +00001020%
1021% A description of each parameter follows:
1022%
cristyd9fdd232013-01-19 00:14:59 +00001023% o server_info: the distributed cache info.
cristyce9db092013-01-16 22:16:51 +00001024%
1025*/
cristyd9fdd232013-01-19 00:14:59 +00001026MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info)
cristyce9db092013-01-16 22:16:51 +00001027{
cristyd9fdd232013-01-19 00:14:59 +00001028 assert(server_info != (DistributeCacheInfo *) NULL);
1029 assert(server_info->signature == MagickSignature);
1030 return(server_info->port);
cristyce9db092013-01-16 22:16:51 +00001031}
1032
1033/*
1034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035% %
1036% %
1037% %
cristy43940f42013-01-17 00:24:06 +00001038+ O p e n D i s t r i b u t e P i x e l C a c h e %
cristybb31fcd2013-01-15 20:06:37 +00001039% %
1040% %
1041% %
1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1043%
1044% OpenDistributePixelCache() opens a pixel cache on a remote server.
1045%
1046% The format of the OpenDistributePixelCache method is:
1047%
1048% MagickBooleanType *OpenDistributePixelCache(
cristyd9fdd232013-01-19 00:14:59 +00001049% DistributeCacheInfo *server_info,Image *image)
cristybb31fcd2013-01-15 20:06:37 +00001050%
1051% A description of each parameter follows:
1052%
cristyd9fdd232013-01-19 00:14:59 +00001053% o server_info: the distributed cache info.
cristybb31fcd2013-01-15 20:06:37 +00001054%
1055% o image: the image.
1056%
1057*/
1058MagickPrivate MagickBooleanType OpenDistributePixelCache(
cristyd9fdd232013-01-19 00:14:59 +00001059 DistributeCacheInfo *server_info,Image *image)
cristybb31fcd2013-01-15 20:06:37 +00001060{
cristy8cca92e2013-01-23 21:00:51 +00001061 MagickBooleanType
1062 status;
1063
cristyb9120722013-01-20 17:20:50 +00001064 MagickOffsetType
1065 count;
1066
cristyce9db092013-01-16 22:16:51 +00001067 register unsigned char
1068 *p;
cristybb31fcd2013-01-15 20:06:37 +00001069
cristyce9db092013-01-16 22:16:51 +00001070 unsigned char
cristyb9120722013-01-20 17:20:50 +00001071 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +00001072
cristyfeb21672013-01-23 00:12:55 +00001073 /*
1074 Open distributed pixel cache.
1075 */
cristyd9fdd232013-01-19 00:14:59 +00001076 assert(server_info != (DistributeCacheInfo *) NULL);
1077 assert(server_info->signature == MagickSignature);
cristybb31fcd2013-01-15 20:06:37 +00001078 assert(image != (Image *) NULL);
1079 assert(image->signature == MagickSignature);
cristyb9120722013-01-20 17:20:50 +00001080 p=message;
cristy9c3f05b2013-01-17 18:51:14 +00001081 *p++='o'; /* open */
cristy766c2f12013-01-25 02:46:26 +00001082 /*
1083 Serialize image attributes (see ValidatePixelCacheMorphology()).
1084 */
cristyd9fdd232013-01-19 00:14:59 +00001085 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1086 p+=sizeof(server_info->session_key);
cristy766c2f12013-01-25 02:46:26 +00001087 (void) memcpy(p,&image->storage_class,sizeof(image->storage_class));
1088 p+=sizeof(image->storage_class);
1089 (void) memcpy(p,&image->colorspace,sizeof(image->colorspace));
1090 p+=sizeof(image->colorspace);
1091 (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait));
1092 p+=sizeof(image->alpha_trait);
cristy883fde12013-04-08 00:50:13 +00001093 (void) memcpy(p,&image->read_mask,sizeof(image->read_mask));
1094 p+=sizeof(image->read_mask);
1095 (void) memcpy(p,&image->write_mask,sizeof(image->write_mask));
1096 p+=sizeof(image->write_mask);
cristyce9db092013-01-16 22:16:51 +00001097 (void) memcpy(p,&image->columns,sizeof(image->columns));
1098 p+=sizeof(image->columns);
1099 (void) memcpy(p,&image->rows,sizeof(image->rows));
1100 p+=sizeof(image->rows);
1101 (void) memcpy(p,&image->number_channels,sizeof(image->number_channels));
1102 p+=sizeof(image->number_channels);
cristy766c2f12013-01-25 02:46:26 +00001103 (void) memcpy(p,image->channel_map,MaxPixelChannels*
1104 sizeof(*image->channel_map));
1105 p+=MaxPixelChannels*sizeof(*image->channel_map);
1106 (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent));
1107 p+=sizeof(image->metacontent_extent);
cristyb9120722013-01-20 17:20:50 +00001108 count=dpc_send(server_info->file,p-message,message);
1109 if (count != (MagickOffsetType) (p-message))
cristybb31fcd2013-01-15 20:06:37 +00001110 return(MagickFalse);
cristy8cca92e2013-01-23 21:00:51 +00001111 status=MagickFalse;
1112 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1113 if (count != (MagickOffsetType) sizeof(status))
1114 return(MagickFalse);
1115 return(status);
cristybb31fcd2013-01-15 20:06:37 +00001116}
1117
1118/*
1119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120% %
1121% %
1122% %
cristy43940f42013-01-17 00:24:06 +00001123+ 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 %
cristybb31fcd2013-01-15 20:06:37 +00001124% %
1125% %
1126% %
1127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128%
cristyce9db092013-01-16 22:16:51 +00001129% ReadDistributePixelCacheMetacontents() reads metacontent from the specified
1130% region of the distributed pixel cache.
cristybb31fcd2013-01-15 20:06:37 +00001131%
cristyce9db092013-01-16 22:16:51 +00001132% The format of the ReadDistributePixelCacheMetacontents method is:
cristybb31fcd2013-01-15 20:06:37 +00001133%
cristyd6e5ed32013-01-19 17:24:56 +00001134% MagickOffsetType ReadDistributePixelCacheMetacontents(
cristyd9fdd232013-01-19 00:14:59 +00001135% DistributeCacheInfo *server_info,const RectangleInfo *region,
cristyce9db092013-01-16 22:16:51 +00001136% const MagickSizeType length,unsigned char *metacontent)
1137%
1138% A description of each parameter follows:
1139%
cristyd9fdd232013-01-19 00:14:59 +00001140% o server_info: the distributed cache info.
cristyce9db092013-01-16 22:16:51 +00001141%
1142% o image: the image.
1143%
1144% o region: read the metacontent from this region of the image.
1145%
cristya4eb3d62013-01-17 00:36:58 +00001146% o length: the length in bytes of the metacontent.
cristyce9db092013-01-16 22:16:51 +00001147%
1148% o metacontent: read these metacontent from the pixel cache.
1149%
1150*/
cristyd6e5ed32013-01-19 17:24:56 +00001151MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
cristyd9fdd232013-01-19 00:14:59 +00001152 DistributeCacheInfo *server_info,const RectangleInfo *region,
cristyce9db092013-01-16 22:16:51 +00001153 const MagickSizeType length,unsigned char *metacontent)
1154{
cristyd6e5ed32013-01-19 17:24:56 +00001155 MagickOffsetType
1156 count;
1157
cristyce9db092013-01-16 22:16:51 +00001158 register unsigned char
1159 *p;
1160
cristyce9db092013-01-16 22:16:51 +00001161 unsigned char
cristyb9120722013-01-20 17:20:50 +00001162 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +00001163
cristyfeb21672013-01-23 00:12:55 +00001164 /*
1165 Read distributed pixel cache metacontent.
1166 */
cristyd9fdd232013-01-19 00:14:59 +00001167 assert(server_info != (DistributeCacheInfo *) NULL);
1168 assert(server_info->signature == MagickSignature);
cristyce9db092013-01-16 22:16:51 +00001169 assert(region != (RectangleInfo *) NULL);
1170 assert(metacontent != (unsigned char *) NULL);
cristy766c2f12013-01-25 02:46:26 +00001171 if (length > (MagickSizeType) SSIZE_MAX)
cristyd6e5ed32013-01-19 17:24:56 +00001172 return(-1);
cristyb9120722013-01-20 17:20:50 +00001173 p=message;
cristyfeb21672013-01-23 00:12:55 +00001174 *p++='R';
cristyd9fdd232013-01-19 00:14:59 +00001175 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1176 p+=sizeof(server_info->session_key);
cristyce9db092013-01-16 22:16:51 +00001177 (void) memcpy(p,&region->width,sizeof(region->width));
1178 p+=sizeof(region->width);
1179 (void) memcpy(p,&region->height,sizeof(region->height));
1180 p+=sizeof(region->height);
1181 (void) memcpy(p,&region->x,sizeof(region->x));
1182 p+=sizeof(region->x);
1183 (void) memcpy(p,&region->y,sizeof(region->y));
1184 p+=sizeof(region->y);
1185 (void) memcpy(p,&length,sizeof(length));
1186 p+=sizeof(length);
cristyb9120722013-01-20 17:20:50 +00001187 count=dpc_send(server_info->file,p-message,message);
1188 if (count != (MagickOffsetType) (p-message))
cristyd6e5ed32013-01-19 17:24:56 +00001189 return(-1);
cristyfeb21672013-01-23 00:12:55 +00001190 return(dpc_read(server_info->file,length,metacontent));
cristyce9db092013-01-16 22:16:51 +00001191}
1192
1193/*
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195% %
1196% %
1197% %
cristy43940f42013-01-17 00:24:06 +00001198+ 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 %
cristyce9db092013-01-16 22:16:51 +00001199% %
1200% %
1201% %
1202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203%
1204% ReadDistributePixelCachePixels() reads pixels from the specified region of
1205% the distributed pixel cache.
1206%
1207% The format of the ReadDistributePixelCachePixels method is:
1208%
cristyd6e5ed32013-01-19 17:24:56 +00001209% MagickOffsetType ReadDistributePixelCachePixels(
cristyd9fdd232013-01-19 00:14:59 +00001210% DistributeCacheInfo *server_info,const RectangleInfo *region,
cristy1d1254d2013-04-19 16:12:56 +00001211% const MagickSizeType length,unsigned char *restrict pixels)
cristybb31fcd2013-01-15 20:06:37 +00001212%
1213% A description of each parameter follows:
1214%
cristyd9fdd232013-01-19 00:14:59 +00001215% o server_info: the distributed cache info.
cristybb31fcd2013-01-15 20:06:37 +00001216%
1217% o image: the image.
1218%
1219% o region: read the pixels from this region of the image.
1220%
cristya4eb3d62013-01-17 00:36:58 +00001221% o length: the length in bytes of the pixels.
cristye34745c2013-01-16 02:27:04 +00001222%
cristybb31fcd2013-01-15 20:06:37 +00001223% o pixels: read these pixels from the pixel cache.
1224%
1225*/
cristyd6e5ed32013-01-19 17:24:56 +00001226MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
cristyd9fdd232013-01-19 00:14:59 +00001227 DistributeCacheInfo *server_info,const RectangleInfo *region,
cristy1d1254d2013-04-19 16:12:56 +00001228 const MagickSizeType length,unsigned char *restrict pixels)
cristybb31fcd2013-01-15 20:06:37 +00001229{
cristyd6e5ed32013-01-19 17:24:56 +00001230 MagickOffsetType
1231 count;
1232
cristyce9db092013-01-16 22:16:51 +00001233 register unsigned char
1234 *p;
cristybb31fcd2013-01-15 20:06:37 +00001235
cristyce9db092013-01-16 22:16:51 +00001236 unsigned char
cristyb9120722013-01-20 17:20:50 +00001237 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +00001238
cristyfeb21672013-01-23 00:12:55 +00001239 /*
1240 Read distributed pixel cache pixels.
1241 */
cristyd9fdd232013-01-19 00:14:59 +00001242 assert(server_info != (DistributeCacheInfo *) NULL);
1243 assert(server_info->signature == MagickSignature);
cristybb31fcd2013-01-15 20:06:37 +00001244 assert(region != (RectangleInfo *) NULL);
cristyce9db092013-01-16 22:16:51 +00001245 assert(pixels != (unsigned char *) NULL);
cristy766c2f12013-01-25 02:46:26 +00001246 if (length > (MagickSizeType) SSIZE_MAX)
cristyd6e5ed32013-01-19 17:24:56 +00001247 return(-1);
cristyb9120722013-01-20 17:20:50 +00001248 p=message;
cristyfeb21672013-01-23 00:12:55 +00001249 *p++='r';
cristyd9fdd232013-01-19 00:14:59 +00001250 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1251 p+=sizeof(server_info->session_key);
cristyce9db092013-01-16 22:16:51 +00001252 (void) memcpy(p,&region->width,sizeof(region->width));
1253 p+=sizeof(region->width);
1254 (void) memcpy(p,&region->height,sizeof(region->height));
1255 p+=sizeof(region->height);
1256 (void) memcpy(p,&region->x,sizeof(region->x));
1257 p+=sizeof(region->x);
1258 (void) memcpy(p,&region->y,sizeof(region->y));
1259 p+=sizeof(region->y);
1260 (void) memcpy(p,&length,sizeof(length));
1261 p+=sizeof(length);
cristyb9120722013-01-20 17:20:50 +00001262 count=dpc_send(server_info->file,p-message,message);
1263 if (count != (MagickOffsetType) (p-message))
cristyd6e5ed32013-01-19 17:24:56 +00001264 return(-1);
cristyfeb21672013-01-23 00:12:55 +00001265 return(dpc_read(server_info->file,length,pixels));
cristybb31fcd2013-01-15 20:06:37 +00001266}
1267
1268/*
1269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1270% %
1271% %
1272% %
cristy43940f42013-01-17 00:24:06 +00001273+ 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 %
cristybb31fcd2013-01-15 20:06:37 +00001274% %
1275% %
1276% %
1277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1278%
1279% RelinquishDistributePixelCache() frees resources acquired with
1280% OpenDistributePixelCache().
1281%
1282% The format of the RelinquishDistributePixelCache method is:
1283%
cristyce9db092013-01-16 22:16:51 +00001284% MagickBooleanType RelinquishDistributePixelCache(
cristyd9fdd232013-01-19 00:14:59 +00001285% DistributeCacheInfo *server_info)
cristybb31fcd2013-01-15 20:06:37 +00001286%
1287% A description of each parameter follows:
1288%
cristyd9fdd232013-01-19 00:14:59 +00001289% o server_info: the distributed cache info.
cristybb31fcd2013-01-15 20:06:37 +00001290%
1291*/
cristyce9db092013-01-16 22:16:51 +00001292MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
cristyd9fdd232013-01-19 00:14:59 +00001293 DistributeCacheInfo *server_info)
cristybb31fcd2013-01-15 20:06:37 +00001294{
cristy3349e172013-01-25 20:05:18 +00001295 MagickBooleanType
1296 status;
1297
cristyb9120722013-01-20 17:20:50 +00001298 MagickOffsetType
1299 count;
1300
cristyce9db092013-01-16 22:16:51 +00001301 register unsigned char
1302 *p;
cristybb31fcd2013-01-15 20:06:37 +00001303
cristyce9db092013-01-16 22:16:51 +00001304 unsigned char
cristyb9120722013-01-20 17:20:50 +00001305 message[MaxTextExtent];
cristybb31fcd2013-01-15 20:06:37 +00001306
cristyfeb21672013-01-23 00:12:55 +00001307 /*
1308 Delete distributed pixel cache.
1309 */
cristyd9fdd232013-01-19 00:14:59 +00001310 assert(server_info != (DistributeCacheInfo *) NULL);
1311 assert(server_info->signature == MagickSignature);
cristyb9120722013-01-20 17:20:50 +00001312 p=message;
cristyfeb21672013-01-23 00:12:55 +00001313 *p++='d';
cristyd9fdd232013-01-19 00:14:59 +00001314 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1315 p+=sizeof(server_info->session_key);
cristyb9120722013-01-20 17:20:50 +00001316 count=dpc_send(server_info->file,p-message,message);
1317 if (count != (MagickOffsetType) (p-message))
cristyce9db092013-01-16 22:16:51 +00001318 return(MagickFalse);
cristy3349e172013-01-25 20:05:18 +00001319 count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
1320 if (count != (MagickOffsetType) sizeof(status))
1321 return(MagickFalse);
1322 return(status);
cristybb31fcd2013-01-15 20:06:37 +00001323}
1324
1325/*
1326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327% %
1328% %
1329% %
cristy43940f42013-01-17 00:24:06 +00001330+ 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 %
cristybb31fcd2013-01-15 20:06:37 +00001331% %
1332% %
1333% %
1334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335%
cristyce9db092013-01-16 22:16:51 +00001336% WriteDistributePixelCacheMetacontents() writes image metacontent to the
1337% specified region of the distributed pixel cache.
cristye34745c2013-01-16 02:27:04 +00001338%
cristyce9db092013-01-16 22:16:51 +00001339% The format of the WriteDistributePixelCacheMetacontents method is:
cristybb31fcd2013-01-15 20:06:37 +00001340%
cristyd6e5ed32013-01-19 17:24:56 +00001341% MagickOffsetType WriteDistributePixelCacheMetacontents(
cristyd9fdd232013-01-19 00:14:59 +00001342% DistributeCacheInfo *server_info,const RectangleInfo *region,
cristyce9db092013-01-16 22:16:51 +00001343% const MagickSizeType length,const unsigned char *metacontent)
1344%
1345% A description of each parameter follows:
1346%
cristyd9fdd232013-01-19 00:14:59 +00001347% o server_info: the distributed cache info.
cristyce9db092013-01-16 22:16:51 +00001348%
1349% o image: the image.
1350%
1351% o region: write the metacontent to this region of the image.
1352%
cristya4eb3d62013-01-17 00:36:58 +00001353% o length: the length in bytes of the metacontent.
cristyce9db092013-01-16 22:16:51 +00001354%
1355% o metacontent: write these metacontent to the pixel cache.
1356%
1357*/
cristyd6e5ed32013-01-19 17:24:56 +00001358MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
cristyd9fdd232013-01-19 00:14:59 +00001359 DistributeCacheInfo *server_info,const RectangleInfo *region,
cristyce9db092013-01-16 22:16:51 +00001360 const MagickSizeType length,const unsigned char *metacontent)
1361{
cristyd6e5ed32013-01-19 17:24:56 +00001362 MagickOffsetType
1363 count;
1364
cristyce9db092013-01-16 22:16:51 +00001365 register unsigned char
1366 *p;
1367
cristyce9db092013-01-16 22:16:51 +00001368 unsigned char
cristyb9120722013-01-20 17:20:50 +00001369 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +00001370
cristyfeb21672013-01-23 00:12:55 +00001371 /*
1372 Write distributed pixel cache metacontent.
1373 */
cristyd9fdd232013-01-19 00:14:59 +00001374 assert(server_info != (DistributeCacheInfo *) NULL);
1375 assert(server_info->signature == MagickSignature);
cristyce9db092013-01-16 22:16:51 +00001376 assert(region != (RectangleInfo *) NULL);
1377 assert(metacontent != (unsigned char *) NULL);
cristy766c2f12013-01-25 02:46:26 +00001378 if (length > (MagickSizeType) SSIZE_MAX)
cristyd6e5ed32013-01-19 17:24:56 +00001379 return(-1);
cristyb9120722013-01-20 17:20:50 +00001380 p=message;
cristyfeb21672013-01-23 00:12:55 +00001381 *p++='W';
cristyd9fdd232013-01-19 00:14:59 +00001382 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1383 p+=sizeof(server_info->session_key);
cristyce9db092013-01-16 22:16:51 +00001384 (void) memcpy(p,&region->width,sizeof(region->width));
1385 p+=sizeof(region->width);
1386 (void) memcpy(p,&region->height,sizeof(region->height));
1387 p+=sizeof(region->height);
1388 (void) memcpy(p,&region->x,sizeof(region->x));
1389 p+=sizeof(region->x);
1390 (void) memcpy(p,&region->y,sizeof(region->y));
1391 p+=sizeof(region->y);
1392 (void) memcpy(p,&length,sizeof(length));
1393 p+=sizeof(length);
cristyb9120722013-01-20 17:20:50 +00001394 count=dpc_send(server_info->file,p-message,message);
1395 if (count != (MagickOffsetType) (p-message))
cristyd6e5ed32013-01-19 17:24:56 +00001396 return(-1);
cristyfeb21672013-01-23 00:12:55 +00001397 return(dpc_send(server_info->file,length,metacontent));
cristyce9db092013-01-16 22:16:51 +00001398}
1399
1400/*
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402% %
1403% %
1404% %
cristy43940f42013-01-17 00:24:06 +00001405+ 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 %
cristyce9db092013-01-16 22:16:51 +00001406% %
1407% %
1408% %
1409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410%
1411% WriteDistributePixelCachePixels() writes image pixels to the specified
1412% region of the distributed pixel cache.
1413%
cristyce9db092013-01-16 22:16:51 +00001414% The format of the WriteDistributePixelCachePixels method is:
1415%
cristyd6e5ed32013-01-19 17:24:56 +00001416% MagickBooleanType WriteDistributePixelCachePixels(
cristyd9fdd232013-01-19 00:14:59 +00001417% DistributeCacheInfo *server_info,const RectangleInfo *region,
cristy1d1254d2013-04-19 16:12:56 +00001418% const MagickSizeType length,const unsigned char *restrict pixels)
cristybb31fcd2013-01-15 20:06:37 +00001419%
1420% A description of each parameter follows:
1421%
cristyd9fdd232013-01-19 00:14:59 +00001422% o server_info: the distributed cache info.
cristybb31fcd2013-01-15 20:06:37 +00001423%
1424% o image: the image.
1425%
1426% o region: write the pixels to this region of the image.
1427%
cristya4eb3d62013-01-17 00:36:58 +00001428% o length: the length in bytes of the pixels.
cristye34745c2013-01-16 02:27:04 +00001429%
cristybb31fcd2013-01-15 20:06:37 +00001430% o pixels: write these pixels to the pixel cache.
1431%
1432*/
cristyd6e5ed32013-01-19 17:24:56 +00001433MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
cristyd9fdd232013-01-19 00:14:59 +00001434 DistributeCacheInfo *server_info,const RectangleInfo *region,
cristy1d1254d2013-04-19 16:12:56 +00001435 const MagickSizeType length,const unsigned char *restrict pixels)
cristybb31fcd2013-01-15 20:06:37 +00001436{
cristyd6e5ed32013-01-19 17:24:56 +00001437 MagickOffsetType
1438 count;
1439
cristyce9db092013-01-16 22:16:51 +00001440 register unsigned char
1441 *p;
cristybb31fcd2013-01-15 20:06:37 +00001442
cristyce9db092013-01-16 22:16:51 +00001443 unsigned char
cristyb9120722013-01-20 17:20:50 +00001444 message[MaxTextExtent];
cristyce9db092013-01-16 22:16:51 +00001445
cristyfeb21672013-01-23 00:12:55 +00001446 /*
1447 Write distributed pixel cache pixels.
1448 */
cristyd9fdd232013-01-19 00:14:59 +00001449 assert(server_info != (DistributeCacheInfo *) NULL);
1450 assert(server_info->signature == MagickSignature);
cristybb31fcd2013-01-15 20:06:37 +00001451 assert(region != (RectangleInfo *) NULL);
cristyce9db092013-01-16 22:16:51 +00001452 assert(pixels != (const unsigned char *) NULL);
cristy766c2f12013-01-25 02:46:26 +00001453 if (length > (MagickSizeType) SSIZE_MAX)
cristyd6e5ed32013-01-19 17:24:56 +00001454 return(-1);
cristyb9120722013-01-20 17:20:50 +00001455 p=message;
cristyfeb21672013-01-23 00:12:55 +00001456 *p++='w';
cristyd9fdd232013-01-19 00:14:59 +00001457 (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key));
1458 p+=sizeof(server_info->session_key);
cristyce9db092013-01-16 22:16:51 +00001459 (void) memcpy(p,&region->width,sizeof(region->width));
1460 p+=sizeof(region->width);
1461 (void) memcpy(p,&region->height,sizeof(region->height));
1462 p+=sizeof(region->height);
1463 (void) memcpy(p,&region->x,sizeof(region->x));
1464 p+=sizeof(region->x);
1465 (void) memcpy(p,&region->y,sizeof(region->y));
1466 p+=sizeof(region->y);
1467 (void) memcpy(p,&length,sizeof(length));
1468 p+=sizeof(length);
cristyb9120722013-01-20 17:20:50 +00001469 count=dpc_send(server_info->file,p-message,message);
1470 if (count != (MagickOffsetType) (p-message))
cristyd6e5ed32013-01-19 17:24:56 +00001471 return(-1);
cristyfeb21672013-01-23 00:12:55 +00001472 return(dpc_send(server_info->file,length,pixels));
cristybb31fcd2013-01-15 20:06:37 +00001473}