Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/*
2
 * Copyright 2020 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploader.h"
18
 
19
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORPlatform.h"
20
#import "GoogleDataTransport/GDTCORLibrary/Internal/GDTCORRegistrar.h"
21
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCORConsoleLogger.h"
22
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREndpoints.h"
23
#import "GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport/GDTCOREvent.h"
24
 
25
#import "GoogleDataTransport/GDTCCTLibrary/Private/GDTCCTUploadOperation.h"
26
 
27
NS_ASSUME_NONNULL_BEGIN
28
 
29
@interface GDTCCTUploader () <NSURLSessionDelegate, GDTCCTUploadMetadataProvider>
30
 
31
@property(nonatomic, readonly) NSOperationQueue *uploadOperationQueue;
32
@property(nonatomic, readonly) dispatch_queue_t uploadQueue;
33
 
34
@property(nonatomic, readonly)
35
    NSMutableDictionary<NSNumber * /*GDTCORTarget*/, GDTCORClock *> *nextUploadTimeByTarget;
36
 
37
@end
38
 
39
@implementation GDTCCTUploader
40
 
41
static NSURL *_testServerURL = nil;
42
 
43
+ (void)load {
44
  GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance];
45
  [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT];
46
  [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL];
47
  [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH];
48
  [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetINT];
49
}
50
 
51
+ (instancetype)sharedInstance {
52
  static GDTCCTUploader *sharedInstance;
53
  static dispatch_once_t onceToken;
54
  dispatch_once(&onceToken, ^{
55
    sharedInstance = [[GDTCCTUploader alloc] init];
56
  });
57
  return sharedInstance;
58
}
59
 
60
- (instancetype)init {
61
  self = [super init];
62
  if (self) {
63
    _uploadQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL);
64
    _uploadOperationQueue = [[NSOperationQueue alloc] init];
65
    _uploadOperationQueue.maxConcurrentOperationCount = 1;
66
    _nextUploadTimeByTarget = [[NSMutableDictionary alloc] init];
67
  }
68
  return self;
69
}
70
 
71
- (void)uploadTarget:(GDTCORTarget)target withConditions:(GDTCORUploadConditions)conditions {
72
  // Current GDTCCTUploader expected behaviour:
73
  // 1. Accept multiple upload request
74
  // 2. Verify if there are events eligible for upload and start upload for the first suitable
75
  // target
76
  // 3. Ignore other requests while an upload is in-progress.
77
 
78
  // TODO: Revisit expected behaviour.
79
  // Potentially better option:
80
  // 1. Accept and enqueue all upload requests
81
  // 2. Notify the client of upload stages
82
  // 3. Allow the client cancelling upload requests as needed.
83
 
84
  id<GDTCORStoragePromiseProtocol> storage = GDTCORStoragePromiseInstanceForTarget(target);
85
  if (storage == nil) {
86
    GDTCORLogError(GDTCORMCEGeneralError,
87
                   @"Failed to upload target: %ld - could not find corresponding storage instance.",
88
                   (long)target);
89
    return;
90
  }
91
 
92
  GDTCCTUploadOperation *uploadOperation =
93
      [[GDTCCTUploadOperation alloc] initWithTarget:target
94
                                         conditions:conditions
95
                                          uploadURL:[[self class] serverURLForTarget:target]
96
                                              queue:self.uploadQueue
97
                                            storage:storage
98
                                   metadataProvider:self];
99
 
100
  GDTCORLogDebug(@"Upload operation created: %@, target: %@", uploadOperation, @(target));
101
 
102
  __weak __auto_type weakSelf = self;
103
  __weak GDTCCTUploadOperation *weakOperation = uploadOperation;
104
  uploadOperation.completionBlock = ^{
105
    __auto_type strongSelf = weakSelf;
106
    GDTCCTUploadOperation *strongOperation = weakOperation;
107
    if (strongSelf == nil || strongOperation == nil) {
108
      GDTCORLogDebug(@"Internal inconsistency: GDTCCTUploader was deallocated during upload.", nil);
109
      return;
110
    }
111
 
112
    GDTCORLogDebug(@"Upload operation finished: %@, uploadAttempted: %@", strongOperation,
113
                   @(strongOperation.uploadAttempted));
114
 
115
    if (strongOperation.uploadAttempted) {
116
      // Ignore all upload requests received when the upload was in progress.
117
      [strongSelf.uploadOperationQueue cancelAllOperations];
118
    }
119
  };
120
 
121
  [self.uploadOperationQueue addOperation:uploadOperation];
122
  GDTCORLogDebug(@"Upload operation scheduled: %@, operation count: %@", uploadOperation,
123
                 @(self.uploadOperationQueue.operationCount));
124
}
125
 
126
#pragma mark - URLs
127
 
128
+ (void)setTestServerURL:(NSURL *_Nullable)serverURL {
129
  _testServerURL = serverURL;
130
}
131
 
132
+ (NSURL *_Nullable)testServerURL {
133
  return _testServerURL;
134
}
135
 
136
+ (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target {
137
#if !NDEBUG
138
  if (_testServerURL) {
139
    return _testServerURL;
140
  }
141
#endif  // !NDEBUG
142
 
143
  return [GDTCOREndpoints uploadURLForTarget:target];
144
}
145
 
146
- (NSString *)FLLAndCSHAndINTAPIKey {
147
  static NSString *defaultServerKey;
148
  static dispatch_once_t onceToken;
149
  dispatch_once(&onceToken, ^{
150
    // These strings should be interleaved to construct the real key.
151
    const char *p1 = "AzSBG0honD6A-PxV5nBc";
152
    const char *p2 = "Iay44Iwtu2vV0AOrz1C";
153
    const char defaultKey[40] = {p1[0],  p2[0],  p1[1],  p2[1],  p1[2],  p2[2],  p1[3],  p2[3],
154
                                 p1[4],  p2[4],  p1[5],  p2[5],  p1[6],  p2[6],  p1[7],  p2[7],
155
                                 p1[8],  p2[8],  p1[9],  p2[9],  p1[10], p2[10], p1[11], p2[11],
156
                                 p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15],
157
                                 p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'};
158
    defaultServerKey = [NSString stringWithUTF8String:defaultKey];
159
  });
160
  return defaultServerKey;
161
}
162
 
163
#pragma mark - GDTCCTUploadMetadataProvider
164
 
165
- (nullable GDTCORClock *)nextUploadTimeForTarget:(GDTCORTarget)target {
166
  @synchronized(self.nextUploadTimeByTarget) {
167
    return self.nextUploadTimeByTarget[@(target)];
168
  }
169
}
170
 
171
- (void)setNextUploadTime:(nullable GDTCORClock *)time forTarget:(GDTCORTarget)target {
172
  @synchronized(self.nextUploadTimeByTarget) {
173
    self.nextUploadTimeByTarget[@(target)] = time;
174
  }
175
}
176
 
177
- (nullable NSString *)APIKeyForTarget:(GDTCORTarget)target {
178
  if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) {
179
    return [self FLLAndCSHAndINTAPIKey];
180
  }
181
 
182
  if (target == kGDTCORTargetINT) {
183
    return [self FLLAndCSHAndINTAPIKey];
184
  }
185
 
186
  return nil;
187
}
188
 
189
#if !NDEBUG
190
 
191
- (BOOL)waitForUploadFinishedWithTimeout:(NSTimeInterval)timeout {
192
  NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
193
  while ([expirationDate compare:[NSDate date]] == NSOrderedDescending) {
194
    if (self.uploadOperationQueue.operationCount == 0) {
195
      return YES;
196
    } else {
197
      [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
198
    }
199
  }
200
 
201
  GDTCORLogDebug(@"Uploader wait for finish timeout exceeded. Operations still in queue: %@",
202
                 self.uploadOperationQueue.operations);
203
  return NO;
204
}
205
 
206
#endif  // !NDEBUG
207
 
208
@end
209
 
210
NS_ASSUME_NONNULL_END