Logo Search packages:      
Sourcecode: adun.app version File versions  Download package

AdunIOManager.m

/*
   Project: Adun

   Copyright (C) 2005 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#include "AdunKernel/AdunIOManager.h"

static id ioManager;

00026 @implementation AdIOManager

/*
 * Connect to and disconnecting from the local
 * AdServer instance
 */

- (BOOL) connectToServer: (NSError**) error;
{
      id reason, userInfo;

      NSDebugLLog(@"Server", @"Server debug - Attempting to  connecting to AdServer using message ports");

      serverConnection = [NSConnection connectionWithRegisteredName: @"AdunServer" 
                        host: nil 
                        usingNameServer: [NSMessagePortNameServer sharedInstance]];
      
      if(serverConnection == nil)
      {
            NSDebugLLog(@"Server", @"Server debug - Unable to find AdunServer on message ports.");
            NSDebugLLog(@"Server", @"Server debug - Checking for a distributed computing enabled server");
            serverConnection = [NSConnection connectionWithRegisteredName: @"AdunServer" 
                        host: nil 
                        usingNameServer: [NSSocketPortNameServer sharedInstance]];
      }

      if(serverConnection != nil)
      {
            [serverConnection retain];
            serverProxy = [[serverConnection rootProxy] retain];
      
            NSDebugLLog(@"Server", @"Server debug - Connected to server");
            NSDebugLLog(@"Server" ,@"Server debug - Stats are %@", [[serverProxy connectionForProxy] statistics]);

            //supply interface using an NSProtocolChecker
      
            checkerInterface = [NSProtocolChecker protocolCheckerWithTarget: self 
                                    protocol: @protocol(AdCommandInterface)];
            [checkerInterface retain];
            [serverProxy useInterface: checkerInterface forProcess:  [[NSProcessInfo processInfo] processIdentifier]];
            return YES;
      }
      else
      {
            reason = @"Unable to connect to server!";
            userInfo = [NSMutableDictionary dictionary];
            [userInfo setObject: reason forKey: NSLocalizedDescriptionKey];
            *error = [NSError errorWithDomain: @"AdCoreErrorDomain" 
                        code: 1
                        userInfo: userInfo];
            return NO;
      }     
}

00080 - (void) acceptRequests
{
      int pid;

      if(serverConnection != nil)
      {
            pid = [[NSProcessInfo processInfo] processIdentifier];
            [serverProxy acceptingRequests: pid];
      }
}

00091 - (void) closeConnection: (NSError*) error
{
      NSDebugLLog(@"Server", @"Server debug - Closing connection to server. Statistics are %@", 
                  [[serverProxy connectionForProxy] statistics]);
      NSDebugLLog(@"Server", @"Server debug - Connection %@", [serverProxy connectionForProxy]);
      [serverProxy closeConnectionForProcess: [[NSProcessInfo processInfo] processIdentifier]
                  error: error];
      [serverProxy release];
      [serverConnection invalidate];
      [serverConnection release];
      [checkerInterface release];
      serverProxy = nil;
}

00105 - (void) sendControllerResults: (NSArray*) results
{
      [serverProxy controllerData: results 
            forProcess: [[NSProcessInfo processInfo] processIdentifier]];
}

/*
 * Setup Methods
 */

00115 + (id) appIOManager
{
      if(ioManager == nil)
            ioManager = [[AdIOManager alloc]
                        initWithEnvironment: [AdEnvironment globalEnvironment]];
      return ioManager;
}

- (void) _setupAdunDirectories
{
      NSString *temp;
      BOOL isDir;
      NSString *currentDir;
      
      userHome = NSHomeDirectory();
      
      GSPrintf(stderr, @"\nHome directory is %@\n", userHome);

      //get process information and setup user directory information

      adunInfo = [NSProcessInfo processInfo];
      currentDir = [self currentDirectoryPath];
      adunUserDir =  [[userHome stringByAppendingPathComponent: @"adun"] retain];
      //FIXME: This should be provided from the command line or from UL
      resultsDir = [[adunUserDir stringByAppendingPathComponent: @"Database/Simulations/"] retain];
      controllerDir = [[adunUserDir stringByAppendingPathComponent: @"Plugins/Controllers"] retain];
      
      GSPrintf(stderr, @"Current Dir: %@\n", currentDir);
      GSPrintf(stderr, @"User Dir: %@\n", adunUserDir);
      GSPrintf(stderr, @"Controller Dir: %@\n", controllerDir);
}

00147 - (id) initWithEnvironment: (id) object observe: (BOOL) value
{
      if(ioManager != nil)
            return ioManager;

      if(self = [super initWithEnvironment: object observe: value])
      {
            if(ioManager == nil)
                  ioManager = self;

            fileManager = [NSFileManager defaultManager];
            fileStreams = [NSMutableDictionary new];
            [fileStreams setObject: [NSValue valueWithPointer: stdout] forKey: @"Standard"];
            [fileStreams setObject: [NSValue valueWithPointer: stdout] forKey: @"Error"];
            simulationData = [NSMutableDictionary new]; 
            outputDir = nil;
            controllerOutputDir = nil;
            
            [self _setupAdunDirectories];
      }

      return self;
}

00171 - (id) initWithEnvironment: (id) object
{
      return [self initWithEnvironment: object observe: YES];
}

- (id) init
{
      return [self initWithEnvironment: nil];
}                 

- (void) dealloc
{

      [self closeAllStreams];
      [fileStreams release];
      if(serverProxy != nil)
            [self closeConnection: nil];
      [adunUserDir release];
      [resultsDir release];
      [controllerDir release];
      [outputDir release];
      [controllerOutputDir release];
      [simulationData release];
      ioManager = nil;
      [super dealloc];
}

/* 
 * Loading of simulation data
 */

- (NSMutableArray*) _convertULSystemsToDataSources: (NSArray*) ulSystems
{
      int i;
      id dataSourceArray, dataSource;

      NSDebugLLog(@"AdIOManager", @"Creating data sources");
      dataSourceArray = [NSMutableArray arrayWithCapacity: 1];
      for(i=0; i<(int)[ulSystems count]; i++)
      {
            dataSource = [AdDataSource dataSourceForULSystem: [ulSystems objectAtIndex: i] 
                        withEnvironment: environment];
            [dataSourceArray addObject: dataSource];
      
            //FIXME: the following is a hack until its decided how systems should be described,
            //what keywords should be used to describe them, how many there should be etc. etc.
      
            if(i==0)
                  [dataSource setValue: @"Solute" forKey: @"Type"];
            if(i==1)
                  [dataSource setValue: @"Solvent" forKey: @"Type"];
      }

      NSDebugLLog(@"AdIOManager", @"Data Sources are %@", dataSourceArray);

      return dataSourceArray;
}

- (void) _loadServerData
{
      int pid;
      id options, ulSystems, dataSourceArray;

      pid = [[NSProcessInfo processInfo] processIdentifier];

      if(serverConnection == nil)
            [NSException raise: NSInternalInconsistencyException
                  format: @"Not connected to server"];

      NSDebugLLog(@"Server", @"Server debug - Retrieving options");
      if((options = [serverProxy getOptionsForProcess: pid]) == nil)
            [NSException raise: NSInternalInconsistencyException
                  format: @"Server returned nil for options"];
      NSDebugLLog(@"Server", @"Server debug - Options are %@", options);
      
      NSDebugLLog(@"Server", @"Server debug - Retrieving systems");
      if((ulSystems = [serverProxy getSystemsForProcess: pid]) == nil)
            [NSException raise: NSInternalInconsistencyException
                  format: @"Server returned nil for system"];
      
      dataSourceArray = [self _convertULSystemsToDataSources: ulSystems];
      [simulationData setObject: dataSourceArray forKey: @"systemDataSources"];
      [simulationData setObject: options forKey: @"options"];
}

- (void) _loadCommandLineData: (NSDictionary*) dict
{
      NSString* templateFile, *systemFile;
      NSEnumerator* systemEnum;
      NSMutableArray* ulSystems = [NSMutableArray array];
      NSKeyedUnarchiver* unarchiver;
      id template, system, systemFiles;
      id dataSourceArray;
      
      //read in the data

      templateFile = [dict objectForKey: @"templateFile"];
      NSDebugLLog(@"AdIOManager", @"Retrieving template from file %@", templateFile);
      template = [NSKeyedUnarchiver unarchiveObjectWithFile: templateFile];
      if(template == nil)
            [NSException raise: NSInternalInconsistencyException
                  format: [NSString stringWithFormat: 
                  @"Could not load template from %@", templateFile]];
      else        
            NSDebugLLog(@"AdIOManager", @"Complete. Unarchived template %@", template);

      systemFiles = [dict objectForKey: @"systemFiles"];
      NSDebugLLog(@"AdIOManager", @"Retrieving system from files %@", systemFiles);
      systemEnum = [systemFiles objectEnumerator];
      while(systemFile = [systemEnum nextObject])
      {
            system = [NSKeyedUnarchiver unarchiveObjectWithFile: systemFile];
            if(system == nil)
                  [NSException raise: NSInternalInconsistencyException
                        format: [NSString stringWithFormat: 
                        @"Could not load template from %@", templateFile]];
            else        
                  NSDebugLLog(@"AdIOManager", @"Complete. Unarchived system %@", system);
            [ulSystems addObject: system];
      }     
            
      dataSourceArray = [self _convertULSystemsToDataSources: ulSystems];
      [simulationData setObject: dataSourceArray forKey: @"systemDataSources"];
      [simulationData setObject: template forKey: @"options"];
      NSDebugLLog(@"AdIOManager", @"Extraction and conversion complete");
}

00298 - (id) loadProcessData: (NSDictionary*) dict
{
      NSString* inputSourceName;

      //options contains information on where to load the input from

      if((inputSourceName = [dict valueForKey: @"inputSourceName"]) == nil)
            [NSException raise: NSInvalidArgumentException
                  format: @"An input source (CommandLine or Server) must be specified"];

      if([inputSourceName isEqual: @"CommandLine"])
            [self _loadCommandLineData: dict];
      else if([inputSourceName isEqual: @"Server"])
            [self _loadServerData];
      else
            [NSException raise: NSInvalidArgumentException
                  format: [NSString stringWithFormat:
                   @"Invalid input source (%@) specified. Valid options are CommandLine or Server", inputSourceName]];
      
      return nil;
}

/*
 * Output directories
 */

- (void) _createSimulationOutputDirectory
{
      NSString *temp;
      BOOL isDir;
      id logFile, oldLogFile;
      NSString* contents;
      
      NSLog(@"Output Dir is %@", outputDir);
      
      if(!([fileManager fileExistsAtPath: outputDir]))
      {
            NSWarnLog(@"Directory %@ doesn't exist. Creating it.\n", outputDir);
            [fileManager createDirectoryAtPath: outputDir attributes: nil];
      }

      //check if dir is writable

      if(![fileManager isWritableFileAtPath: outputDir])
      {
            NSWarnLog(@"Directory %@ is not writable\n", outputDir);
            [NSException raise: NSInternalInconsistencyException
                  format: @"Cannot create output directory %@", outputDir];
      }

      GSPrintf(stderr, @"Output directory is %@.\n", outputDir);

      //set up output files

      [self openFile: [outputDir stringByAppendingPathComponent: @"trajectory.ad"]
            usingName: @"TrajectoryFile"
            flag: @"w+"];
      [self openFile: [outputDir stringByAppendingPathComponent: @"energy.ad"]
            usingName: @"EnergyFile"
            flag: @"w+"];
      

      if([[NSUserDefaults standardUserDefaults] boolForKey: @"RedirectOutput"])
      {
            fflush(stderr);
            logFile = [outputDir stringByAppendingPathComponent: @"AdunCore.log"];
            oldLogFile = [[NSUserDefaults standardUserDefaults] stringForKey: @"LogFile"];
            if(![[NSFileManager defaultManager] isWritableFileAtPath:
                   [logFile stringByDeletingLastPathComponent]])
            {
                  NSWarnLog(@"Cannot redirect to output dir!");
            }
            else
            {
                  /*
                   * movePath:toPath:handler doesnt work - may have something to
                   * do with the fact that oldLogFile is stderr when we try to move it.
                   * Work around by reading in old file and writing to the new one.
                   */
                  contents = [NSString stringWithContentsOfFile: oldLogFile];
                  freopen([logFile cString], "w", stderr);
                  GSPrintf(stderr, @"%@\n", contents);
                  [[NSFileManager defaultManager] removeFileAtPath: oldLogFile
                        handler: nil];
            }
      }

      fflush(stderr);
}

- (void) _createControllerOutputDirectory
{
      BOOL isDir;

      //remove any previous directory with this name

      if([fileManager fileExistsAtPath: controllerOutputDir])
            if(![fileManager removeFileAtPath: controllerOutputDir
                  handler: nil])
            {
                  [NSException raise: NSInternalInconsistencyException
                        format: @"Unable to remove directory blocking creation of \
new controller output directory %@", controllerOutputDir];
            }
                        
      if(![fileManager createDirectoryAtPath: controllerOutputDir attributes: nil])
            [NSException raise: NSInternalInconsistencyException
                  format: @"Unable to create controller output directory %@", 
                        controllerOutputDir];
}

00409 - (void) setSimulationOutputDirectory: (NSString*) aPath
{
      if(aPath == outputDir)
            return;
      else
            [outputDir release];

      if([aPath isAbsolutePath])
      {
            outputDir = [aPath retain];
      }
      else
      {
            //we create the directory in the current directory
            aPath = [aPath lastPathComponent];
            outputDir = [[fileManager currentDirectoryPath] 
                        stringByAppendingPathComponent: aPath];   
            [outputDir retain];           
      }     

      [self _createSimulationOutputDirectory];
}

00432 - (void) setControllerOutputDirectory: (NSString*) aPath
{
      if(aPath == controllerOutputDir)
            return;
      else
            [controllerOutputDir release];
            
      if([aPath isAbsolutePath])
      {
            controllerOutputDir = [aPath retain];
      }
      else
      {
            //we create the directory in the current directory
            aPath = [aPath lastPathComponent];
            controllerOutputDir = [[fileManager currentDirectoryPath] 
                        stringByAppendingPathComponent: aPath];   
            [controllerOutputDir retain];       
      }

      [self _createControllerOutputDirectory];
}

/*
 * Input/Output related methods
 */

- (FILE*) openFile: (NSString*) file  usingName: (NSString*) name flag: (NSString*) fileFlag
{
      int length;
      const char* filename;
      const char* flag;
      FILE* file_p;

      if(file == nil)
      {
            NSWarnLog(@"There is no file called %@\n", file);
            return NULL;
      }
      
      if(![fileManager fileExistsAtPath: file])
            NSWarnLog(@"File %@ does not exist. Will create it if flag indicates\n", file);

      filename = [file cString];
      flag = [fileFlag cString];

      //open the file

      file_p = fopen(filename, flag);
      if(file_p == NULL)
      {
            NSWarnLog(@"File %@ does not exist and flag is %@\n", file, fileFlag);
            return NULL;
      }
      else
            [fileStreams setObject: [NSValue valueWithPointer: file_p] forKey: name];

      return file_p;
}

- (FILE*) getStreamForName: (NSString*) name
{
      return (FILE*)[[fileStreams objectForKey: name] pointerValue];
}

- (void) closeStreamWithName: (NSString*) name
{
      fclose([self getStreamForName: name]);
      [fileStreams removeObjectForKey: name];
}

- (void) closeAllStreams
{
      NSEnumerator *enumerator = [fileStreams keyEnumerator];
      id key;

      while(key = [enumerator nextObject])
            if(![key isEqual:@"Error"] && ![key isEqual: @"Standard"])
                  [self closeStreamWithName: key];
}

- (void) writeMatrix: (AdMatrix*) Matrix toStream: (FILE*) stream
{
      int i, j;

      for(i=0; i<Matrix->no_rows; i++)
      {
            for(j=0; j<Matrix->no_columns; j++)
                  fprintf(stream, "%-12lf", Matrix->matrix[i][j]);
            fprintf(stream, "\n");
      }
}

/* 
 * Accessors 
 */

00529 - (NSString*) simulationOutputDirectory 
{
      return [[outputDir retain] autorelease];
}

- (NSString*) controllerOutputDirectory
{
      return [[controllerOutputDir retain] autorelease];
}

- (NSString*) controllerDirectory
{
      return [[controllerDir retain] autorelease];
}

- (NSString*) adunUserDirectory
{
      return [[adunUserDir retain] autorelease];
}

- (NSString*) resultsDirectory
{
      return [[resultsDir retain] autorelease];
}

- (NSString*) currentDirectoryPath
{
      return [fileManager currentDirectoryPath];
}

- (NSMutableDictionary*) simulationOptions
{
      return [simulationData valueForKey: @"options"];
}

- (id) systemDataSources
{
      return [simulationData valueForKey: @"systemDataSources"];  
}

/*
 * Commands
 */

00573 - (void) setCore: (id) object
{
      core = object;
}

- (id) core
{
      return core;
}

- (id) execute: (NSDictionary*) commandDict error: (NSError**) errorResult;
{
      NSString* command;
      SEL commandSelector;
      id result;

      NSDebugLLog(@"Execute", @"Recieved %@", commandDict);

      if((command = [commandDict objectForKey: @"command"]) == nil)
            [NSException raise: NSInvalidArgumentException
                  format: @"The command dictionary is missing the command key"];
      
      NSDebugLLog(@"Execute", @"Command is %@. Querying core %@ for validity", command, core);

      if(![core validateCommand: command])      
      {
            result = nil;
            *errorResult = [NSError errorWithDomain: @"AdCoreErrorDomain"
                        code: 0
                        userInfo: [NSDictionary dictionaryWithObject:
                              [NSString stringWithFormat: @"The supplied command (%@) is invalid", command]
                              forKey: NSLocalizedDescriptionKey]];

            return result;
      }     
      
      commandSelector = NSSelectorFromString([NSString stringWithFormat:@"%@:", command]);
      
      NSDebugLLog(@"Execute", @"Command validated. Exectuing");

      result = [core performSelector: commandSelector 
                  withObject: [commandDict objectForKey: @"options"]];
      NSDebugLLog(@"Execute", @"Command executed. Results %@", result);
      *errorResult = [core errorForCommand: command];
      NSDebugLLog(@"Execute", @"Error is %@", *errorResult);

      return result;
}

00622 - (NSMutableDictionary*) optionsForCommand: (NSString*) command;
{
      return [core optionsForCommand: command];
}

00627 - (NSArray*) validCommands
{
      return [core validCommands];
}


@end


Generated by  Doxygen 1.6.0   Back to index