/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % 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 % % John Cristy % % January 2013 % % % % % % Copyright 1999-2013 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/distribute-cache.h" #include "MagickCore/distribute-cache-private.h" #include "MagickCore/exception.h" #include "MagickCore/exception-private.h" #include "MagickCore/memory_.h" #include "MagickCore/registry.h" #if defined(MAGICKCORE_HAVE_SOCKET) #include #include #include #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. % */ MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo( ExceptionInfo *exception) { #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_HAVE_PTHREAD) char *host, **hosts; const char *value; DistributeCacheInfo *distribute_cache_info; distribute_cache_info=(DistributeCacheInfo *) NULL; distribute_cache_info=(DistributeCacheInfo *) AcquireMagickMemory( sizeof(*distribute_cache_info)); if (distribute_cache_info == (DistributeCacheInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(distribute_cache_info,0, sizeof(*distribute_cache_info)); distribute_cache_info->signature=MagickSignature; value=GetImageRegistry(StringRegistryType,"cache:hosts",exception); if (value == (const char *) NULL) value=(const char *) "127.0.0.1"; host=AcquireString(value); if (host == (char *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); SubstituteString(&host,",","\n"); hosts=StringToList(host); if (hosts == (char **) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); hosts=DestroyStringList(hosts); return(distribute_cache_info); #else return((DistributeCacheInfo *) NULL); #endif } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 *distribute_cache_info) % % A description of each parameter follows: % % o distribute_cache_info: the distributed cache info. % */ MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( DistributeCacheInfo *distribute_cache_info) { assert(distribute_cache_info != (DistributeCacheInfo *) NULL); assert(distribute_cache_info->signature == MagickSignature); #if defined(MAGICKCORE_HAVE_SOCKET) #endif distribute_cache_info->signature=(~MagickSignature); distribute_cache_info=(DistributeCacheInfo *) RelinquishMagickMemory(distribute_cache_info); return(distribute_cache_info); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + P i x e l C a c h e S e r v e r % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PixelCacheServer() waits on the specified port for commands to create, read, % update, or destroy a pixel cache. % % The format of the PixelCacheServer() method is: % % void PixelCacheServer(const size_t port) % % A description of each parameter follows: % % o port: connect the distributed pixel cache at this port. % */ MagickExport void PixelCacheServer(const size_t port) { #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_HAVE_PTHREAD) char buffer[MaxTextExtent]; int cache_socket, cache_client, status; socklen_t length, one; ssize_t count; struct sockaddr_in address; cache_socket=socket(AF_INET,SOCK_STREAM,0); if (cache_socket == -1) { perror("Distributed pixel cache: server socket"); exit(1); } one=1; status=setsockopt(cache_socket,SOL_SOCKET,SO_REUSEADDR,&one,(socklen_t) sizeof(one)); if (status == -1) { perror("Distributed pixel cache: server setsockopt"); exit(1); } (void) ResetMagickMemory(&address,0,sizeof(address)); address.sin_family=AF_INET; address.sin_port=htons(port); address.sin_addr.s_addr=INADDR_ANY; status=bind(cache_socket,(struct sockaddr *) &address,(socklen_t) sizeof(address)); if (status == -1) { perror("Distributed pixel cache: server bind"); exit(1); } status=listen(cache_socket,5); if (status == -1) { perror("Distributed pixel cache: server listen"); exit(1); } (void) fprintf(stdout, "Distributed pixel cache server: waiting for client on port %d\n",(int) port); (void) fflush(stdout); for ( ; ; ) { length=(socklen_t) sizeof(address); cache_client=accept(cache_socket,(struct sockaddr *) &address,&length); (void) fprintf(stdout,"Connection from (%s, %d)\n", inet_ntoa(address.sin_addr),(int) ntohs(address.sin_port)); count=recv(cache_client,buffer,1,0); buffer[count]='\0'; switch (*buffer) { case 'c': { /* Create cache. */ break; } case 'r': { /* Read cache. */ break; } case 'u': { /* Update cache. */ break; } case 'd': { /* Delete cache. */ break; } } } #else (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, "DelegateLibrarySupportNotBuiltIn","'%s' (socket)",image_info->filename); #endif }