GDTCOREvent.m 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright 2018 Google
  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. #import "GDTCORLibrary/Public/GDTCOREvent.h"
  17. #import <GoogleDataTransport/GDTCORAssert.h>
  18. #import <GoogleDataTransport/GDTCORClock.h>
  19. #import <GoogleDataTransport/GDTCORConsoleLogger.h>
  20. #import <GoogleDataTransport/GDTCORPlatform.h>
  21. #import "GDTCORLibrary/Private/GDTCORDataFuture.h"
  22. #import "GDTCORLibrary/Private/GDTCOREvent_Private.h"
  23. @implementation GDTCOREvent
  24. - (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target {
  25. GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID");
  26. GDTCORAssert(target > 0, @"A target cannot be negative or 0");
  27. if (mappingID == nil || mappingID.length == 0 || target <= 0) {
  28. return nil;
  29. }
  30. self = [super init];
  31. if (self) {
  32. _mappingID = mappingID;
  33. _target = target;
  34. _qosTier = GDTCOREventQosDefault;
  35. }
  36. GDTCORLogDebug("Event %@ created. mappingID: %@ target:%ld", self, mappingID, (long)target);
  37. return self;
  38. }
  39. - (instancetype)copy {
  40. GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target];
  41. copy.dataObject = _dataObject;
  42. copy.qosTier = _qosTier;
  43. copy.clockSnapshot = _clockSnapshot;
  44. copy.customPrioritizationParams = _customPrioritizationParams;
  45. copy->_GDTFilePath = _GDTFilePath;
  46. GDTCORLogDebug("Copying event %@ to event %@", self, copy);
  47. return copy;
  48. }
  49. - (NSUInteger)hash {
  50. // This loses some precision, but it's probably fine.
  51. NSUInteger mappingIDHash = [_mappingID hash];
  52. NSUInteger timeHash = [_clockSnapshot hash];
  53. NSInteger dataObjectHash = [_dataObject hash];
  54. NSUInteger fileURL = [_GDTFilePath hash];
  55. return mappingIDHash ^ _target ^ _qosTier ^ timeHash ^ dataObjectHash ^ fileURL;
  56. }
  57. - (BOOL)isEqual:(id)object {
  58. return [self hash] == [object hash];
  59. }
  60. #pragma mark - Property overrides
  61. - (void)setDataObject:(id<GDTCOREventDataObject>)dataObject {
  62. // If you're looking here because of a performance issue in -transportBytes slowing the assignment
  63. // of -dataObject, one way to address this is to add a queue to this class,
  64. // dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync.
  65. if (dataObject != _dataObject) {
  66. _dataObject = dataObject;
  67. }
  68. }
  69. - (NSURL *)fileURL {
  70. if (!_GDTFilePath) {
  71. _GDTFilePath = [NSString stringWithFormat:@"event-%lu", (unsigned long)self.hash];
  72. }
  73. return [GDTCORRootDirectory() URLByAppendingPathComponent:_GDTFilePath];
  74. }
  75. #pragma mark - Private methods
  76. - (BOOL)writeToGDTPath:(NSString *)filePath error:(NSError **)error {
  77. NSData *dataTransportBytes = [_dataObject transportBytes];
  78. if (dataTransportBytes == nil) {
  79. _GDTFilePath = nil;
  80. _dataObject = nil;
  81. return NO;
  82. }
  83. NSURL *fileURL = [GDTCORRootDirectory() URLByAppendingPathComponent:filePath];
  84. BOOL writingSuccess = [dataTransportBytes writeToURL:fileURL
  85. options:NSDataWritingAtomic
  86. error:error];
  87. if (!writingSuccess) {
  88. GDTCORLogError(GDTCORMCEFileWriteError, @"An event file could not be written: %@", fileURL);
  89. return NO;
  90. }
  91. _GDTFilePath = filePath;
  92. _dataObject = nil;
  93. return YES;
  94. }
  95. #pragma mark - NSSecureCoding and NSCoding Protocols
  96. /** NSCoding key for mappingID property. */
  97. static NSString *mappingIDKey = @"_mappingID";
  98. /** NSCoding key for target property. */
  99. static NSString *targetKey = @"_target";
  100. /** NSCoding key for qosTier property. */
  101. static NSString *qosTierKey = @"_qosTier";
  102. /** NSCoding key for clockSnapshot property. */
  103. static NSString *clockSnapshotKey = @"_clockSnapshot";
  104. /** NSCoding key for fileURL property. */
  105. static NSString *fileURLKey = @"_fileURL";
  106. /** NSCoding key for GDTFilePath property. */
  107. static NSString *kGDTFilePathKey = @"_GDTFilePath";
  108. /** NSCoding key for customPrioritizationParams property. */
  109. static NSString *customPrioritizationParams = @"_customPrioritizationParams";
  110. /** NSCoding key for backwards compatibility of GDTCORStoredEvent mappingID property.*/
  111. static NSString *kStoredEventMappingIDKey = @"GDTCORStoredEventMappingIDKey";
  112. /** NSCoding key for backwards compatibility of GDTCORStoredEvent target property.*/
  113. static NSString *kStoredEventTargetKey = @"GDTCORStoredEventTargetKey";
  114. /** NSCoding key for backwards compatibility of GDTCORStoredEvent qosTier property.*/
  115. static NSString *kStoredEventQosTierKey = @"GDTCORStoredEventQosTierKey";
  116. /** NSCoding key for backwards compatibility of GDTCORStoredEvent clockSnapshot property.*/
  117. static NSString *kStoredEventClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey";
  118. /** NSCoding key for backwards compatibility of GDTCORStoredEvent dataFuture property.*/
  119. static NSString *kStoredEventDataFutureKey = @"GDTCORStoredEventDataFutureKey";
  120. /** NSCoding key for backwards compatibility of GDTCORStoredEvent customPrioritizationParams
  121. * property.*/
  122. static NSString *kStoredEventCustomPrioritizationParamsKey =
  123. @"GDTCORStoredEventcustomPrioritizationParamsKey";
  124. + (BOOL)supportsSecureCoding {
  125. return YES;
  126. }
  127. - (id)initWithCoder:(NSCoder *)aDecoder {
  128. GDTCORDataFuture *dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture class]
  129. forKey:kStoredEventDataFutureKey];
  130. if (dataFuture) {
  131. return [self initWithCoderForStoredEventBackwardCompatibility:aDecoder
  132. fileURL:dataFuture.fileURL];
  133. }
  134. NSString *mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:mappingIDKey];
  135. NSInteger target = [aDecoder decodeIntegerForKey:targetKey];
  136. self = [self initWithMappingID:mappingID target:target];
  137. if (self) {
  138. _qosTier = [aDecoder decodeIntegerForKey:qosTierKey];
  139. _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey];
  140. NSURL *fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:fileURLKey];
  141. if (fileURL) {
  142. _GDTFilePath = [fileURL lastPathComponent];
  143. } else {
  144. _GDTFilePath = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGDTFilePathKey];
  145. }
  146. _customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class]
  147. forKey:customPrioritizationParams];
  148. }
  149. return self;
  150. }
  151. - (id)initWithCoderForStoredEventBackwardCompatibility:(NSCoder *)aDecoder
  152. fileURL:(NSURL *)fileURL {
  153. NSString *mappingID = [aDecoder decodeObjectOfClass:[NSString class]
  154. forKey:kStoredEventMappingIDKey];
  155. NSInteger target = [[aDecoder decodeObjectOfClass:[NSNumber class]
  156. forKey:kStoredEventTargetKey] integerValue];
  157. self = [self initWithMappingID:mappingID target:target];
  158. if (self) {
  159. _qosTier = [[aDecoder decodeObjectOfClass:[NSNumber class]
  160. forKey:kStoredEventQosTierKey] integerValue];
  161. _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class]
  162. forKey:kStoredEventClockSnapshotKey];
  163. if (fileURL) {
  164. _GDTFilePath = [fileURL lastPathComponent];
  165. } else {
  166. _GDTFilePath = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGDTFilePathKey];
  167. }
  168. _customPrioritizationParams =
  169. [aDecoder decodeObjectOfClass:[NSDictionary class]
  170. forKey:kStoredEventCustomPrioritizationParamsKey];
  171. }
  172. return self;
  173. }
  174. - (void)encodeWithCoder:(NSCoder *)aCoder {
  175. [aCoder encodeObject:_mappingID forKey:mappingIDKey];
  176. [aCoder encodeInteger:_target forKey:targetKey];
  177. [aCoder encodeInteger:_qosTier forKey:qosTierKey];
  178. [aCoder encodeObject:_clockSnapshot forKey:clockSnapshotKey];
  179. [aCoder encodeObject:_GDTFilePath forKey:kGDTFilePathKey];
  180. [aCoder encodeObject:_customPrioritizationParams forKey:customPrioritizationParams];
  181. }
  182. @end