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