Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  IdentityInfoFetcher.m  Sprache: unbekannt

 
Spracherkennung für: .m vermutete Sprache: Lisp {Lisp[37] Masm[37] ABAP[32]} [Methode: maximale Elemente, drei Dimensionen]

#import "IdentityInfoFetcher.h"
#import "ServerAPIConnector.h"

#ifdef DEBUG
static const DDLogLevel ddLogLevel = DDLogLevelInfo;
#else
static const DDLogLevel ddLogLevel = DDLogLevelWarning;
#endif

@implementation IdentityInfoFetcher {
    NSMutableDictionary *prefetchCache;
    NSMutableDictionary *pendingFetchCompletionHandlersByIdentity;
    NSMutableDictionary *pendingFetchErrorHandlersByIdentity;
    NSMutableDictionary *workInfoBlockUnknownCache;
    dispatch_queue_t queue;
}

+ (IdentityInfoFetcher*)sharedIdentityInfoFetcher {
    static IdentityInfoFetcher *instance;
    
    @synchronized (self) {
        if (!instance)
            instance = [[IdentityInfoFetcher alloc] init];
    }
    
    return instance;
}

- (id)init
{
    self = [super init];
    if (self) {
        queue = dispatch_queue_create("ch.threema.identityinfofetcher", DISPATCH_QUEUE_SERIAL);
        prefetchCache = [NSMutableDictionary dictionary];
        pendingFetchCompletionHandlersByIdentity = [NSMutableDictionary dictionary];
        pendingFetchErrorHandlersByIdentity = [NSMutableDictionary dictionary];
        workInfoBlockUnknownCache = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)prefetchIdentityInfo:(NSSet*)identities onCompletion:(void(^)(void))onCompletion onError:(void(^)(NSError *error))onError {    
    ServerAPIConnector *apiConnector = [[ServerAPIConnector alloc] init];
    [apiConnector fetchBulkIdentityInfo:[identities allObjects] onCompletion:^(NSArray *identities, NSArray *publicKeys, NSArray *featureMasks, NSArray *states, NSArray *types) {
        dispatch_async(queue, ^{
            // Add results to cache
            for (int i = 0; i < identities.count; i++) {
                [prefetchCache setObject:@{
                    @"publicKey": publicKeys[i],
                    @"featureMask": featureMasks[i],
                    @"state": states[i],
                    @"type": types[i]
                } forKey:identities[i]];
            }
            onCompletion();
        });
    } onError:^(NSError *error) {
        onError(error);
    }];
}

- (void)fetchIdentityInfoFor:(NSString*)identity onCompletion:(void(^)(NSData *publicKey, NSNumber *state, NSNumber *type, NSNumber *featureMask))onCompletion onError:(void(^)(NSError *error))onError {
    
    dispatch_async(queue, ^{
        // Check prefetch cache
        NSDictionary *cachedIdentityInfo = [prefetchCache objectForKey:identity];
        if (cachedIdentityInfo != nil) {
            onCompletion(cachedIdentityInfo[@"publicKey"], cachedIdentityInfo[@"state"], cachedIdentityInfo[@"type"], cachedIdentityInfo[@"featureMask"]);
            return;
        }
        
        // Not in prefetch cache - fetch now
        if (pendingFetchCompletionHandlersByIdentity[identity]) {
            // A fetch request is already pending for this identity.
            // Store the completion/error blocks and call them later to avoid fetching multiple times in parallel.
            [pendingFetchCompletionHandlersByIdentity[identity] addObject:[onCompletion copy]];
            [pendingFetchErrorHandlersByIdentity[identity] addObject:[onError copy]];
        } else {
            // No other fetch pending for this identity
            pendingFetchCompletionHandlersByIdentity[identity] = [NSMutableArray arrayWithObject:[onCompletion copy]];
            pendingFetchErrorHandlersByIdentity[identity] = [NSMutableArray arrayWithObject:[onError copy]];
            
            ServerAPIConnector *apiConnector = [[ServerAPIConnector alloc] init];
            DDLogVerbose(@"Fetching identity %@ from server", identity);
            [apiConnector fetchIdentityInfo:identity onCompletion:^(NSData *publicKey, NSNumber *state, NSNumber *type, NSNumber *featureMask) {
                dispatch_async(queue, ^{
                    for (void(^completionHandler)(NSData*, NSNumber*, NSNumber*, NSNumber*) in pendingFetchCompletionHandlersByIdentity[identity]) {
                        completionHandler(publicKey, state, type, featureMask);
                    }
                    [pendingFetchCompletionHandlersByIdentity removeObjectForKey:identity];
                    [pendingFetchErrorHandlersByIdentity removeObjectForKey:identity];
                });
            } onError:^(NSError *error) {
                dispatch_async(queue, ^{
                    for (void(^errorHandler)(NSError *) in pendingFetchErrorHandlersByIdentity[identity]) {
                        errorHandler(error);
                    }
                    [pendingFetchCompletionHandlersByIdentity removeObjectForKey:identity];
                    [pendingFetchErrorHandlersByIdentity removeObjectForKey:identity];
                });
            }];
        }
    });
}

- (void)fetchWorkIdentitiesInfo:(NSArray *)identities onCompletion:(void(^)(NSArray *foundIdentities))onCompletion onError:(void(^)(NSError *error))onError {
    NSMutableArray *cachedIdentities = [NSMutableArray new];
    BOOL allIdentitiesAreCached = true;
    
    for (NSString *identity in identities) {
        if ([workInfoBlockUnknownCache.allKeys containsObject:identity]) {
            NSDictionary *identityInfo = [workInfoBlockUnknownCache valueForKey:identity];
            if (![identityInfo isEqual:[NSNull null]]) {
                [cachedIdentities addObject:identityInfo];
            }
        }
        else {
            allIdentitiesAreCached = false;
            break;
        }
    }
    
    if (allIdentitiesAreCached) {
        onCompletion(cachedIdentities);
        return;
    }
    
    ServerAPIConnector *apiConnector = [[ServerAPIConnector alloc] init];
    [apiConnector fetchWorkIdentitiesInfo:identities onCompletion:^(NSArray *foundIdentities) {
        dispatch_async(queue, ^{
            for (NSDictionary *foundIdentity in foundIdentities) {
                [workInfoBlockUnknownCache setObject:foundIdentity forKey:foundIdentity[@"id"]];
            }
            
            if (foundIdentities.count < identities.count) {
                for (NSString *identity in identities) {
                    if (![foundIdentities containsObject:identity]) {
                        [workInfoBlockUnknownCache setObject:[NSNull null] forKey:identity];
                    }
                }
            }
            
            onCompletion(foundIdentities);
        });
    } onError:^(NSError *error) {
        onError(error);
    }];
}

@end

[Dauer der Verarbeitung: 0.14 Sekunden]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104842
#Domains=499168