PDA

View Full Version : Distributed Application




sivaprakash
Apr 27, 2011, 04:37 AM
Hi

Can you please clarify the following


1. I have created a Server and Client application to build Distributed Environment application. I have created Proxy object for Server and making the communication between them as mentioned in http://bit.ly/geHQow.

2. I have to start the Server in the system boot up itself, so shall I use Apple Script Daemon to start the Server during the boot up as shown here http://bit.ly/htctih.

3. I believe we can not Write Objective-C code in Daemon.

4. We have to use Apple Script (Daemon) to start the server during the boot up or there any other straight forward way?


Thanks
Siva



jiminaus
Apr 27, 2011, 04:55 AM
1. I have created a Server and Client application to build Distributed Environment application. I have created Proxy object for Server and making the communication between them as mentioned in http://bit.ly/geHQow.


Good on you for getting this far.


2. I have to start the Server in the system boot up itself, so shall I use Apple Script Daemon to start the Server during the boot up as shown here http://bit.ly/htctih.


Create a non-launch-on-demand daemon using launchd. Read the Creating launchd Daemons and Agents chapter for the System Startup Programming Topics guide.


3. I believe we can not Write Objective-C code in Daemon.


There is not reason AFAIK why a daemon couldn't be written in Objective-C. There might be some parts of Cocoa that might not work from a daemon, but anything in Foundation framework should work.


4. We have to use Apple Script (Daemon) to start the server during the boot up or there any other straight forward way?


I don't know what you mean by an Apple Script Daemon so I don't know what you mean by this. The recommend way to start a daemon is to use launchd on Mac OS X.

Another way you do it is to start the daemon on demand. In the client, try to get the object vended by the server. If that fails, check if the server is running, if not start the server and then try getting the vended object again.

EDIT: If you want your server program to be able to have a GUI, and it's okay to have it run once per logged-in user (think Fast User Switching), then you might want to set it up an agent instead of as a daemon. See Technical Note TN2083 : Daemons and Agents (http://developer.apple.com/library/mac/#technotes/tn2083)

sivaprakash
Apr 27, 2011, 05:39 AM
Hi

Thanks !!

The reason why I want to start the Daemon during the start-up up there will be a situation where Server has to start process some process with out Client's interaction. For example, Scheduled Tasks where I keep the Scheduler information in some file system/database and the service has to pick them up and work.

For this requirement can I use Daemon Thread to Start the Service and check the health of the Service?

Thanks
Siva

jiminaus
Apr 27, 2011, 06:15 AM
The reason why I want to start the Daemon during the start-up up there will be a situation where Server has to start process some process with out Client's interaction. For example, Scheduled Tasks where I keep the Scheduler information in some file system/database and the service has to pick them up and work.

For this requirement can I use Daemon Thread to Start the Service and check the health of the Service?


So you will need to set up a launchd daemon with the RunAtLoad and KeepAlive keys in the server's launchd.plist set to true. Launchd will then start your server at boot, and restart it if it ever exits.

If you wanted to do a more active, watchdog-like check to confirm that your server process is actually responding, you could have a second launchd.plist which uses either the StartInterval or StartCalendarInterval keys to run a server checking program periodically. If the server checking program detects the server isn't responding, it could send a SIGKILL to the server which would cause the server process to die, which in turn would cause launchd to restart the server.

sivaprakash
Apr 27, 2011, 07:51 AM
Oh That's Great !!

So the over all design would be

Server Application (Objective-C)which will be triggered by Daemon with RunAtLoad and KeepAlive, so that my Server application will be triggered during the System Boot up.

Since this Server application has to run irrespective of whether the user has logged in or not so I should place Server application and Daemon under "System\Library\launchdaemons" folder, it right ?

Thanks
Siva

jiminaus
Apr 27, 2011, 04:42 PM
Oh That's Great !!

So the over all design would be

Server Application (Objective-C)which will be triggered by Daemon with RunAtLoad and KeepAlive, so that my Server application will be triggered during the System Boot up.

Since this Server application has to run irrespective of whether the user has logged in or not so I should place Server application and Daemon under "System\Library\launchdaemons" folder, it right ?

Thanks
Siva

NOTHING should ever be written into /System/Library. Use the equivalent directory in /Library for system-wide things or ~/Library for user-local things.

In your case, you would install the launchd.plist for your server into /Library/LaunchDaemons. Note the naming convention for these plist files.

(BTW This isn't Windows. The components of paths are separated by / not \.)

sivaprakash
Apr 28, 2011, 02:38 AM
Thanks !!

It really helped me to build the service layer.

The other question I have is how can I get the response back from Server to Client ? Because I am making Async calls to Server after performing some process the server has to post the result back to Client? - Is it possible and sample ?

Thanks
Siva

jiminaus
Apr 28, 2011, 03:11 AM
Thanks !!

It really helped me to build the service layer.

The other question I have is how can I get the response back from Server to Client ? Because I am making Async calls to Server after performing some process the server has to post the result back to Client? - Is it possible and sample ?

Thanks
Siva

I haven't done this before. I've not used asynchronous distributed messages when a response was necessary.

A couple of ways come to mind that you could try.

1) Don't use asynchronous methods and declare a return type. Use GCD to move the server call into a client background thread to avoid locking up the client main thread.

2) Use NSDistributedNotificationCenter to publish when an operation completes. But this would break if you ever needed to move the server onto a different computer than the client.

3) Declare a callback protocol and add a callback parameter to the operation. Then have the server send an asynchronous message back to the client via object passed in as the callback parameter.


@protocol LongOperationCallback
- (oneway void)longOperationCompleted;
- (oneway void)longOperationFailedWithError:(byval out NSError *)error;
@end

@protocol Server
- (oneway void)longOperation:(int)parameter
withCallback:(byref id<LongOperationCallback>)callback;
@end



/* In the client */

@interface LongOperationCallbackImpl <LongOperationCallback>
/* Add context properties */
@end

/* Implement LongOperationCallbackImpl in terms of context properties */



/* Then elsewhere in the client */

- (void)someMethodInTheClient
{
LongOperationCallbackImpl callbackImpl =
[[LongOperationCallbackImpl alloc] init];
/* Set context properties in callbackImpl */
[server longOperation:parameter withCallback:callbackImpl];
}



/* In the server's implementation of the Server protocol */

- (void)longOperation:(int)parameter
withCallback:(id<LongOperationCallback>)callback
{
/* Start the operation on a background thread so
the server can go on to accepting other distributed
messages while the long operation proceeds. */
NSDictionary *dict =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:parameter], @"parameter",
callback, @"callback",
nil];
[self performSelectorInBackground:@selector(longOperationImpl:)
withObject:dict];
}

- (void)longOperationImpl:(NSDictionary *)dict
{
int parameter = [(NSNumber *)[dict objectForKey:@"parameter"] intValue];
id<LongOperationCallback> callback = [dict objectForKey:@"callback"];

/* Do the long operation here */

if (operationSuccessful) {
[callback longOperationCompleted];
} else {
/* Create NSError to describe failure */
[callback longOperationFailedWithError:error];
}
}


None of the above is tested. The theory should be sound. But there might be a gotcha in the detail of Objective-C distributed objects. This idea comes from CORBA.