Annotation of Examples/EnterpriseObjects/ManyToMany/Projects_sybase/UniqueKey.m, revision 1.1.1.1

1.1       root        1: #import <appkit/appkit.h>
                      2: #import "UniqueKey.h"
                      3: 
                      4: 
                      5: static BOOL  _Debug = YES;
                      6: static id    _connectionDictionary = nil;
                      7: 
                      8: 
                      9: @implementation UniqueKey
                     10: 
                     11: /******************************************************************************
                     12: * Allow the programmer to specify login information for our separate UniqueKey
                     13: * channel.  If no information is supplied, we display our own login panel.
                     14: ******************************************************************************/
                     15: + setConnectionDictionary:(NSDictionary *)connectionDictionary
                     16: {
                     17:     if(_connectionDictionary) [_connectionDictionary autorelease];
                     18:     _connectionDictionary = [connectionDictionary retain];
                     19:     return self;
                     20: }
                     21: + connectionDictionary
                     22: {
                     23:     return [[_connectionDictionary retain] autorelease];
                     24: }
                     25: 
                     26: 
                     27: /******************************************************************************
                     28: * The UniqueKey objects share a database channel that is sure
                     29: * to be free to allow immediate reservation of a block of keys.
                     30: ******************************************************************************/
                     31: - initSharedChannel
                     32: {              
                     33:     NSString                                   *modelName = @"UniqueKey";
                     34:     NSString                                   *path;
                     35:     NSString                                   *_entityName = @"UniqueKey";
                     36:     EOModel                                            *eoModel;
                     37:     EOAdaptor                                  *eoAdaptor;
                     38:     EODatabase                                 *db;
                     39:     static EODatabaseContext   *_sharedContext;
                     40:     static EODatabaseChannel   *_sharedChannel;
                     41:     static EOEntity                            *_sharedEntity;
                     42:     static BOOL                                        initFlag = NO;
                     43:     
                     44:     if(!initFlag) {
                     45:        path = [EOModel findPathForModelNamed:modelName];
                     46:        if(!path) {
                     47:                NXRunAlertPanel([NXApp appName],
                     48:                        "UniqueKey is unable to find %s",NULL,NULL,NULL,[modelName cString]);
                     49:                return nil;
                     50:        }
                     51:        
                     52:        eoModel=[[EOModel alloc] initWithContentsOfFile:path];
                     53:        if(!eoModel) {
                     54:                NXRunAlertPanel([NXApp appName],
                     55:                        "UniqueKey is unable to open %s",NULL,NULL,NULL,[path cString]);
                     56:                return nil;
                     57:         }
                     58:         
                     59:        eoAdaptor= [EOAdaptor adaptorWithModel:eoModel];
                     60:        if(!eoAdaptor) {
                     61:                NXRunAlertPanel([NXApp appName],
                     62:                        "UniqueKey is unable to create adaptorWithModel:",NULL,NULL,NULL);
                     63:                return nil;
                     64:         }
                     65:         
                     66:        if([UniqueKey connectionDictionary]!=nil)
                     67:                [eoAdaptor setConnectionDictionary:[UniqueKey connectionDictionary]];
                     68:        if(![eoAdaptor hasValidConnectionDictionary])
                     69:                [eoAdaptor runLoginPanelAndValidateConnectionDictionary];
                     70: 
                     71:        db=[[EODatabase alloc] initWithAdaptor:eoAdaptor];
                     72:        if(!db) {
                     73:                NXRunAlertPanel([NXApp appName],
                     74:                        "UniqueKey is unable to initWithAdaptor:",NULL,NULL,NULL);
                     75:                return nil;
                     76:        }
                     77:     
                     78:        _sharedContext=[[EODatabaseContext alloc] initWithDatabase:db];
                     79:        if(!_sharedContext) {
                     80:                NXRunAlertPanel([NXApp appName],
                     81:                        "UniqueKey is unable to initWithDatabase:",NULL,NULL,NULL);
                     82:                return nil;
                     83:        }
                     84:     
                     85:        _sharedChannel=[[EODatabaseChannel alloc] initWithDatabaseContext:_sharedContext];
                     86:        if(!_sharedChannel) {
                     87:                NXRunAlertPanel([NXApp appName],
                     88:                        "UniqueKey is unable to initWithDatabaseContext:",NULL,NULL,NULL);
                     89:                return nil;
                     90:        }
                     91:     
                     92:        _sharedEntity= [eoModel entityNamed:_entityName];
                     93:        if(!_sharedEntity) {
                     94:                NXRunAlertPanel([NXApp appName],
                     95:                        "UniqueKey is unable to find entityNamed:%s",NULL,NULL,NULL,[_entityName cString]);
                     96:                return nil;
                     97:        }
                     98: 
                     99:        [[_sharedChannel adaptorChannel] openChannel];
                    100:        if(_Debug) [[_sharedChannel adaptorChannel] setDelegate:self];
                    101: 
                    102:        initFlag=TRUE;
                    103:     }
                    104:     
                    105:     dbContext        = [_sharedContext retain];
                    106:     dbChannel        = [_sharedChannel retain];
                    107:     uniqueKeyEntity  = [_sharedEntity retain];
                    108:     return self;
                    109: }
                    110: 
                    111: 
                    112: /******************************************************************************
                    113: * Init a UniqueKey object to reserve integer keys in blocks of <count> keys.  Hold
                    114: * off reserving any keys until the first call to nextKey.  Each call to nextKey
                    115: * returns a unique integer key.  The first call reserves a block of <count> keys.
                    116: * When the block has been used, a new block is reserved.
                    117: *
                    118: * UniqueKey uses a separate table to hold the external entity name and current
                    119: * max reserved integer key.  The UniqueKey objects share a database channel that
                    120: * is sure to be free to allow immediate reservation of a block of keys.
                    121: ******************************************************************************/
                    122: - initWithEntity:(EOEntity*)entity count:(unsigned int)count
                    123: {
                    124:     NSString   *qualifierString;
                    125:     EOQualifier        *tableNameQualifier;
                    126:     NSNumber   *max;
                    127: 
                    128:     keyCount   = count;
                    129:     nextKey    = 0;
                    130:     maxKey     = 0;
                    131:     
                    132:     if(!entity || ![self initSharedChannel]) return nil;
                    133: 
                    134:     // Construct the qualifier for our name
                    135:     qualifierString = [NSString stringWithFormat:@"EntityName = '%@'",[entity externalName]];
                    136:     
                    137:     tableNameQualifier = [[[EOQualifier allocWithZone:[self zone]]
                    138:        initWithEntity:uniqueKeyEntity qualifierFormat:qualifierString] autorelease];
                    139: 
                    140:     // Select the object and check for the presence of our name and "MaxKey"
                    141:     [dbContext beginTransaction];
                    142:     [dbChannel selectObjectsDescribedByQualifier:tableNameQualifier fetchOrder:nil];
                    143:     tableMax=[[dbChannel fetchWithZone:[dbChannel zone]] retain];
                    144:     [dbChannel cancelFetch];
                    145:     [dbContext commitTransaction];
                    146:     
                    147:     // Was there an entry for our table name?
                    148:     if(!tableMax) {
                    149:        NSLog(@"Unique key was unable to fetch EntityName = %@",[entity externalName]);
                    150:        return nil;
                    151:     }
                    152:     
                    153:     // Then there should be a value for "MaxKey" for our table
                    154:     max=[tableMax objectForKey:@"MaxKey"];
                    155:     if(!max) {
                    156:        NSLog(@"Unique key method nextKey could not fine MaxKey");
                    157:        return nil;
                    158:     }
                    159:     return self;
                    160: }
                    161: 
                    162: 
                    163: /******************************************************************************
                    164: * Hand out the next unique key from our reserved block.  If the block is exhausted,
                    165: * increment the max_id (high-water mark) and attempt to updateObject:.  This
                    166: * writes the new max_id back to the table.  Under optimistic locking (the default)
                    167: * the update will fail if another client has bumped up the max_id since our last use.
                    168: * In that case, we need to refetchObject: and try again.
                    169: ******************************************************************************/
                    170: - (int) nextKey
                    171: {
                    172:     NSNumber   *max;
                    173: 
                    174:     // Hand out our next reserved key.  If we are out of keys, fall through to
                    175:     // reserve another block of keyCount keys.
                    176:     if(++nextKey<=maxKey) return nextKey;
                    177:     
                    178:     // Attempt to bump up the count by keyCount.  Fail on optomistic lock if someone
                    179:     // else reserved a chunck since our original select (or our last update).
                    180:     [dbContext beginTransaction];
                    181:     while(1) {
                    182:        max    = [tableMax objectForKey:@"MaxKey"];
                    183:        maxKey = [max intValue]+keyCount;
                    184:        [tableMax setObject:[NSNumber numberWithInt:maxKey] forKey:@"MaxKey"];
                    185:        if([dbChannel updateObject:tableMax]) break;
                    186: 
                    187:        [dbContext rollbackTransaction];
                    188:        [dbContext beginTransaction];
                    189:        [dbChannel refetchObject:tableMax];
                    190:     }
                    191:     [dbContext commitTransaction];
                    192:     
                    193:     nextKey=maxKey-keyCount+1;
                    194:     return nextKey;
                    195: }
                    196: 
                    197: 
                    198: /******************************************************************************
                    199: * Echo SQL when debug is enabled.
                    200: ******************************************************************************/
                    201: - (EODelegateResponse)adaptorChannel:channel
                    202:        willEvaluateExpression:(NSMutableString *)expression
                    203: {
                    204:        NSLog(expression);
                    205:        return EODelegateApproves;
                    206: }
                    207: 
                    208: 
                    209: - (void)dealloc
                    210: {
                    211:        [dbContext release];
                    212:        [dbChannel release];
                    213:        [uniqueKeyEntity release];
                    214:        [tableMax release];
                    215:        if (_connectionDictionary)
                    216:                [_connectionDictionary release];
                    217:        [super dealloc];
                    218:    
                    219: }
                    220: 
                    221: @end

unix.superglobalmegacorp.com

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