From 9d3ea027836442df9e7160bc43cb9cec793f60d3 Mon Sep 17 00:00:00 2001 From: dirk Date: Sat, 17 Jan 2015 22:42:01 +0000 Subject: [PATCH] Fixed 64 bit warnings. --- MagickCore/distribute-cache.c | 3056 +++++++++++++++++---------------- MagickCore/nt-base.c | 2 +- 2 files changed, 1530 insertions(+), 1528 deletions(-) diff --git a/MagickCore/distribute-cache.c b/MagickCore/distribute-cache.c index 850b3854d..aa716181a 100644 --- a/MagickCore/distribute-cache.c +++ b/MagickCore/distribute-cache.c @@ -1,1527 +1,1529 @@ -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% DDDD IIIII SSSSS TTTTT RRRR IIIII BBBB U U TTTTT EEEEE % -% D D I SS T R R I B B U U T E % -% D D I SSS T RRRR I BBBB U U T EEE % -% D D I SS T R R I B B U U T E % -% DDDDA IIIII SSSSS T R R IIIII BBBB UUU T EEEEE % -% % -% CCCC AAA CCCC H H EEEEE % -% C A A C H H E % -% C AAAAA C HHHHH EEE % -% C A A C H H E % -% CCCC A A CCCC H H EEEEE % -% % -% % -% MagickCore Distributed Pixel Cache Methods % -% % -% Software Design % -% Cristy % -% January 2013 % -% % -% % -% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% http://www.imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% A distributed pixel cache is an extension of the traditional pixel cache -% available on a single host. The distributed pixel cache may span multiple -% servers so that it can grow in size and transactional capacity to support -% very large images. Start up the pixel cache server on one or more machines. -% When you read or operate on an image and the local pixel cache resources are -% exhausted, ImageMagick contacts one or more of these remote pixel servers to -% store or retrieve pixels. -% -*/ - -/* - Include declarations. -*/ -#include "MagickCore/studio.h" -#include "MagickCore/cache.h" -#include "MagickCore/cache-private.h" -#include "MagickCore/distribute-cache.h" -#include "MagickCore/distribute-cache-private.h" -#include "MagickCore/exception.h" -#include "MagickCore/exception-private.h" -#include "MagickCore/geometry.h" -#include "MagickCore/image.h" -#include "MagickCore/image-private.h" -#include "MagickCore/list.h" -#include "MagickCore/locale_.h" -#include "MagickCore/memory_.h" -#include "MagickCore/nt-base-private.h" -#include "MagickCore/pixel.h" -#include "MagickCore/policy.h" -#include "MagickCore/random_.h" -#include "MagickCore/registry.h" -#include "MagickCore/splay-tree.h" -#include "MagickCore/string_.h" -#include "MagickCore/string-private.h" -#include "MagickCore/version.h" -#include "MagickCore/version-private.h" -#undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE -#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT) -#include -#include -#include -#include -#define CHAR_TYPE_CAST -#define CLOSE_SOCKET(socket) (void) close(socket) -#define HANDLER_RETURN_TYPE void * -#define HANDLER_RETURN_VALUE (void *) NULL -#define SOCKET_TYPE int -#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE -#elif defined(MAGICKCORE_WINDOWS_SUPPORT) -#define CHAR_TYPE_CAST (char *) -#define CLOSE_SOCKET(socket) (void) closesocket(socket) -#define HANDLER_RETURN_TYPE DWORD WINAPI -#define HANDLER_RETURN_VALUE 0 -#define SOCKET_TYPE SOCKET -#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE -#else -#define CLOSE_SOCKET(socket) -#define HANDLER_RETURN_TYPE void * -#define HANDLER_RETURN_VALUE (void *) NULL -#define SOCKET_TYPE int -#undef send -#undef recv -#define send(file,buffer,length,flags) 0 -#define recv(file,buffer,length,flags) 0 -#endif - -/* - Define declarations. -*/ -#define DPCHostname "127.0.0.1" -#define DPCPendingConnections 10 -#define DPCPort 6668 -#define DPCSessionKeyLength 8 -#ifndef MSG_NOSIGNAL -# define MSG_NOSIGNAL 0 -#endif - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure. -% -% The format of the AcquireDistributeCacheInfo method is: -% -% DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception) -% -% A description of each parameter follows: -% -% o exception: return any errors or warnings in this structure. -% -*/ - -static inline MagickOffsetType dpc_read(int file,const MagickSizeType length, - unsigned char *restrict message) -{ - register MagickOffsetType - i; - - ssize_t - count; - -#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) - magick_unreferenced(file); - magick_unreferenced(message); -#endif - - count=0; - for (i=0; i < (MagickOffsetType) length; i+=count) - { - count=recv(file,CHAR_TYPE_CAST message+i,(size_t) MagickMin(length-i, - (MagickSizeType) SSIZE_MAX),0); - if (count <= 0) - { - count=0; - if (errno != EINTR) - break; - } - } - return(i); -} - -static int ConnectPixelCacheServer(const char *hostname,const int port, - size_t *session_key,ExceptionInfo *exception) -{ -#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) - char - service[MaxTextExtent]; - - const char - *shared_secret; - - int - status; - - SOCKET_TYPE - client_socket; - - ssize_t - count; - - struct addrinfo - hint, - *result; - - unsigned char - secret[MaxTextExtent]; - - /* - Connect to distributed pixel cache and get session key. - */ - *session_key=0; - shared_secret=GetPolicyValue("shared-secret"); - if (shared_secret == (const char *) NULL) - { - (void) ThrowMagickException(exception,GetMagickModule(),CacheError, - "DistributedPixelCache","'%s'","shared secret expected"); - return(-1); - } -#if defined(MAGICKCORE_WINDOWS_SUPPORT) - NTInitializeWinsock(MagickTrue); -#endif - (void) ResetMagickMemory(&hint,0,sizeof(hint)); - hint.ai_family=AF_INET; - hint.ai_socktype=SOCK_STREAM; - hint.ai_flags=AI_PASSIVE; - (void) FormatLocaleString(service,MaxTextExtent,"%d",port); - status=getaddrinfo(hostname,service,&hint,&result); - if (status != 0) - { - (void) ThrowMagickException(exception,GetMagickModule(),CacheError, - "DistributedPixelCache","'%s'",hostname); - return(-1); - } - client_socket=socket(result->ai_family,result->ai_socktype, - result->ai_protocol); - if (client_socket == -1) - { - (void) ThrowMagickException(exception,GetMagickModule(),CacheError, - "DistributedPixelCache","'%s'",hostname); - return(-1); - } - status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen); - if (status == -1) - { - (void) ThrowMagickException(exception,GetMagickModule(),CacheError, - "DistributedPixelCache","'%s'",hostname); - return(-1); - } - count=recv(client_socket,CHAR_TYPE_CAST secret,MaxTextExtent,0); - if (count != -1) - { - StringInfo - *nonce; - - nonce=AcquireStringInfo(count); - (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count); - *session_key=GetMagickSignature(nonce); - nonce=DestroyStringInfo(nonce); - } - if (*session_key == 0) - { - CLOSE_SOCKET(client_socket); - client_socket=(SOCKET_TYPE) (-1); - } - return(client_socket); -#else - (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, - "DelegateLibrarySupportNotBuiltIn","distributed pixel cache"); - return(MagickFalse); -#endif -} - -static char *GetHostname(int *port,ExceptionInfo *exception) -{ - char - *host, - *hosts, - **hostlist; - - int - argc; - - register ssize_t - i; - - static size_t - id = 0; - - /* - Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668). - */ - hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",exception); - if (hosts == (char *) NULL) - { - *port=DPCPort; - return(AcquireString(DPCHostname)); - } - (void) SubstituteString(&hosts,","," "); - hostlist=StringToArgv(hosts,&argc); - hosts=DestroyString(hosts); - if (hostlist == (char **) NULL) - { - *port=DPCPort; - return(AcquireString(DPCHostname)); - } - hosts=AcquireString(hostlist[(id++ % (argc-1))+1]); - for (i=0; i < (ssize_t) argc; i++) - hostlist[i]=DestroyString(hostlist[i]); - hostlist=(char **) RelinquishMagickMemory(hostlist); - (void) SubstituteString(&hosts,":"," "); - hostlist=StringToArgv(hosts,&argc); - if (hostlist == (char **) NULL) - { - *port=DPCPort; - return(AcquireString(DPCHostname)); - } - host=AcquireString(hostlist[1]); - if (hostlist[2] == (char *) NULL) - *port=DPCPort; - else - *port=StringToLong(hostlist[2]); - for (i=0; i < (ssize_t) argc; i++) - hostlist[i]=DestroyString(hostlist[i]); - hostlist=(char **) RelinquishMagickMemory(hostlist); - return(host); -} - -MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo( - ExceptionInfo *exception) -{ - char - *hostname; - - DistributeCacheInfo - *server_info; - - size_t - session_key; - - /* - Connect to the distributed pixel cache server. - */ - server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info)); - if (server_info == (DistributeCacheInfo *) NULL) - ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); - (void) ResetMagickMemory(server_info,0,sizeof(*server_info)); - server_info->signature=MagickSignature; - server_info->port=0; - hostname=GetHostname(&server_info->port,exception); - session_key=0; - server_info->file=ConnectPixelCacheServer(hostname,server_info->port, - &session_key,exception); - if (server_info->file == -1) - server_info=DestroyDistributeCacheInfo(server_info); - else - { - server_info->session_key=session_key; - (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent); - server_info->debug=IsEventLogging(); - } - hostname=DestroyString(hostname); - return(server_info); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% DestroyDistributeCacheInfo() deallocates memory associated with an -% DistributeCacheInfo structure. -% -% The format of the DestroyDistributeCacheInfo method is: -% -% DistributeCacheInfo *DestroyDistributeCacheInfo( -% DistributeCacheInfo *server_info) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -*/ -MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( - DistributeCacheInfo *server_info) -{ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - if (server_info->file > 0) - CLOSE_SOCKET(server_info->file); - server_info->signature=(~MagickSignature); - server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info); - return(server_info); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% DistributePixelCacheServer() waits on the specified port for commands to -% create, read, update, or destroy a pixel cache. -% -% The format of the DistributePixelCacheServer() method is: -% -% void DistributePixelCacheServer(const int port) -% -% A description of each parameter follows: -% -% o port: connect the distributed pixel cache at this port. -% -% o exception: return any errors or warnings in this structure. -% -*/ - -static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry, - const size_t session_key) -{ - /* - Destroy distributed pixel cache. - */ - return(DeleteNodeFromSplayTree(registry,(const void *) session_key)); -} - -static inline MagickOffsetType dpc_send(int file,const MagickSizeType length, - const unsigned char *restrict message) -{ - MagickOffsetType - count; - - register MagickOffsetType - i; - -#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) - magick_unreferenced(file); - magick_unreferenced(message); -#endif - - /* - Ensure a complete message is sent. - */ - count=0; - for (i=0; i < (MagickOffsetType) length; i+=count) - { - count=(MagickOffsetType) send(file,CHAR_TYPE_CAST message+i,(size_t) MagickMin(length-i, - (MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL); - if (count <= 0) - { - count=0; - if (errno != EINTR) - break; - } - } - return(i); -} - -static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file, - const size_t session_key,ExceptionInfo *exception) -{ - Image - *image; - - MagickBooleanType - status; - - MagickOffsetType - count; - - MagickSizeType - length; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Open distributed pixel cache. - */ - image=AcquireImage((ImageInfo *) NULL,exception); - if (image == (Image *) NULL) - return(MagickFalse); - length=sizeof(image->storage_class)+sizeof(image->colorspace)+ - sizeof(image->alpha_trait)+sizeof(image->read_mask)+ - sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+ - sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+ - sizeof(image->metacontent_extent); - count=dpc_read(file,length,message); - if (count != (MagickOffsetType) length) - return(MagickFalse); - /* - Deserialize the image attributes. - */ - p=message; - (void) memcpy(&image->storage_class,p,sizeof(image->storage_class)); - p+=sizeof(image->storage_class); - (void) memcpy(&image->colorspace,p,sizeof(image->colorspace)); - p+=sizeof(image->colorspace); - (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait)); - p+=sizeof(image->alpha_trait); - (void) memcpy(&image->read_mask,p,sizeof(image->read_mask)); - p+=sizeof(image->read_mask); - (void) memcpy(&image->write_mask,p,sizeof(image->write_mask)); - p+=sizeof(image->write_mask); - (void) memcpy(&image->columns,p,sizeof(image->columns)); - p+=sizeof(image->columns); - (void) memcpy(&image->rows,p,sizeof(image->rows)); - p+=sizeof(image->rows); - (void) memcpy(&image->number_channels,p,sizeof(image->number_channels)); - p+=sizeof(image->number_channels); - (void) memcpy(image->channel_map,p,MaxPixelChannels* - sizeof(*image->channel_map)); - p+=MaxPixelChannels*sizeof(*image->channel_map); - (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent)); - p+=sizeof(image->metacontent_extent); - if (SyncImagePixelCache(image,exception) == MagickFalse) - return(MagickFalse); - status=AddValueToSplayTree(registry,(const void *) session_key,image); - return(status); -} - -static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, - int file,const size_t session_key,ExceptionInfo *exception) -{ - const unsigned char - *metacontent; - - Image - *image; - - MagickOffsetType - count; - - MagickSizeType - length; - - RectangleInfo - region; - - register const Quantum - *p; - - register unsigned char - *q; - - unsigned char - message[MaxTextExtent]; - - /* - Read distributed pixel cache metacontent. - */ - image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); - if (image == (Image *) NULL) - return(MagickFalse); - length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ - sizeof(region.y)+sizeof(length); - count=dpc_read(file,length,message); - if (count != (MagickOffsetType) length) - return(MagickFalse); - q=message; - (void) memcpy(®ion.width,q,sizeof(region.width)); - q+=sizeof(region.width); - (void) memcpy(®ion.height,q,sizeof(region.height)); - q+=sizeof(region.height); - (void) memcpy(®ion.x,q,sizeof(region.x)); - q+=sizeof(region.x); - (void) memcpy(®ion.y,q,sizeof(region.y)); - q+=sizeof(region.y); - (void) memcpy(&length,q,sizeof(length)); - q+=sizeof(length); - p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, - exception); - if (p == (const Quantum *) NULL) - return(MagickFalse); - metacontent=(const unsigned char *) GetVirtualMetacontent(image); - count=dpc_send(file,length,metacontent); - if (count != (MagickOffsetType) length) - return(MagickFalse); - return(MagickTrue); -} - -static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry, - int file,const size_t session_key,ExceptionInfo *exception) -{ - Image - *image; - - MagickOffsetType - count; - - MagickSizeType - length; - - RectangleInfo - region; - - register const Quantum - *p; - - register unsigned char - *q; - - unsigned char - message[MaxTextExtent]; - - /* - Read distributed pixel cache pixels. - */ - image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); - if (image == (Image *) NULL) - return(MagickFalse); - length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ - sizeof(region.y)+sizeof(length); - count=dpc_read(file,length,message); - if (count != (MagickOffsetType) length) - return(MagickFalse); - q=message; - (void) memcpy(®ion.width,q,sizeof(region.width)); - q+=sizeof(region.width); - (void) memcpy(®ion.height,q,sizeof(region.height)); - q+=sizeof(region.height); - (void) memcpy(®ion.x,q,sizeof(region.x)); - q+=sizeof(region.x); - (void) memcpy(®ion.y,q,sizeof(region.y)); - q+=sizeof(region.y); - (void) memcpy(&length,q,sizeof(length)); - q+=sizeof(length); - p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, - exception); - if (p == (const Quantum *) NULL) - return(MagickFalse); - count=dpc_send(file,length,(unsigned char *) p); - if (count != (MagickOffsetType) length) - return(MagickFalse); - return(MagickTrue); -} - -static void *RelinquishImageRegistry(void *image) -{ - return((void *) DestroyImageList((Image *) image)); -} - -static MagickBooleanType WriteDistributeCacheMetacontent( - SplayTreeInfo *registry,int file,const size_t session_key, - ExceptionInfo *exception) -{ - Image - *image; - - MagickOffsetType - count; - - MagickSizeType - length; - - RectangleInfo - region; - - register Quantum - *q; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent], - *metacontent; - - /* - Write distributed pixel cache metacontent. - */ - image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); - if (image == (Image *) NULL) - return(MagickFalse); - length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ - sizeof(region.y)+sizeof(length); - count=dpc_read(file,length,message); - if (count != (MagickOffsetType) length) - return(MagickFalse); - p=message; - (void) memcpy(®ion.width,p,sizeof(region.width)); - p+=sizeof(region.width); - (void) memcpy(®ion.height,p,sizeof(region.height)); - p+=sizeof(region.height); - (void) memcpy(®ion.x,p,sizeof(region.x)); - p+=sizeof(region.x); - (void) memcpy(®ion.y,p,sizeof(region.y)); - p+=sizeof(region.y); - (void) memcpy(&length,p,sizeof(length)); - p+=sizeof(length); - q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, - exception); - if (q == (Quantum *) NULL) - return(MagickFalse); - metacontent=(unsigned char *) GetAuthenticMetacontent(image); - count=dpc_read(file,length,metacontent); - if (count != (MagickOffsetType) length) - return(MagickFalse); - return(SyncAuthenticPixels(image,exception)); -} - -static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, - int file,const size_t session_key,ExceptionInfo *exception) -{ - Image - *image; - - MagickOffsetType - count; - - MagickSizeType - length; - - RectangleInfo - region; - - register Quantum - *q; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Write distributed pixel cache pixels. - */ - image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); - if (image == (Image *) NULL) - return(MagickFalse); - length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ - sizeof(region.y)+sizeof(length); - count=dpc_read(file,length,message); - if (count != (MagickOffsetType) length) - return(MagickFalse); - p=message; - (void) memcpy(®ion.width,p,sizeof(region.width)); - p+=sizeof(region.width); - (void) memcpy(®ion.height,p,sizeof(region.height)); - p+=sizeof(region.height); - (void) memcpy(®ion.x,p,sizeof(region.x)); - p+=sizeof(region.x); - (void) memcpy(®ion.y,p,sizeof(region.y)); - p+=sizeof(region.y); - (void) memcpy(&length,p,sizeof(length)); - p+=sizeof(length); - q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, - exception); - if (q == (Quantum *) NULL) - return(MagickFalse); - count=dpc_read(file,length,(unsigned char *) q); - if (count != (MagickOffsetType) length) - return(MagickFalse); - return(SyncAuthenticPixels(image,exception)); -} - -static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket) -{ - const char - *shared_secret; - - ExceptionInfo - *exception; - - MagickBooleanType - status; - - MagickOffsetType - count; - - register unsigned char - *p; - - RandomInfo - *random_info; - - size_t - key, - session_key; - - SOCKET_TYPE - client_socket; - - SplayTreeInfo - *registry; - - StringInfo - *secret; - - unsigned char - command, - session[2*MaxTextExtent]; - - /* - Distributed pixel cache client. - */ - shared_secret=GetPolicyValue("shared-secret"); - if (shared_secret == (const char *) NULL) - ThrowFatalException(CacheFatalError,"shared secret expected"); - p=session; - (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent); - p+=strlen(shared_secret); - random_info=AcquireRandomInfo(); - secret=GetRandomKey(random_info,DPCSessionKeyLength); - (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength); - session_key=GetMagickSignature(secret); - random_info=DestroyRandomInfo(random_info); - exception=AcquireExceptionInfo(); - registry=NewSplayTree((int (*)(const void *,const void *)) NULL, - (void *(*)(void *)) NULL,RelinquishImageRegistry); - client_socket=(*(SOCKET_TYPE *) socket); - count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret)); - secret=DestroyStringInfo(secret); - for ( ; ; ) - { - count=dpc_read(client_socket,1,(unsigned char *) &command); - if (count <= 0) - break; - count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key); - if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key)) - break; - status=MagickFalse; - switch (command) - { - case 'o': - { - status=OpenDistributeCache(registry,client_socket,session_key, - exception); - count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status); - break; - } - case 'r': - { - status=ReadDistributeCachePixels(registry,client_socket,session_key, - exception); - break; - } - case 'R': - { - status=ReadDistributeCacheMetacontent(registry,client_socket, - session_key,exception); - break; - } - case 'w': - { - status=WriteDistributeCachePixels(registry,client_socket,session_key, - exception); - break; - } - case 'W': - { - status=WriteDistributeCacheMetacontent(registry,client_socket, - session_key,exception); - break; - } - case 'd': - { - status=DestroyDistributeCache(registry,session_key); - break; - } - default: - break; - } - if (status == MagickFalse) - break; - if (command == 'd') - break; - } - count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status); - CLOSE_SOCKET(client_socket); - exception=DestroyExceptionInfo(exception); - registry=DestroySplayTree(registry); - return(HANDLER_RETURN_VALUE); -} - -MagickExport void DistributePixelCacheServer(const int port, - ExceptionInfo *exception) -{ -#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) - char - service[MaxTextExtent]; - - int - status; - -#if defined(MAGICKCORE_THREAD_SUPPORT) - pthread_attr_t - attributes; - - pthread_t - threads; -#elif defined(MAGICKCORE_WINDOWS_SUPPORT) - DWORD - threadID; -#else - Not implemented! -#endif - - register struct addrinfo - *p; - - SOCKET_TYPE - server_socket; - - struct addrinfo - hint, - *result; - - struct sockaddr_in - address; - - /* - Launch distributed pixel cache server. - */ - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickSignature); -#if defined(MAGICKCORE_WINDOWS_SUPPORT) - NTInitializeWinsock(MagickFalse); -#endif - (void) ResetMagickMemory(&hint,0,sizeof(hint)); - hint.ai_family=AF_INET; - hint.ai_socktype=SOCK_STREAM; - hint.ai_flags=AI_PASSIVE; - (void) FormatLocaleString(service,MaxTextExtent,"%d",port); - status=getaddrinfo((const char *) NULL,service,&hint,&result); - if (status != 0) - ThrowFatalException(CacheFatalError,"UnableToListen"); - server_socket=(SOCKET_TYPE) 0; - for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next) - { - int - one; - - server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol); - if (server_socket == -1) - continue; - one=1; - status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR, - CHAR_TYPE_CAST &one,(socklen_t) sizeof(one)); - if (status == -1) - { - CLOSE_SOCKET(server_socket); - continue; - } - status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen); - if (status == -1) - { - CLOSE_SOCKET(server_socket); - continue; - } - break; - } - if (p == (struct addrinfo *) NULL) - ThrowFatalException(CacheFatalError,"UnableToBind"); - freeaddrinfo(result); - status=listen(server_socket,DPCPendingConnections); - if (status != 0) - ThrowFatalException(CacheFatalError,"UnableToListen"); -#if defined(MAGICKCORE_THREAD_SUPPORT) - pthread_attr_init(&attributes); -#endif - for ( ; ; ) - { - SOCKET_TYPE - client_socket; - - socklen_t - length; - - length=(socklen_t) sizeof(address); - client_socket=accept(server_socket,(struct sockaddr *) &address,&length); - if (client_socket == -1) - ThrowFatalException(CacheFatalError,"UnableToEstablishConnection"); -#if defined(MAGICKCORE_THREAD_SUPPORT) - status=pthread_create(&threads,&attributes,DistributePixelCacheClient, - (void *) &client_socket); - if (status == -1) - ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); -#elif defined(MAGICKCORE_WINDOWS_SUPPORT) - if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0, - &threadID) == (HANDLE) NULL) - ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); -#else - Not implemented! -#endif - } -#else - magick_unreferenced(port); - magick_unreferenced(exception); - ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn"); -#endif -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ G e t D i s t r i b u t e C a c h e F i l e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% GetDistributeCacheFile() returns the file associated with this -% DistributeCacheInfo structure. -% -% The format of the GetDistributeCacheFile method is: -% -% int GetDistributeCacheFile(const DistributeCacheInfo *server_info) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -*/ -MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info) -{ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - return(server_info->file); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% GetDistributeCacheHostname() returns the hostname associated with this -% DistributeCacheInfo structure. -% -% The format of the GetDistributeCacheHostname method is: -% -% const char *GetDistributeCacheHostname( -% const DistributeCacheInfo *server_info) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -*/ -MagickPrivate const char *GetDistributeCacheHostname( - const DistributeCacheInfo *server_info) -{ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - return(server_info->hostname); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ G e t D i s t r i b u t e C a c h e P o r t % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% GetDistributeCachePort() returns the port associated with this -% DistributeCacheInfo structure. -% -% The format of the GetDistributeCachePort method is: -% -% int GetDistributeCachePort(const DistributeCacheInfo *server_info) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -*/ -MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info) -{ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - return(server_info->port); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ O p e n D i s t r i b u t e P i x e l C a c h e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% OpenDistributePixelCache() opens a pixel cache on a remote server. -% -% The format of the OpenDistributePixelCache method is: -% -% MagickBooleanType *OpenDistributePixelCache( -% DistributeCacheInfo *server_info,Image *image) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -% o image: the image. -% -*/ -MagickPrivate MagickBooleanType OpenDistributePixelCache( - DistributeCacheInfo *server_info,Image *image) -{ - MagickBooleanType - status; - - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Open distributed pixel cache. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - assert(image != (Image *) NULL); - assert(image->signature == MagickSignature); - p=message; - *p++='o'; /* open */ - /* - Serialize image attributes (see ValidatePixelCacheMorphology()). - */ - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - (void) memcpy(p,&image->storage_class,sizeof(image->storage_class)); - p+=sizeof(image->storage_class); - (void) memcpy(p,&image->colorspace,sizeof(image->colorspace)); - p+=sizeof(image->colorspace); - (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait)); - p+=sizeof(image->alpha_trait); - (void) memcpy(p,&image->read_mask,sizeof(image->read_mask)); - p+=sizeof(image->read_mask); - (void) memcpy(p,&image->write_mask,sizeof(image->write_mask)); - p+=sizeof(image->write_mask); - (void) memcpy(p,&image->columns,sizeof(image->columns)); - p+=sizeof(image->columns); - (void) memcpy(p,&image->rows,sizeof(image->rows)); - p+=sizeof(image->rows); - (void) memcpy(p,&image->number_channels,sizeof(image->number_channels)); - p+=sizeof(image->number_channels); - (void) memcpy(p,image->channel_map,MaxPixelChannels* - sizeof(*image->channel_map)); - p+=MaxPixelChannels*sizeof(*image->channel_map); - (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent)); - p+=sizeof(image->metacontent_extent); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(MagickFalse); - status=MagickFalse; - count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); - if (count != (MagickOffsetType) sizeof(status)) - return(MagickFalse); - return(status); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ReadDistributePixelCacheMetacontents() reads metacontent from the specified -% region of the distributed pixel cache. -% -% The format of the ReadDistributePixelCacheMetacontents method is: -% -% MagickOffsetType ReadDistributePixelCacheMetacontents( -% DistributeCacheInfo *server_info,const RectangleInfo *region, -% const MagickSizeType length,unsigned char *metacontent) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -% o image: the image. -% -% o region: read the metacontent from this region of the image. -% -% o length: the length in bytes of the metacontent. -% -% o metacontent: read these metacontent from the pixel cache. -% -*/ -MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent( - DistributeCacheInfo *server_info,const RectangleInfo *region, - const MagickSizeType length,unsigned char *metacontent) -{ - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Read distributed pixel cache metacontent. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - assert(region != (RectangleInfo *) NULL); - assert(metacontent != (unsigned char *) NULL); - if (length > (MagickSizeType) SSIZE_MAX) - return(-1); - p=message; - *p++='R'; - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - (void) memcpy(p,®ion->width,sizeof(region->width)); - p+=sizeof(region->width); - (void) memcpy(p,®ion->height,sizeof(region->height)); - p+=sizeof(region->height); - (void) memcpy(p,®ion->x,sizeof(region->x)); - p+=sizeof(region->x); - (void) memcpy(p,®ion->y,sizeof(region->y)); - p+=sizeof(region->y); - (void) memcpy(p,&length,sizeof(length)); - p+=sizeof(length); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(-1); - return(dpc_read(server_info->file,length,metacontent)); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ReadDistributePixelCachePixels() reads pixels from the specified region of -% the distributed pixel cache. -% -% The format of the ReadDistributePixelCachePixels method is: -% -% MagickOffsetType ReadDistributePixelCachePixels( -% DistributeCacheInfo *server_info,const RectangleInfo *region, -% const MagickSizeType length,unsigned char *restrict pixels) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -% o image: the image. -% -% o region: read the pixels from this region of the image. -% -% o length: the length in bytes of the pixels. -% -% o pixels: read these pixels from the pixel cache. -% -*/ -MagickPrivate MagickOffsetType ReadDistributePixelCachePixels( - DistributeCacheInfo *server_info,const RectangleInfo *region, - const MagickSizeType length,unsigned char *restrict pixels) -{ - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Read distributed pixel cache pixels. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - assert(region != (RectangleInfo *) NULL); - assert(pixels != (unsigned char *) NULL); - if (length > (MagickSizeType) SSIZE_MAX) - return(-1); - p=message; - *p++='r'; - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - (void) memcpy(p,®ion->width,sizeof(region->width)); - p+=sizeof(region->width); - (void) memcpy(p,®ion->height,sizeof(region->height)); - p+=sizeof(region->height); - (void) memcpy(p,®ion->x,sizeof(region->x)); - p+=sizeof(region->x); - (void) memcpy(p,®ion->y,sizeof(region->y)); - p+=sizeof(region->y); - (void) memcpy(p,&length,sizeof(length)); - p+=sizeof(length); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(-1); - return(dpc_read(server_info->file,length,pixels)); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% RelinquishDistributePixelCache() frees resources acquired with -% OpenDistributePixelCache(). -% -% The format of the RelinquishDistributePixelCache method is: -% -% MagickBooleanType RelinquishDistributePixelCache( -% DistributeCacheInfo *server_info) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -*/ -MagickPrivate MagickBooleanType RelinquishDistributePixelCache( - DistributeCacheInfo *server_info) -{ - MagickBooleanType - status; - - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Delete distributed pixel cache. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - p=message; - *p++='d'; - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(MagickFalse); - count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); - if (count != (MagickOffsetType) sizeof(status)) - return(MagickFalse); - return(status); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% WriteDistributePixelCacheMetacontents() writes image metacontent to the -% specified region of the distributed pixel cache. -% -% The format of the WriteDistributePixelCacheMetacontents method is: -% -% MagickOffsetType WriteDistributePixelCacheMetacontents( -% DistributeCacheInfo *server_info,const RectangleInfo *region, -% const MagickSizeType length,const unsigned char *metacontent) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -% o image: the image. -% -% o region: write the metacontent to this region of the image. -% -% o length: the length in bytes of the metacontent. -% -% o metacontent: write these metacontent to the pixel cache. -% -*/ -MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent( - DistributeCacheInfo *server_info,const RectangleInfo *region, - const MagickSizeType length,const unsigned char *metacontent) -{ - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Write distributed pixel cache metacontent. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - assert(region != (RectangleInfo *) NULL); - assert(metacontent != (unsigned char *) NULL); - if (length > (MagickSizeType) SSIZE_MAX) - return(-1); - p=message; - *p++='W'; - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - (void) memcpy(p,®ion->width,sizeof(region->width)); - p+=sizeof(region->width); - (void) memcpy(p,®ion->height,sizeof(region->height)); - p+=sizeof(region->height); - (void) memcpy(p,®ion->x,sizeof(region->x)); - p+=sizeof(region->x); - (void) memcpy(p,®ion->y,sizeof(region->y)); - p+=sizeof(region->y); - (void) memcpy(p,&length,sizeof(length)); - p+=sizeof(length); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(-1); - return(dpc_send(server_info->file,length,metacontent)); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -+ 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 % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% WriteDistributePixelCachePixels() writes image pixels to the specified -% region of the distributed pixel cache. -% -% The format of the WriteDistributePixelCachePixels method is: -% -% MagickBooleanType WriteDistributePixelCachePixels( -% DistributeCacheInfo *server_info,const RectangleInfo *region, -% const MagickSizeType length,const unsigned char *restrict pixels) -% -% A description of each parameter follows: -% -% o server_info: the distributed cache info. -% -% o image: the image. -% -% o region: write the pixels to this region of the image. -% -% o length: the length in bytes of the pixels. -% -% o pixels: write these pixels to the pixel cache. -% -*/ -MagickPrivate MagickOffsetType WriteDistributePixelCachePixels( - DistributeCacheInfo *server_info,const RectangleInfo *region, - const MagickSizeType length,const unsigned char *restrict pixels) -{ - MagickOffsetType - count; - - register unsigned char - *p; - - unsigned char - message[MaxTextExtent]; - - /* - Write distributed pixel cache pixels. - */ - assert(server_info != (DistributeCacheInfo *) NULL); - assert(server_info->signature == MagickSignature); - assert(region != (RectangleInfo *) NULL); - assert(pixels != (const unsigned char *) NULL); - if (length > (MagickSizeType) SSIZE_MAX) - return(-1); - p=message; - *p++='w'; - (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); - p+=sizeof(server_info->session_key); - (void) memcpy(p,®ion->width,sizeof(region->width)); - p+=sizeof(region->width); - (void) memcpy(p,®ion->height,sizeof(region->height)); - p+=sizeof(region->height); - (void) memcpy(p,®ion->x,sizeof(region->x)); - p+=sizeof(region->x); - (void) memcpy(p,®ion->y,sizeof(region->y)); - p+=sizeof(region->y); - (void) memcpy(p,&length,sizeof(length)); - p+=sizeof(length); - count=dpc_send(server_info->file,p-message,message); - if (count != (MagickOffsetType) (p-message)) - return(-1); - return(dpc_send(server_info->file,length,pixels)); -} +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% DDDD IIIII SSSSS TTTTT RRRR IIIII BBBB U U TTTTT EEEEE % +% D D I SS T R R I B B U U T E % +% D D I SSS T RRRR I BBBB U U T EEE % +% D D I SS T R R I B B U U T E % +% DDDDA IIIII SSSSS T R R IIIII BBBB UUU T EEEEE % +% % +% CCCC AAA CCCC H H EEEEE % +% C A A C H H E % +% C AAAAA C HHHHH EEE % +% C A A C H H E % +% CCCC A A CCCC H H EEEEE % +% % +% % +% MagickCore Distributed Pixel Cache Methods % +% % +% Software Design % +% Cristy % +% January 2013 % +% % +% % +% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization % +% dedicated to making software imaging solutions freely available. % +% % +% You may not use this file except in compliance with the License. You may % +% obtain a copy of the License at % +% % +% http://www.imagemagick.org/script/license.php % +% % +% Unless required by applicable law or agreed to in writing, software % +% distributed under the License is distributed on an "AS IS" BASIS, % +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % +% See the License for the specific language governing permissions and % +% limitations under the License. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% A distributed pixel cache is an extension of the traditional pixel cache +% available on a single host. The distributed pixel cache may span multiple +% servers so that it can grow in size and transactional capacity to support +% very large images. Start up the pixel cache server on one or more machines. +% When you read or operate on an image and the local pixel cache resources are +% exhausted, ImageMagick contacts one or more of these remote pixel servers to +% store or retrieve pixels. +% +*/ + +/* + Include declarations. +*/ +#include "MagickCore/studio.h" +#include "MagickCore/cache.h" +#include "MagickCore/cache-private.h" +#include "MagickCore/distribute-cache.h" +#include "MagickCore/distribute-cache-private.h" +#include "MagickCore/exception.h" +#include "MagickCore/exception-private.h" +#include "MagickCore/geometry.h" +#include "MagickCore/image.h" +#include "MagickCore/image-private.h" +#include "MagickCore/list.h" +#include "MagickCore/locale_.h" +#include "MagickCore/memory_.h" +#include "MagickCore/nt-base-private.h" +#include "MagickCore/pixel.h" +#include "MagickCore/policy.h" +#include "MagickCore/random_.h" +#include "MagickCore/registry.h" +#include "MagickCore/splay-tree.h" +#include "MagickCore/string_.h" +#include "MagickCore/string-private.h" +#include "MagickCore/version.h" +#include "MagickCore/version-private.h" +#undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE +#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT) +#include +#include +#include +#include +#define CHAR_TYPE_CAST +#define CLOSE_SOCKET(socket) (void) close(socket) +#define HANDLER_RETURN_TYPE void * +#define HANDLER_RETURN_VALUE (void *) NULL +#define SOCKET_TYPE int +#define LENGTH_TYPE size_t +#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE +#elif defined(MAGICKCORE_WINDOWS_SUPPORT) +#define CHAR_TYPE_CAST (char *) +#define CLOSE_SOCKET(socket) (void) closesocket(socket) +#define HANDLER_RETURN_TYPE DWORD WINAPI +#define HANDLER_RETURN_VALUE 0 +#define SOCKET_TYPE SOCKET +#define LENGTH_TYPE int +#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE +#else +#define CLOSE_SOCKET(socket) +#define HANDLER_RETURN_TYPE void * +#define HANDLER_RETURN_VALUE (void *) NULL +#define SOCKET_TYPE int +#undef send +#undef recv +#define send(file,buffer,length,flags) 0 +#define recv(file,buffer,length,flags) 0 +#endif + +/* + Define declarations. +*/ +#define DPCHostname "127.0.0.1" +#define DPCPendingConnections 10 +#define DPCPort 6668 +#define DPCSessionKeyLength 8 +#ifndef MSG_NOSIGNAL +# define MSG_NOSIGNAL 0 +#endif + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% AcquireDistributeCacheInfo() allocates the DistributeCacheInfo structure. +% +% The format of the AcquireDistributeCacheInfo method is: +% +% DistributeCacheInfo *AcquireDistributeCacheInfo(ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o exception: return any errors or warnings in this structure. +% +*/ + +static inline MagickOffsetType dpc_read(int file,const MagickSizeType length, + unsigned char *restrict message) +{ + register MagickOffsetType + i; + + ssize_t + count; + +#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + magick_unreferenced(file); + magick_unreferenced(message); +#endif + + count=0; + for (i=0; i < (MagickOffsetType) length; i+=count) + { + count=recv(file,CHAR_TYPE_CAST message+i,(LENGTH_TYPE) MagickMin(length-i, + (MagickSizeType) SSIZE_MAX),0); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + return(i); +} + +static int ConnectPixelCacheServer(const char *hostname,const int port, + size_t *session_key,ExceptionInfo *exception) +{ +#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + char + service[MaxTextExtent]; + + const char + *shared_secret; + + int + status; + + SOCKET_TYPE + client_socket; + + ssize_t + count; + + struct addrinfo + hint, + *result; + + unsigned char + secret[MaxTextExtent]; + + /* + Connect to distributed pixel cache and get session key. + */ + *session_key=0; + shared_secret=GetPolicyValue("shared-secret"); + if (shared_secret == (const char *) NULL) + { + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, + "DistributedPixelCache","'%s'","shared secret expected"); + return(-1); + } +#if defined(MAGICKCORE_WINDOWS_SUPPORT) + NTInitializeWinsock(MagickTrue); +#endif + (void) ResetMagickMemory(&hint,0,sizeof(hint)); + hint.ai_family=AF_INET; + hint.ai_socktype=SOCK_STREAM; + hint.ai_flags=AI_PASSIVE; + (void) FormatLocaleString(service,MaxTextExtent,"%d",port); + status=getaddrinfo(hostname,service,&hint,&result); + if (status != 0) + { + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, + "DistributedPixelCache","'%s'",hostname); + return(-1); + } + client_socket=socket(result->ai_family,result->ai_socktype, + result->ai_protocol); + if (client_socket == -1) + { + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, + "DistributedPixelCache","'%s'",hostname); + return(-1); + } + status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen); + if (status == -1) + { + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, + "DistributedPixelCache","'%s'",hostname); + return(-1); + } + count=recv(client_socket,CHAR_TYPE_CAST secret,MaxTextExtent,0); + if (count != -1) + { + StringInfo + *nonce; + + nonce=AcquireStringInfo(count); + (void) memcpy(GetStringInfoDatum(nonce),secret,(size_t) count); + *session_key=GetMagickSignature(nonce); + nonce=DestroyStringInfo(nonce); + } + if (*session_key == 0) + { + CLOSE_SOCKET(client_socket); + client_socket=(SOCKET_TYPE) (-1); + } + return(client_socket); +#else + (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, + "DelegateLibrarySupportNotBuiltIn","distributed pixel cache"); + return(MagickFalse); +#endif +} + +static char *GetHostname(int *port,ExceptionInfo *exception) +{ + char + *host, + *hosts, + **hostlist; + + int + argc; + + register ssize_t + i; + + static size_t + id = 0; + + /* + Parse host list (e.g. 192.168.100.1:6668,192.168.100.2:6668). + */ + hosts=(char *) GetImageRegistry(StringRegistryType,"cache:hosts",exception); + if (hosts == (char *) NULL) + { + *port=DPCPort; + return(AcquireString(DPCHostname)); + } + (void) SubstituteString(&hosts,","," "); + hostlist=StringToArgv(hosts,&argc); + hosts=DestroyString(hosts); + if (hostlist == (char **) NULL) + { + *port=DPCPort; + return(AcquireString(DPCHostname)); + } + hosts=AcquireString(hostlist[(id++ % (argc-1))+1]); + for (i=0; i < (ssize_t) argc; i++) + hostlist[i]=DestroyString(hostlist[i]); + hostlist=(char **) RelinquishMagickMemory(hostlist); + (void) SubstituteString(&hosts,":"," "); + hostlist=StringToArgv(hosts,&argc); + if (hostlist == (char **) NULL) + { + *port=DPCPort; + return(AcquireString(DPCHostname)); + } + host=AcquireString(hostlist[1]); + if (hostlist[2] == (char *) NULL) + *port=DPCPort; + else + *port=StringToLong(hostlist[2]); + for (i=0; i < (ssize_t) argc; i++) + hostlist[i]=DestroyString(hostlist[i]); + hostlist=(char **) RelinquishMagickMemory(hostlist); + return(host); +} + +MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo( + ExceptionInfo *exception) +{ + char + *hostname; + + DistributeCacheInfo + *server_info; + + size_t + session_key; + + /* + Connect to the distributed pixel cache server. + */ + server_info=(DistributeCacheInfo *) AcquireMagickMemory(sizeof(*server_info)); + if (server_info == (DistributeCacheInfo *) NULL) + ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); + (void) ResetMagickMemory(server_info,0,sizeof(*server_info)); + server_info->signature=MagickSignature; + server_info->port=0; + hostname=GetHostname(&server_info->port,exception); + session_key=0; + server_info->file=ConnectPixelCacheServer(hostname,server_info->port, + &session_key,exception); + if (server_info->file == -1) + server_info=DestroyDistributeCacheInfo(server_info); + else + { + server_info->session_key=session_key; + (void) CopyMagickString(server_info->hostname,hostname,MaxTextExtent); + server_info->debug=IsEventLogging(); + } + hostname=DestroyString(hostname); + return(server_info); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DestroyDistributeCacheInfo() deallocates memory associated with an +% DistributeCacheInfo structure. +% +% The format of the DestroyDistributeCacheInfo method is: +% +% DistributeCacheInfo *DestroyDistributeCacheInfo( +% DistributeCacheInfo *server_info) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +*/ +MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( + DistributeCacheInfo *server_info) +{ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + if (server_info->file > 0) + CLOSE_SOCKET(server_info->file); + server_info->signature=(~MagickSignature); + server_info=(DistributeCacheInfo *) RelinquishMagickMemory(server_info); + return(server_info); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DistributePixelCacheServer() waits on the specified port for commands to +% create, read, update, or destroy a pixel cache. +% +% The format of the DistributePixelCacheServer() method is: +% +% void DistributePixelCacheServer(const int port) +% +% A description of each parameter follows: +% +% o port: connect the distributed pixel cache at this port. +% +% o exception: return any errors or warnings in this structure. +% +*/ + +static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry, + const size_t session_key) +{ + /* + Destroy distributed pixel cache. + */ + return(DeleteNodeFromSplayTree(registry,(const void *) session_key)); +} + +static inline MagickOffsetType dpc_send(int file,const MagickSizeType length, + const unsigned char *restrict message) +{ + MagickOffsetType + count; + + register MagickOffsetType + i; + +#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + magick_unreferenced(file); + magick_unreferenced(message); +#endif + + /* + Ensure a complete message is sent. + */ + count=0; + for (i=0; i < (MagickOffsetType) length; i+=count) + { + count=(MagickOffsetType) send(file,CHAR_TYPE_CAST message+i,(LENGTH_TYPE) + MagickMin(length-i,(MagickSizeType) SSIZE_MAX),MSG_NOSIGNAL); + if (count <= 0) + { + count=0; + if (errno != EINTR) + break; + } + } + return(i); +} + +static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file, + const size_t session_key,ExceptionInfo *exception) +{ + Image + *image; + + MagickBooleanType + status; + + MagickOffsetType + count; + + MagickSizeType + length; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Open distributed pixel cache. + */ + image=AcquireImage((ImageInfo *) NULL,exception); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(image->storage_class)+sizeof(image->colorspace)+ + sizeof(image->alpha_trait)+sizeof(image->read_mask)+ + sizeof(image->write_mask)+sizeof(image->columns)+sizeof(image->rows)+ + sizeof(image->number_channels)+MaxPixelChannels*sizeof(*image->channel_map)+ + sizeof(image->metacontent_extent); + count=dpc_read(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + /* + Deserialize the image attributes. + */ + p=message; + (void) memcpy(&image->storage_class,p,sizeof(image->storage_class)); + p+=sizeof(image->storage_class); + (void) memcpy(&image->colorspace,p,sizeof(image->colorspace)); + p+=sizeof(image->colorspace); + (void) memcpy(&image->alpha_trait,p,sizeof(image->alpha_trait)); + p+=sizeof(image->alpha_trait); + (void) memcpy(&image->read_mask,p,sizeof(image->read_mask)); + p+=sizeof(image->read_mask); + (void) memcpy(&image->write_mask,p,sizeof(image->write_mask)); + p+=sizeof(image->write_mask); + (void) memcpy(&image->columns,p,sizeof(image->columns)); + p+=sizeof(image->columns); + (void) memcpy(&image->rows,p,sizeof(image->rows)); + p+=sizeof(image->rows); + (void) memcpy(&image->number_channels,p,sizeof(image->number_channels)); + p+=sizeof(image->number_channels); + (void) memcpy(image->channel_map,p,MaxPixelChannels* + sizeof(*image->channel_map)); + p+=MaxPixelChannels*sizeof(*image->channel_map); + (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent)); + p+=sizeof(image->metacontent_extent); + if (SyncImagePixelCache(image,exception) == MagickFalse) + return(MagickFalse); + status=AddValueToSplayTree(registry,(const void *) session_key,image); + return(status); +} + +static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, + int file,const size_t session_key,ExceptionInfo *exception) +{ + const unsigned char + *metacontent; + + Image + *image; + + MagickOffsetType + count; + + MagickSizeType + length; + + RectangleInfo + region; + + register const Quantum + *p; + + register unsigned char + *q; + + unsigned char + message[MaxTextExtent]; + + /* + Read distributed pixel cache metacontent. + */ + image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); + count=dpc_read(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + q=message; + (void) memcpy(®ion.width,q,sizeof(region.width)); + q+=sizeof(region.width); + (void) memcpy(®ion.height,q,sizeof(region.height)); + q+=sizeof(region.height); + (void) memcpy(®ion.x,q,sizeof(region.x)); + q+=sizeof(region.x); + (void) memcpy(®ion.y,q,sizeof(region.y)); + q+=sizeof(region.y); + (void) memcpy(&length,q,sizeof(length)); + q+=sizeof(length); + p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, + exception); + if (p == (const Quantum *) NULL) + return(MagickFalse); + metacontent=(const unsigned char *) GetVirtualMetacontent(image); + count=dpc_send(file,length,metacontent); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(MagickTrue); +} + +static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry, + int file,const size_t session_key,ExceptionInfo *exception) +{ + Image + *image; + + MagickOffsetType + count; + + MagickSizeType + length; + + RectangleInfo + region; + + register const Quantum + *p; + + register unsigned char + *q; + + unsigned char + message[MaxTextExtent]; + + /* + Read distributed pixel cache pixels. + */ + image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); + count=dpc_read(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + q=message; + (void) memcpy(®ion.width,q,sizeof(region.width)); + q+=sizeof(region.width); + (void) memcpy(®ion.height,q,sizeof(region.height)); + q+=sizeof(region.height); + (void) memcpy(®ion.x,q,sizeof(region.x)); + q+=sizeof(region.x); + (void) memcpy(®ion.y,q,sizeof(region.y)); + q+=sizeof(region.y); + (void) memcpy(&length,q,sizeof(length)); + q+=sizeof(length); + p=GetVirtualPixels(image,region.x,region.y,region.width,region.height, + exception); + if (p == (const Quantum *) NULL) + return(MagickFalse); + count=dpc_send(file,length,(unsigned char *) p); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(MagickTrue); +} + +static void *RelinquishImageRegistry(void *image) +{ + return((void *) DestroyImageList((Image *) image)); +} + +static MagickBooleanType WriteDistributeCacheMetacontent( + SplayTreeInfo *registry,int file,const size_t session_key, + ExceptionInfo *exception) +{ + Image + *image; + + MagickOffsetType + count; + + MagickSizeType + length; + + RectangleInfo + region; + + register Quantum + *q; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent], + *metacontent; + + /* + Write distributed pixel cache metacontent. + */ + image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); + count=dpc_read(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + p=message; + (void) memcpy(®ion.width,p,sizeof(region.width)); + p+=sizeof(region.width); + (void) memcpy(®ion.height,p,sizeof(region.height)); + p+=sizeof(region.height); + (void) memcpy(®ion.x,p,sizeof(region.x)); + p+=sizeof(region.x); + (void) memcpy(®ion.y,p,sizeof(region.y)); + p+=sizeof(region.y); + (void) memcpy(&length,p,sizeof(length)); + p+=sizeof(length); + q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, + exception); + if (q == (Quantum *) NULL) + return(MagickFalse); + metacontent=(unsigned char *) GetAuthenticMetacontent(image); + count=dpc_read(file,length,metacontent); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(SyncAuthenticPixels(image,exception)); +} + +static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, + int file,const size_t session_key,ExceptionInfo *exception) +{ + Image + *image; + + MagickOffsetType + count; + + MagickSizeType + length; + + RectangleInfo + region; + + register Quantum + *q; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Write distributed pixel cache pixels. + */ + image=(Image *) GetValueFromSplayTree(registry,(const void *) session_key); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); + count=dpc_read(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + p=message; + (void) memcpy(®ion.width,p,sizeof(region.width)); + p+=sizeof(region.width); + (void) memcpy(®ion.height,p,sizeof(region.height)); + p+=sizeof(region.height); + (void) memcpy(®ion.x,p,sizeof(region.x)); + p+=sizeof(region.x); + (void) memcpy(®ion.y,p,sizeof(region.y)); + p+=sizeof(region.y); + (void) memcpy(&length,p,sizeof(length)); + p+=sizeof(length); + q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, + exception); + if (q == (Quantum *) NULL) + return(MagickFalse); + count=dpc_read(file,length,(unsigned char *) q); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(SyncAuthenticPixels(image,exception)); +} + +static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket) +{ + const char + *shared_secret; + + ExceptionInfo + *exception; + + MagickBooleanType + status; + + MagickOffsetType + count; + + register unsigned char + *p; + + RandomInfo + *random_info; + + size_t + key, + session_key; + + SOCKET_TYPE + client_socket; + + SplayTreeInfo + *registry; + + StringInfo + *secret; + + unsigned char + command, + session[2*MaxTextExtent]; + + /* + Distributed pixel cache client. + */ + shared_secret=GetPolicyValue("shared-secret"); + if (shared_secret == (const char *) NULL) + ThrowFatalException(CacheFatalError,"shared secret expected"); + p=session; + (void) CopyMagickString((char *) p,shared_secret,MaxTextExtent); + p+=strlen(shared_secret); + random_info=AcquireRandomInfo(); + secret=GetRandomKey(random_info,DPCSessionKeyLength); + (void) memcpy(p,GetStringInfoDatum(secret),DPCSessionKeyLength); + session_key=GetMagickSignature(secret); + random_info=DestroyRandomInfo(random_info); + exception=AcquireExceptionInfo(); + registry=NewSplayTree((int (*)(const void *,const void *)) NULL, + (void *(*)(void *)) NULL,RelinquishImageRegistry); + client_socket=(*(SOCKET_TYPE *) socket); + count=dpc_send(client_socket,DPCSessionKeyLength,GetStringInfoDatum(secret)); + secret=DestroyStringInfo(secret); + for ( ; ; ) + { + count=dpc_read(client_socket,1,(unsigned char *) &command); + if (count <= 0) + break; + count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key); + if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key)) + break; + status=MagickFalse; + switch (command) + { + case 'o': + { + status=OpenDistributeCache(registry,client_socket,session_key, + exception); + count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status); + break; + } + case 'r': + { + status=ReadDistributeCachePixels(registry,client_socket,session_key, + exception); + break; + } + case 'R': + { + status=ReadDistributeCacheMetacontent(registry,client_socket, + session_key,exception); + break; + } + case 'w': + { + status=WriteDistributeCachePixels(registry,client_socket,session_key, + exception); + break; + } + case 'W': + { + status=WriteDistributeCacheMetacontent(registry,client_socket, + session_key,exception); + break; + } + case 'd': + { + status=DestroyDistributeCache(registry,session_key); + break; + } + default: + break; + } + if (status == MagickFalse) + break; + if (command == 'd') + break; + } + count=dpc_send(client_socket,sizeof(status),(unsigned char *) &status); + CLOSE_SOCKET(client_socket); + exception=DestroyExceptionInfo(exception); + registry=DestroySplayTree(registry); + return(HANDLER_RETURN_VALUE); +} + +MagickExport void DistributePixelCacheServer(const int port, + ExceptionInfo *exception) +{ +#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + char + service[MaxTextExtent]; + + int + status; + +#if defined(MAGICKCORE_THREAD_SUPPORT) + pthread_attr_t + attributes; + + pthread_t + threads; +#elif defined(MAGICKCORE_WINDOWS_SUPPORT) + DWORD + threadID; +#else + Not implemented! +#endif + + register struct addrinfo + *p; + + SOCKET_TYPE + server_socket; + + struct addrinfo + hint, + *result; + + struct sockaddr_in + address; + + /* + Launch distributed pixel cache server. + */ + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickSignature); +#if defined(MAGICKCORE_WINDOWS_SUPPORT) + NTInitializeWinsock(MagickFalse); +#endif + (void) ResetMagickMemory(&hint,0,sizeof(hint)); + hint.ai_family=AF_INET; + hint.ai_socktype=SOCK_STREAM; + hint.ai_flags=AI_PASSIVE; + (void) FormatLocaleString(service,MaxTextExtent,"%d",port); + status=getaddrinfo((const char *) NULL,service,&hint,&result); + if (status != 0) + ThrowFatalException(CacheFatalError,"UnableToListen"); + server_socket=(SOCKET_TYPE) 0; + for (p=result; p != (struct addrinfo *) NULL; p=p->ai_next) + { + int + one; + + server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol); + if (server_socket == -1) + continue; + one=1; + status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR, + CHAR_TYPE_CAST &one,(socklen_t) sizeof(one)); + if (status == -1) + { + CLOSE_SOCKET(server_socket); + continue; + } + status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen); + if (status == -1) + { + CLOSE_SOCKET(server_socket); + continue; + } + break; + } + if (p == (struct addrinfo *) NULL) + ThrowFatalException(CacheFatalError,"UnableToBind"); + freeaddrinfo(result); + status=listen(server_socket,DPCPendingConnections); + if (status != 0) + ThrowFatalException(CacheFatalError,"UnableToListen"); +#if defined(MAGICKCORE_THREAD_SUPPORT) + pthread_attr_init(&attributes); +#endif + for ( ; ; ) + { + SOCKET_TYPE + client_socket; + + socklen_t + length; + + length=(socklen_t) sizeof(address); + client_socket=accept(server_socket,(struct sockaddr *) &address,&length); + if (client_socket == -1) + ThrowFatalException(CacheFatalError,"UnableToEstablishConnection"); +#if defined(MAGICKCORE_THREAD_SUPPORT) + status=pthread_create(&threads,&attributes,DistributePixelCacheClient, + (void *) &client_socket); + if (status == -1) + ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); +#elif defined(MAGICKCORE_WINDOWS_SUPPORT) + if (CreateThread(0,0,DistributePixelCacheClient,(void*) &client_socket,0, + &threadID) == (HANDLE) NULL) + ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); +#else + Not implemented! +#endif + } +#else + magick_unreferenced(port); + magick_unreferenced(exception); + ThrowFatalException(MissingDelegateError,"DelegateLibrarySupportNotBuiltIn"); +#endif +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ G e t D i s t r i b u t e C a c h e F i l e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GetDistributeCacheFile() returns the file associated with this +% DistributeCacheInfo structure. +% +% The format of the GetDistributeCacheFile method is: +% +% int GetDistributeCacheFile(const DistributeCacheInfo *server_info) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +*/ +MagickPrivate int GetDistributeCacheFile(const DistributeCacheInfo *server_info) +{ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + return(server_info->file); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GetDistributeCacheHostname() returns the hostname associated with this +% DistributeCacheInfo structure. +% +% The format of the GetDistributeCacheHostname method is: +% +% const char *GetDistributeCacheHostname( +% const DistributeCacheInfo *server_info) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +*/ +MagickPrivate const char *GetDistributeCacheHostname( + const DistributeCacheInfo *server_info) +{ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + return(server_info->hostname); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ G e t D i s t r i b u t e C a c h e P o r t % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GetDistributeCachePort() returns the port associated with this +% DistributeCacheInfo structure. +% +% The format of the GetDistributeCachePort method is: +% +% int GetDistributeCachePort(const DistributeCacheInfo *server_info) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +*/ +MagickPrivate int GetDistributeCachePort(const DistributeCacheInfo *server_info) +{ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + return(server_info->port); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ O p e n D i s t r i b u t e P i x e l C a c h e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% OpenDistributePixelCache() opens a pixel cache on a remote server. +% +% The format of the OpenDistributePixelCache method is: +% +% MagickBooleanType *OpenDistributePixelCache( +% DistributeCacheInfo *server_info,Image *image) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +% o image: the image. +% +*/ +MagickPrivate MagickBooleanType OpenDistributePixelCache( + DistributeCacheInfo *server_info,Image *image) +{ + MagickBooleanType + status; + + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Open distributed pixel cache. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + p=message; + *p++='o'; /* open */ + /* + Serialize image attributes (see ValidatePixelCacheMorphology()). + */ + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + (void) memcpy(p,&image->storage_class,sizeof(image->storage_class)); + p+=sizeof(image->storage_class); + (void) memcpy(p,&image->colorspace,sizeof(image->colorspace)); + p+=sizeof(image->colorspace); + (void) memcpy(p,&image->alpha_trait,sizeof(image->alpha_trait)); + p+=sizeof(image->alpha_trait); + (void) memcpy(p,&image->read_mask,sizeof(image->read_mask)); + p+=sizeof(image->read_mask); + (void) memcpy(p,&image->write_mask,sizeof(image->write_mask)); + p+=sizeof(image->write_mask); + (void) memcpy(p,&image->columns,sizeof(image->columns)); + p+=sizeof(image->columns); + (void) memcpy(p,&image->rows,sizeof(image->rows)); + p+=sizeof(image->rows); + (void) memcpy(p,&image->number_channels,sizeof(image->number_channels)); + p+=sizeof(image->number_channels); + (void) memcpy(p,image->channel_map,MaxPixelChannels* + sizeof(*image->channel_map)); + p+=MaxPixelChannels*sizeof(*image->channel_map); + (void) memcpy(p,&image->metacontent_extent,sizeof(image->metacontent_extent)); + p+=sizeof(image->metacontent_extent); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(MagickFalse); + status=MagickFalse; + count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); + if (count != (MagickOffsetType) sizeof(status)) + return(MagickFalse); + return(status); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ReadDistributePixelCacheMetacontents() reads metacontent from the specified +% region of the distributed pixel cache. +% +% The format of the ReadDistributePixelCacheMetacontents method is: +% +% MagickOffsetType ReadDistributePixelCacheMetacontents( +% DistributeCacheInfo *server_info,const RectangleInfo *region, +% const MagickSizeType length,unsigned char *metacontent) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +% o image: the image. +% +% o region: read the metacontent from this region of the image. +% +% o length: the length in bytes of the metacontent. +% +% o metacontent: read these metacontent from the pixel cache. +% +*/ +MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent( + DistributeCacheInfo *server_info,const RectangleInfo *region, + const MagickSizeType length,unsigned char *metacontent) +{ + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Read distributed pixel cache metacontent. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + assert(region != (RectangleInfo *) NULL); + assert(metacontent != (unsigned char *) NULL); + if (length > (MagickSizeType) SSIZE_MAX) + return(-1); + p=message; + *p++='R'; + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + (void) memcpy(p,®ion->width,sizeof(region->width)); + p+=sizeof(region->width); + (void) memcpy(p,®ion->height,sizeof(region->height)); + p+=sizeof(region->height); + (void) memcpy(p,®ion->x,sizeof(region->x)); + p+=sizeof(region->x); + (void) memcpy(p,®ion->y,sizeof(region->y)); + p+=sizeof(region->y); + (void) memcpy(p,&length,sizeof(length)); + p+=sizeof(length); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(-1); + return(dpc_read(server_info->file,length,metacontent)); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% ReadDistributePixelCachePixels() reads pixels from the specified region of +% the distributed pixel cache. +% +% The format of the ReadDistributePixelCachePixels method is: +% +% MagickOffsetType ReadDistributePixelCachePixels( +% DistributeCacheInfo *server_info,const RectangleInfo *region, +% const MagickSizeType length,unsigned char *restrict pixels) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +% o image: the image. +% +% o region: read the pixels from this region of the image. +% +% o length: the length in bytes of the pixels. +% +% o pixels: read these pixels from the pixel cache. +% +*/ +MagickPrivate MagickOffsetType ReadDistributePixelCachePixels( + DistributeCacheInfo *server_info,const RectangleInfo *region, + const MagickSizeType length,unsigned char *restrict pixels) +{ + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Read distributed pixel cache pixels. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + assert(region != (RectangleInfo *) NULL); + assert(pixels != (unsigned char *) NULL); + if (length > (MagickSizeType) SSIZE_MAX) + return(-1); + p=message; + *p++='r'; + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + (void) memcpy(p,®ion->width,sizeof(region->width)); + p+=sizeof(region->width); + (void) memcpy(p,®ion->height,sizeof(region->height)); + p+=sizeof(region->height); + (void) memcpy(p,®ion->x,sizeof(region->x)); + p+=sizeof(region->x); + (void) memcpy(p,®ion->y,sizeof(region->y)); + p+=sizeof(region->y); + (void) memcpy(p,&length,sizeof(length)); + p+=sizeof(length); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(-1); + return(dpc_read(server_info->file,length,pixels)); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% RelinquishDistributePixelCache() frees resources acquired with +% OpenDistributePixelCache(). +% +% The format of the RelinquishDistributePixelCache method is: +% +% MagickBooleanType RelinquishDistributePixelCache( +% DistributeCacheInfo *server_info) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +*/ +MagickPrivate MagickBooleanType RelinquishDistributePixelCache( + DistributeCacheInfo *server_info) +{ + MagickBooleanType + status; + + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Delete distributed pixel cache. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + p=message; + *p++='d'; + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(MagickFalse); + count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); + if (count != (MagickOffsetType) sizeof(status)) + return(MagickFalse); + return(status); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% WriteDistributePixelCacheMetacontents() writes image metacontent to the +% specified region of the distributed pixel cache. +% +% The format of the WriteDistributePixelCacheMetacontents method is: +% +% MagickOffsetType WriteDistributePixelCacheMetacontents( +% DistributeCacheInfo *server_info,const RectangleInfo *region, +% const MagickSizeType length,const unsigned char *metacontent) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +% o image: the image. +% +% o region: write the metacontent to this region of the image. +% +% o length: the length in bytes of the metacontent. +% +% o metacontent: write these metacontent to the pixel cache. +% +*/ +MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent( + DistributeCacheInfo *server_info,const RectangleInfo *region, + const MagickSizeType length,const unsigned char *metacontent) +{ + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Write distributed pixel cache metacontent. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + assert(region != (RectangleInfo *) NULL); + assert(metacontent != (unsigned char *) NULL); + if (length > (MagickSizeType) SSIZE_MAX) + return(-1); + p=message; + *p++='W'; + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + (void) memcpy(p,®ion->width,sizeof(region->width)); + p+=sizeof(region->width); + (void) memcpy(p,®ion->height,sizeof(region->height)); + p+=sizeof(region->height); + (void) memcpy(p,®ion->x,sizeof(region->x)); + p+=sizeof(region->x); + (void) memcpy(p,®ion->y,sizeof(region->y)); + p+=sizeof(region->y); + (void) memcpy(p,&length,sizeof(length)); + p+=sizeof(length); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(-1); + return(dpc_send(server_info->file,length,metacontent)); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ 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 % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% WriteDistributePixelCachePixels() writes image pixels to the specified +% region of the distributed pixel cache. +% +% The format of the WriteDistributePixelCachePixels method is: +% +% MagickBooleanType WriteDistributePixelCachePixels( +% DistributeCacheInfo *server_info,const RectangleInfo *region, +% const MagickSizeType length,const unsigned char *restrict pixels) +% +% A description of each parameter follows: +% +% o server_info: the distributed cache info. +% +% o image: the image. +% +% o region: write the pixels to this region of the image. +% +% o length: the length in bytes of the pixels. +% +% o pixels: write these pixels to the pixel cache. +% +*/ +MagickPrivate MagickOffsetType WriteDistributePixelCachePixels( + DistributeCacheInfo *server_info,const RectangleInfo *region, + const MagickSizeType length,const unsigned char *restrict pixels) +{ + MagickOffsetType + count; + + register unsigned char + *p; + + unsigned char + message[MaxTextExtent]; + + /* + Write distributed pixel cache pixels. + */ + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickSignature); + assert(region != (RectangleInfo *) NULL); + assert(pixels != (const unsigned char *) NULL); + if (length > (MagickSizeType) SSIZE_MAX) + return(-1); + p=message; + *p++='w'; + (void) memcpy(p,&server_info->session_key,sizeof(server_info->session_key)); + p+=sizeof(server_info->session_key); + (void) memcpy(p,®ion->width,sizeof(region->width)); + p+=sizeof(region->width); + (void) memcpy(p,®ion->height,sizeof(region->height)); + p+=sizeof(region->height); + (void) memcpy(p,®ion->x,sizeof(region->x)); + p+=sizeof(region->x); + (void) memcpy(p,®ion->y,sizeof(region->y)); + p+=sizeof(region->y); + (void) memcpy(p,&length,sizeof(length)); + p+=sizeof(length); + count=dpc_send(server_info->file,p-message,message); + if (count != (MagickOffsetType) (p-message)) + return(-1); + return(dpc_send(server_info->file,length,pixels)); +} diff --git a/MagickCore/nt-base.c b/MagickCore/nt-base.c index 80bc6122a..79cc0e4b7 100644 --- a/MagickCore/nt-base.c +++ b/MagickCore/nt-base.c @@ -68,7 +68,7 @@ Define declarations. */ #if !defined(MAP_FAILED) -#define MAP_FAILED ((void *) -1) +#define MAP_FAILED ((void *)(LONG_PTR)-1) #endif /* -- 2.40.0