aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Database/Core/FRepoManager.m
blob: 31c3efc5df7ffae64f15e298c70e4cfc770ccb9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2017 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#import <FirebaseCore/FIRLogger.h>
#import "FRepoManager.h"
#import "FRepo.h"
#import "FIRDatabaseQuery_Private.h"
#import "FAtomicNumber.h"
#import "FIRDatabaseConfig_Private.h"
#import "FIRDatabase_Private.h"

@implementation FRepoManager

typedef NSMutableDictionary<NSString *,
                            NSMutableDictionary<FRepoInfo *, FRepo *> *>
    FRepoDictionary;

+ (FRepoDictionary *)configs {
    static dispatch_once_t pred = 0;
    static FRepoDictionary *configs;
    dispatch_once(&pred, ^{
        configs = [NSMutableDictionary dictionary];
    });
    return configs;
}

/**
 * Used for legacy unit tests.  The public API should go through FirebaseDatabase which
 * calls createRepo.
 */
+ (FRepo *) getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config {
    [config freeze];
    FRepoDictionary *configs = [FRepoManager configs];
    @synchronized(configs) {
        NSMutableDictionary<FRepoInfo *, FRepo *> *repos = configs[config.sessionIdentifier];
        if (!repos || repos[repoInfo] == nil) {
            // Calling this should create the repo.
            [FIRDatabase createDatabaseForTests:repoInfo config:config];
        }

        return configs[config.sessionIdentifier][repoInfo];
    }
}

+ (FRepo *) createRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config database:(FIRDatabase *)database {
    [config freeze];
    FRepoDictionary *configs = [FRepoManager configs];
    @synchronized(configs) {
        NSMutableDictionary<FRepoInfo *, FRepo *> *repos =
            configs[config.sessionIdentifier];
        if (!repos) {
            repos = [NSMutableDictionary dictionary];
            configs[config.sessionIdentifier] = repos;
        }
        FRepo *repo = repos[repoInfo];
        if (repo == nil) {
            repo = [[FRepo alloc] initWithRepoInfo:repoInfo config:config database:database];
            repos[repoInfo] = repo;
            return repo;
        } else {
            [NSException raise:@"RepoExists" format:@"createRepo called for Repo that already exists."];
            return nil;
        }
    }
}

+ (void) interrupt:(FIRDatabaseConfig *)config {
    dispatch_async([FIRDatabaseQuery sharedQueue], ^{
        FRepoDictionary *configs = [FRepoManager configs];
        NSMutableDictionary<FRepoInfo *, FRepo *> *repos = configs[config.sessionIdentifier];
        for (FRepo *repo in [repos allValues]) {
            [repo interrupt];
        }
    });
}

+ (void) interruptAll {
    dispatch_async([FIRDatabaseQuery sharedQueue], ^{
        FRepoDictionary *configs = [FRepoManager configs];
        for (NSMutableDictionary<FRepoInfo *, FRepo *> *repos in [configs allValues]) {
              for (FRepo *repo in [repos allValues]) {
                    [repo interrupt];
              }
        }
    });
}

+ (void) resume:(FIRDatabaseConfig *)config {
    dispatch_async([FIRDatabaseQuery sharedQueue], ^{
        FRepoDictionary *configs = [FRepoManager configs];
        NSMutableDictionary<FRepoInfo *, FRepo *> *repos = configs[config.sessionIdentifier];
        for (FRepo *repo in [repos allValues]) {
            [repo resume];
        }
    });
}

+ (void) resumeAll {
    dispatch_async([FIRDatabaseQuery sharedQueue], ^{
        FRepoDictionary *configs = [FRepoManager configs];
        for (NSMutableDictionary<FRepoInfo *, FRepo *> *repos in [configs allValues]) {
            for (FRepo *repo in [repos allValues]) {
                [repo resume];
            }
        }
    });
}

+ (void)disposeRepos:(FIRDatabaseConfig *)config {
    // Do this synchronously to make sure we release our references to LevelDB before returning, allowing LevelDB
    // to close and release its exclusive locks.
    dispatch_sync([FIRDatabaseQuery sharedQueue], ^{
        FFLog(@"I-RDB040001", @"Disposing all repos for Config with name %@", config.sessionIdentifier);
        NSMutableDictionary *configs = [FRepoManager configs];
        for (FRepo* repo in [configs[config.sessionIdentifier] allValues]) {
            [repo dispose];
        }
        [configs removeObjectForKey:config.sessionIdentifier];
    });
}

@end