Annotation of Examples/EnterpriseObjects/DistributedEO/DEOClient.subproj/DEONotificationCenter.m, revision 1.1.1.1

1.1       root        1: /*
                      2:    DEONotificationCenter.m created by enoyau on Fri 13-Jan-1995
                      3: 
                      4:    You may freely copy, distribute, and reuse the code in this example.
                      5:    NeXT disclaims any warranty of any kind, expressed or implied, as to its
                      6:    fitness for any particular use.
                      7: */
                      8: 
                      9: #import "DEONotificationCenter.h"
                     10: #import "DEONotification.h"
                     11: #import "DEOServerMonitor.h"
                     12: #import <foundation/NSException.h>
                     13: 
                     14: #import <libc.h>
                     15: 
                     16: NSString *DEOUpdate = @"DEOUpdate";
                     17: NSString *DEOInsert = @"DEOInsert";
                     18: NSString *DEODelete = @"DEODelete";
                     19: 
                     20: @interface DEONotificationCenter(Communication) <DEOClient>
                     21: - (void)registerAgain:(NSNotification *)note;
                     22: @end
                     23: 
                     24: // Holder object to allow the server to retain the proxy to
                     25: // a DEONotificationCenter without retaining the center itself.
                     26: // See comment in initWithDatabaseChannel:entity:
                     27: @interface DEONotificationCenterHolder : NSObject <DEOClient>
                     28: {
                     29:     DEONotificationCenter *center;
                     30: }
                     31: - initWithNonRetainedObject:(DEONotificationCenter *)aCenter;
                     32: @end
                     33: 
                     34: 
                     35: @implementation DEONotificationCenter
                     36: 
                     37: static NSString *localHostname = nil;
                     38: 
                     39: + initialize
                     40: {
                     41:     if(!localHostname) {
                     42:         char DEOHostname[1024];
                     43: 
                     44:         gethostname(DEOHostname, 1024);
                     45:         localHostname = [[NSString alloc] initWithCString:DEOHostname];
                     46:     }
                     47:     return self;
                     48: }
                     49: 
                     50: + (NSString *)localHostname
                     51: {
                     52:     return localHostname;
                     53: }
                     54: 
                     55: - initWithDatabaseChannel:(EODatabaseChannel *)aDatabaseChannel 
                     56:                    entity:(EOEntity *)anEntity
                     57: {
                     58:     NSArray *objs;
                     59:     NSArray *keys;
                     60:     
                     61:     [super init];
                     62: 
                     63:     // localCenter is used for notification.
                     64:     localCenter = [[NSNotificationCenter alloc] init];
                     65:     entity = [anEntity retain];
                     66:     databaseChannel = [aDatabaseChannel retain];
                     67: 
                     68:     // Build the unique identifier for the DEONotificationCenter
                     69:     objs = [NSArray arrayWithObjects:
                     70:         localHostname,
                     71:         [NSString stringWithFormat:@"%d", getpid()],
                     72:         [anEntity name],
                     73:         [NSString stringWithFormat:@"%x", self],
                     74:         0];
                     75: 
                     76:     keys = [NSArray arrayWithObjects:
                     77:         @"hostname",
                     78:         @"pid",
                     79:         @"entity",
                     80:         @"self",
                     81:         0];
                     82: 
                     83:     localID = [[NSDictionary dictionaryWithObjects:objs forKeys:keys] retain];
                     84: 
                     85:     // Register self for notifications from monitor
                     86:     monitor = [[DEOServerMonitor serverMonitor] retain];
                     87:     [[NSNotificationCenter defaultCenter] addObserver:self
                     88:                                              selector:@selector(registerAgain:)
                     89:                                      notificationName:DEOServerReinitialize
                     90:                                                object:monitor];
                     91: 
                     92:     // We need to pass the server a pointer to our object, but it cannot
                     93:     // retain it, or a cycle will be created.  Unfortunately, the server
                     94:     // MUST retain the object we pass it or the proxy on the server side
                     95:     // will be released.  The solution is to pass the server an "holder"
                     96:     // object that it can retain (thus retaining the proxy) without
                     97:     // retaining us (thus avoiding a cycle).  This holder must pass on
                     98:     // messages to our actual instance.
                     99:     container =
                    100:         [[DEONotificationCenterHolder alloc] initWithNonRetainedObject:self];
                    101: 
                    102:     [self registerAgain:nil];
                    103:     
                    104:     return self;
                    105: }
                    106: 
                    107: - (void)dealloc
                    108: {
                    109:     [localCenter release];
                    110:     [entity release];
                    111:     [databaseChannel release];
                    112:     [localID release];
                    113:     NS_DURING
                    114:         [[monitor server] unregisterClient:(id <DEOClient>)container];
                    115:     NS_HANDLER
                    116:         NSLog(@"Failed to send remote method unregisterClient: to server.\n");
                    117:     NS_ENDHANDLER
                    118:     [container release];
                    119:     [monitor release];
                    120:     [super dealloc];
                    121:     return;
                    122: }
                    123: 
                    124: - (void)addObserver:observer
                    125:            selector:(SEL)selector
                    126:    notificationName:(NSString *)notificationName
                    127:              object:object
                    128: {
                    129:     [localCenter addObserver:observer
                    130:                     selector:selector
                    131:             notificationName:notificationName
                    132:                       object:object];
                    133: }
                    134: 
                    135: - (void)removeObserver:observer
                    136:       notificationName:(NSString *)notificationName
                    137:                 object:object;
                    138: {
                    139:     [localCenter removeObserver:observer
                    140:                notificationName:notificationName
                    141:                          object:object];
                    142: }
                    143: 
                    144: - (void)removeObserver:observer
                    145: {
                    146:     [localCenter removeObserver:observer];
                    147: }
                    148: 
                    149: - (void)postNotificationName:(NSString *)notificationName object:object
                    150: {
                    151:     [self postNotificationName:notificationName object:object userInfo:nil];
                    152: }
                    153: 
                    154: - (void)postNotificationName:(NSString *)name
                    155:                       object:object
                    156:                     userInfo:(NSDictionary *)userInfo;
                    157: {
                    158:     NSMutableDictionary *info = [NSMutableDictionary dictionary];
                    159:     NSDictionary *primaryKey =
                    160:         [entity primaryKeyForRow:[[[databaseChannel databaseContext] database] snapshotForObject:object]];
                    161: 
                    162:     // Encodes the enterprise object in a dictionary with the primary key.
                    163:     [info setObject:primaryKey forKey:@"primaryKey"];
                    164:     [info setObject:name       forKey:@"notificationName"];
                    165:     [info setObject:localID    forKey:@"sender"];
                    166: 
                    167:     NS_DURING
                    168:         [[monitor server] dispatchInformation:info
                    169:                                        forKey:[entity name]
                    170:                                      userInfo:userInfo];
                    171:     NS_HANDLER
                    172:             NSLog(@"Failed to send remote method dispatchInformation:forKey:userInfo: to server.\n");
                    173:     NS_ENDHANDLER
                    174: }
                    175: 
                    176: @end
                    177: 
                    178: @implementation DEONotificationCenter(Communication)
                    179: 
                    180: - (oneway)dispatchInformation:(NSDictionary *)info
                    181:                        forKey:(NSString *)key
                    182:                      userInfo:(NSDictionary *)userInfo
                    183: {
                    184:     // Decodes the enterprise object from information over the wire
                    185:     id database = [[databaseChannel databaseContext] database];
                    186:     id eoObject = [database objectForPrimaryKey:[info objectForKey:@"primaryKey"]
                    187:                                          entity:entity];
                    188: 
                    189:     if(!eoObject) {
                    190:         // Creates an EOFault if object does not exist yet
                    191:         [EOFault objectFaultWithPrimaryKey:[info objectForKey:@"primaryKey"]
                    192:                                     entity:entity
                    193:                            databaseChannel:databaseChannel
                    194:                                       zone:NSDefaultMallocZone()];
                    195:     }
                    196: 
                    197:     [localCenter postNotification:
                    198:         [DEONotification notificationWithName:[info objectForKey:@"notificationName"]
                    199:                                        object:eoObject
                    200:                                      userInfo:userInfo
                    201:                                       isLocal:[[info objectForKey:@"sender"] isEqual:localID]]];
                    202: 
                    203:     return;
                    204: }
                    205: 
                    206: // Is called at init time or when the server has died.
                    207: - (void)registerAgain:(NSNotification *)note
                    208: {
                    209:     NS_DURING
                    210:         // Register as entity user in the distributed server
                    211:         [[monitor server] registerClient:(id <DEOClient>)container forKey:[entity name]];
                    212:     NS_HANDLER
                    213:         NSLog(@"Failed to send remote method registerClient:forKey: to server.\n");
                    214:     NS_ENDHANDLER
                    215: }
                    216: 
                    217: @end
                    218: 
                    219: @implementation DEONotificationCenterHolder
                    220: 
                    221: - initWithNonRetainedObject:(DEONotificationCenter *)aCenter
                    222: {
                    223:     [super init];
                    224:     center = aCenter;
                    225:     return self;
                    226: }
                    227: 
                    228: - (oneway)dispatchInformation:(NSDictionary *)info
                    229:                        forKey:(NSString *)key
                    230:                      userInfo:(NSDictionary *)userInfo
                    231: {
                    232:     [center dispatchInformation:info
                    233:                          forKey:key
                    234:                        userInfo:userInfo];
                    235: }
                    236: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.