Commit 1dfd0433 authored by Alex朱枝文's avatar Alex朱枝文

RN初始化

parent d5d3eee0
export NODE_BINARY=$(command -v node)
export NODE_BINARY=/usr/local/Cellar/node/23.4.0/bin/node
################################################################################################################################
##################################################### podspec file for dev #####################################################
################################################################################################################################
Pod::Spec.new do |s|
s.name = 'AliyunLogProducer'
s.version = "4.3.4"
s.summary = 'aliyun log service ios producer.'
s.description = <<-DESC
log service ios producer.
https://help.aliyun.com/document_detail/29063.html
https://help.aliyun.com/product/28958.html
DESC
s.homepage = 'https://github.com/aliyun/aliyun-log-ios-sdk'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'aliyun-log' => 'yulong.gyl@alibaba-inc.com' }
s.source = { :git => 'https://gitee.com/aliyun-sls/aliyun-log-ios-sdk.git', :tag => s.version.to_s }
s.social_media_url = 'http://t.cn/AiRpol8C'
# s.ios.deployment_target = '10.0'
# s.osx.deployment_target = '10.12'
# s.tvos.deployment_target = '10.0'
s.platform = :ios, "10.0"
s.requires_arc = true
s.libraries = 'z'
s.swift_version = "5.0"
# s.xcconfig = { 'GCC_ENABLE_CPP_EXCEPTIONS' => 'YES' }
# s.default_subspec = 'Producer'
s.pod_target_xcconfig = {
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64 i386',
}
s.user_target_xcconfig = {
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64 i386'
}
s.ios.deployment_target = '10.0'
s.tvos.deployment_target = '10.0'
s.osx.deployment_target = '10.12'
s.source_files = 'Sources/Producer/**/*.{h,m}', 'Sources/aliyun-log-c-sdk/**/*.{c,h}'
s.public_header_files = 'Sources/Producer/include/*.h', 'Sources/aliyun-log-c-sdk/include/*.h'
s.resource_bundles = { s.name => ['Sources/Producer/PrivacyInfo.xcprivacy'] }
end
//
// AliyunLog.m
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AliyunLog.h"
#import "TimeUtils.h"
#import "SLSProducer.h"
@interface AliyunLog ()
@property (nonatomic, assign) unsigned int logTime;
@property (nonatomic, strong) NSMutableDictionary *content;
- (BOOL) checkValue: (NSString *)value;
@end
@implementation AliyunLog
- (id) init
{
if (self = [super init])
{
_logTime = (unsigned int) [TimeUtils getTimeInMilliis];
_content = [NSMutableDictionary dictionary];
}
return self;
}
+ (instancetype) log {
return [[AliyunLog alloc] init];
}
- (BOOL) checkValue:(NSString *)value {
return value && [value isKindOfClass:[NSString class]];
}
- (void)PutContent:(NSString *) key value:(NSString *)value
{
[self putContent:key value:value];
}
- (void) putContent: (NSString *) key value: (NSString *) value {
if ([self checkValue:key] && [self checkValue:value]) {
[_content setObject:value forKey:key];
}
}
- (BOOL) putContents: (NSDictionary *) dict {
if (!dict) {
return NO;
}
NSDictionary *tmp = [NSDictionary dictionaryWithDictionary:dict];
NSMutableDictionary *newDict = [NSMutableDictionary dictionary];
BOOL error = NO;
id value = nil;
for (id key in tmp.allKeys) {
if (![key isKindOfClass:[NSString class]]) {
error = YES;
break;
}
value = [tmp objectForKey:key];
if ([value isKindOfClass:[NSString class]]) {
[newDict setObject:value forKey:key];
} else if ([value isKindOfClass:[NSNumber class]]) {
[newDict setObject:[value stringValue] forKey:key];
} else if ([value isKindOfClass:[NSNull class]]) {
[newDict setObject:@"null" forKey:key];
} else if (([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]])
&& [NSJSONSerialization isValidJSONObject:value]) {
[newDict setObject:[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:value
options:kNilOptions
error:nil
]
encoding:NSUTF8StringEncoding]
forKey:key
];
} else {
error = YES;
break;
}
}
if (!error) {
[_content addEntriesFromDictionary:newDict];
} else {
SLSLog(@"Your NSDictionary is not support convert to JSON, all values will not be added, please check your data.");
}
return error;
}
- (void) putContent: (NSString *) key intValue: (int) value {
if ([self checkValue:key]) {
[_content setObject:[NSString stringWithFormat:@"%d", value] forKey:key];
}
}
- (void) putContent: (NSString *) key longValue: (long) value {
if ([self checkValue:key]) {
[_content setObject:[NSString stringWithFormat:@"%ld", value] forKey:key];
}
}
- (void) putContent: (NSString *) key longlongValue: (long long) value {
if ([self checkValue:key]) {
[_content setObject:[NSString stringWithFormat:@"%lld", value] forKey:key];
}
}
- (void) putContent: (NSString *) key floatValue: (float) value {
if ([self checkValue:key]) {
[_content setObject:[NSString stringWithFormat:@"%f", value] forKey:key];
}
}
- (void) putContent: (NSString *) key doubleValue: (double) value {
if ([self checkValue:key]) {
[_content setObject:[NSString stringWithFormat:@"%f", value] forKey:key];
}
}
- (void) putContent: (NSString *) key boolValue: (BOOL) value {
if ([self checkValue:key]) {
[NSNumber numberWithBool:YES];
[_content setObject:(YES == value ? @"YES" : @"NO") forKey:key];
}
}
- (BOOL) putContent: (NSData *) value {
if (!value) {
return NO;
}
if ([value isKindOfClass:[NSNull class]]) {
[self putContent:@"data" value:@"null"];
return YES;
}
NSError *error = nil;
id data = [NSJSONSerialization JSONObjectWithData:value
options:kNilOptions
error:&error
];
if (nil != error) {
NSString *string = [[NSString alloc] initWithData:value encoding:NSUTF8StringEncoding];
[self putContent:@"data" value:string];
return YES;
}
if ([data isKindOfClass:[NSDictionary class]]) {
[self putContents:data];
} else if ([data isKindOfClass:[NSArray class]]) {
[self putContent:@"data" arrayValue:data];
} else {
SLSLog(@"Class %@ not support convert to JSON.", [data class]);
return NO;
}
return YES;
}
- (BOOL) putContent: (NSString *) key dataValue: (NSData *)value {
if ([self checkValue:key] && value && ![value isKindOfClass:[NSNull class]]) {
[_content setObject:[[NSString alloc] initWithData:value
encoding:NSUTF8StringEncoding
]
forKey:key];
return YES;
}
return NO;
}
- (BOOL) putContent: (NSString *) key arrayValue: (NSArray *) value {
if ([self checkValue:key] && value && [NSJSONSerialization isValidJSONObject:value]) {
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:value
options:kNilOptions
error:&error
];
if (nil != error) {
SLSLog(@"error while deserializing NSArray to JSON. error: %@", error.description);
return NO;
}
[_content setObject:[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding
]
forKey:key];
return YES;
}
return NO;
}
- (BOOL) putContent: (NSString *) key dictValue: (NSDictionary *) value {
if ([self checkValue:key] && value && [NSJSONSerialization isValidJSONObject:value]) {
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:value
options:kNilOptions
error:&error
];
if (nil != error) {
SLSLog(@"error while deserializing NSDictionary to JSON. error: %@", error.description);
return NO;
}
[_content setObject:[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding
]
forKey:key];
return YES;
}
return NO;
}
- (NSMutableDictionary *)getContent
{
return _content;
}
- (void)SetTime:(unsigned int) logTime
{
_logTime = logTime;
}
- (unsigned int)getTime
{
return _logTime;
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
//
// LogProducerClient.m
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LogProducerClient.h"
#import "LogProducerConfig.h"
#import "AliyunLog.h"
#import "TimeUtils.h"
@interface LogProducerClient ()
@end
@implementation LogProducerClient
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig
{
return [self initWithLogProducerConfig:logProducerConfig callback:nil];
}
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig callback:(on_log_producer_send_done_function)callback
{
return [self initWithLogProducerConfig:logProducerConfig callback:callback userparams:NULL];
}
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig callback:(on_log_producer_send_done_function)callback userparams: (NSObject *)params
{
if (self = [super init])
{
self->config = logProducerConfig->config;
self->producer = create_log_producer(logProducerConfig->config, *callback, (nil == params ? nil : (__bridge void *)(params)));
self->client = get_log_producer_client(self->producer, nil);
NSString *endpoint = [logProducerConfig getEndpoint];
NSString *project = [logProducerConfig getProject];
if ([endpoint length] != 0 && [project length] != 0) {
[TimeUtils startUpdateServerTime:endpoint project:project];
}
enable = YES;
}
return self;
}
- (void)DestroyLogProducer
{
if (!enable) {
return;
}
enable = NO;
destroy_log_producer(self->producer);
CFRelease(self->config->user_params);
}
- (LogProducerResult)AddLog:(AliyunLog *) log
{
return [self AddLog:log flush:0];
}
- (LogProducerResult)AddLog:(AliyunLog *) log flush:(int) flush
{
if (!enable || self->client == NULL || log == nil) {
return LogProducerInvalid;
}
NSMutableDictionary *logContents = [log getContent];
int pairCount = (int)[logContents count];
char **keyArray = (char **)malloc(sizeof(char *)*(pairCount));
char **valueArray = (char **)malloc(sizeof(char *)*(pairCount));
int32_t *keyCountArray = (int32_t*)malloc(sizeof(int32_t)*(pairCount));
int32_t *valueCountArray = (int32_t*)malloc(sizeof(int32_t)*(pairCount));
int ids = 0;
for (NSString *key in logContents) {
NSString *string = nil;
id value = logContents[key];
if ([value isKindOfClass:[NSNumber class]]) {
string = [value stringValue];
} else if ([value isKindOfClass: [NSString class]]){
string = value;
} else {
continue;
}
char* keyChar=[self convertToChar:key];
char* valueChar=[self convertToChar:string];
keyArray[ids] = keyChar;
valueArray[ids] = valueChar;
keyCountArray[ids] = (int32_t)strlen(keyChar);
valueCountArray[ids] = (int32_t)strlen(valueChar);
ids = ids + 1;
}
log_producer_result res = log_producer_client_add_log_with_len_time_int32(self->client, [log getTime], pairCount, keyArray, keyCountArray, valueArray, valueCountArray, flush);
for(int i=0;i<pairCount;i++) {
free(keyArray[i]);
free(valueArray[i]);
}
free(keyArray);
free(valueArray);
free(keyCountArray);
free(valueCountArray);
return res;
}
-(char*)convertToChar:(NSString*)strtemp
{
// NSUInteger len = [strtemp lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
// if (len > 1000000) return strdup([strtemp UTF8String]);
// char cStr [len];
// [strtemp getCString:cStr maxLength:len encoding:NSUTF8StringEncoding];
// return strdup(cStr);
NSUInteger len = [strtemp lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
// the limit on stack size will cause crash
// https://github.com/CocoaLumberjack/CocoaLumberjack/issues/38
char* cStr = malloc(sizeof(char) * len);
[strtemp getCString:cStr maxLength:len encoding:NSUTF8StringEncoding];
return cStr;
}
@end
//
// LogProducerConfig.m
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#ifdef DEBUG
#define SLSLog(...) NSLog(__VA_ARGS__)
#else
#define SLSLog(...)
#endif
#import "SLSSystemCapabilities.h"
#import <Foundation/Foundation.h>
#import "LogProducerConfig.h"
#import "inner_log.h"
#import "TimeUtils.h"
#import "SLSURLSession.h"
#import "SLSHttpHeader.h"
#import "log_define.h"
@interface LogProducerConfig ()
@property(nonatomic, strong) SLSHttpHeaderInjector injector;
@property(nonatomic, assign) BOOL enablePersistent;
@end
@implementation LogProducerConfig
static int os_http_post(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response)
{
size_t request_id_len = sizeof(char) * 256;
http_response->requestID = (char*) malloc(request_id_len);
memset(http_response->requestID, 0, request_id_len);
size_t error_message_len = sizeof(char) * 256;
http_response->errorMessage = (char*) malloc(error_message_len);
memset(http_response->errorMessage, 0, error_message_len);
if(url == NULL || *url == 0 || header_array == NULL || header_count < 1 || data == NULL || data_len <= 0) {
http_response->statusCode = 400;
strcpy(http_response->requestID, "");
strcpy(http_response->errorMessage, "request is incorrect");
return 400; // bad request
}
NSString *urlString = [NSString stringWithUTF8String:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"POST"];
[request setURL:[NSURL URLWithString:urlString]];
// set headers
for(int i=0; i<header_count; i++) {
char *kv = header_array[i];
if(kv != NULL) {
char *eq = strchr(kv, ':');
if(eq != NULL && eq != kv && eq[1] != 0) {
*eq = 0;
[request addValue:[NSString stringWithUTF8String:eq+1] forHTTPHeaderField:[NSString stringWithUTF8String:kv]];
*eq = '='; // restore
}
}
}
// set body
NSData *postData = [NSData dataWithBytes:data length:data_len];
[request setHTTPBody:postData];
// send
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSData *resData = [SLSURLSession sendSynchronousRequest:request
returningResponse:&response
error:&error
];
if(response != nil){
int responseCode = (int)[response statusCode];
http_response->statusCode = responseCode;
NSDictionary *fields = [response allHeaderFields];
NSString *timeVal = fields[@"x-log-time"];
if ([timeVal length] != 0) {
NSInteger serverTime = [timeVal integerValue];
if (serverTime > 1500000000 && serverTime < 4294967294) {
[TimeUtils updateServerTime:serverTime];
}
}
if (responseCode != 200) {
NSString *res = [[NSString alloc] initWithData:resData encoding:NSUTF8StringEncoding];
strncpy(http_response->requestID, res.length > 0 ? [res UTF8String] : "", request_id_len);
SLSLog(@"%ld %@ %@", [response statusCode], [response allHeaderFields], res);
} else {
NSString *requestId = fields[@"x-log-requestid"];
strncpy(http_response->requestID, requestId.length > 0 ? [requestId UTF8String] : "", request_id_len);
}
return responseCode;
} else {
http_response->statusCode = -1;
strcpy(http_response->requestID, "");
if(error != nil){
NSString *errorMessage = [NSString stringWithFormat:@"domain: %@, code: %ld, description: %@", error.domain, (long)error.code, error.localizedDescription];
SLSLog(@"os_http_post error: %@", errorMessage);
strncpy(http_response->errorMessage, [errorMessage UTF8String], error_message_len);
if (error.code == kCFURLErrorUserCancelledAuthentication) {
return 401;
}
if (error.code == kCFURLErrorBadServerResponse) {
return 500;
}
}
return -1;
}
}
static char* nsstring_to_char(NSString *str) {
NSUInteger len = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
char cStr [len];
[str getCString:cStr maxLength:len encoding:NSUTF8StringEncoding];
return strdup(cStr);
}
+ (void)load{
log_set_http_post_func(os_http_post);
}
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore
{
if (self = [super init])
{
self = [self initWithEndpoint:endpoint project:project logstore:logstore accessKeyID:nil accessKeySecret:nil];
}
return self;
}
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore accessKeyID:(NSString *)accessKeyID accessKeySecret:(NSString *)accessKeySecret
{
if (self = [super init])
{
self = [self initWithEndpoint:endpoint project:project logstore:logstore accessKeyID:accessKeyID accessKeySecret:accessKeySecret securityToken:nil];
}
return self;
}
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore accessKeyID:(NSString *)accessKeyID accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken
{
if (self = [super init])
{
self->config = create_log_producer_config();
self->config->user_params = (__bridge_retained void *)(self);
#if SLS_HOST_MAC
log_producer_config_set_source(self->config, "macOS");
#elif SLS_HOST_TV
log_producer_config_set_source(self->config, "tvOS");
#else
log_producer_config_set_source(self->config, "iOS");
#endif
log_producer_config_set_packet_timeout(self->config, 3000);
log_producer_config_set_packet_log_count(self->config, 1024);
log_producer_config_set_packet_log_bytes(self->config, 1024*1024);
log_producer_config_set_send_thread_count(self->config, 1);
log_producer_config_set_drop_unauthorized_log(self->config, 0);
log_producer_config_set_drop_delay_log(self->config, 0);
log_set_get_time_unix_func(time_func);
log_set_http_header_inject_func(sls_ios_http_header_inject_func);
log_set_http_header_release_inject_func(sls_ios_http_header_release_inject_func);
[self setHttpHeaderInjector:^NSArray<NSString *> *(NSArray<NSString *> *srcHeaders) {
return [SLSHttpHeader getHeaders:srcHeaders, nil];
}];
[self setEndpoint:endpoint];
[self setProject:project];
[self setLogstore:logstore];
[self setAccessKeyId:accessKeyID];
[self setAccessKeySecret:accessKeySecret];
if ([securityToken length] != 0) {
[self ResetSecurityToken:accessKeyID accessKeySecret:accessKeySecret securityToken:securityToken];
}
}
return self;
}
void sls_ios_http_header_inject_func(log_producer_config *config, char **src_headers, int src_count, char **dest_headers, int *dest_count) {
NSMutableArray<NSString *> *headers = [NSMutableArray array];
for (int i = 0; i < src_count; i ++) {
char *kv = src_headers[i];
if (NULL == kv) {
continue;
}
char *eq = strchr(kv, ':');
if (NULL == eq || eq == kv || eq[1] == 0) {
continue;
}
*eq = 0;
[headers addObject:[NSString stringWithUTF8String:kv]];
[headers addObject:[NSString stringWithUTF8String:(eq+1)]];
}
LogProducerConfig *producer = (__bridge LogProducerConfig *)(config->user_params);
NSArray<NSString *> *injectedHeaders = producer->_injector(headers);
if(nil == injectedHeaders || injectedHeaders.count == 0) {
return;
}
NSUInteger count = injectedHeaders.count / 2;
for (int i = 0; i < count; i ++) {
const char *key = [[injectedHeaders objectAtIndex:2*i] UTF8String];
const char *value = [[injectedHeaders objectAtIndex:2*i+1] UTF8String];
unsigned long len = strlen(key) + strlen(value) + strlen(":") + 1;
// dynamic alloc 'len' of char* for reduce mem cost
char *kv = (char *) malloc(sizeof(char) * len);
memset(kv, 0, sizeof(char) * len);
strcat(kv, key);
strcat(kv, ":");
strcat(kv, value);
dest_headers[i] = kv;
(*dest_count)++;
}
}
void sls_ios_http_header_release_inject_func(log_producer_config *config, char **dest_headers, int dest_count) {
if (0 == dest_count) {
return;
}
for (int i = 0; i < dest_count; i ++) {
free(dest_headers[i]);
}
}
- (void) setHttpHeaderInjector: (SLSHttpHeaderInjector) injector {
_injector = injector;
}
unsigned int time_func() {
NSInteger timeInMillis = [TimeUtils getTimeInMilliis];
return (unsigned int) timeInMillis;
}
- (void)setEndpoint:(NSString *)endpoint
{
if (endpoint.length > 0 && ![[endpoint lowercaseString] hasPrefix:@"http"]) {
endpoint = [NSString stringWithFormat:@"https://%@", endpoint];
}
self->endpoint = endpoint;
log_producer_config_set_endpoint(self->config, [endpoint UTF8String]);
}
- (NSString *)getEndpoint
{
return self->endpoint;
}
- (void)setProject:(NSString *)project
{
self->project = project;
log_producer_config_set_project(self->config, [project UTF8String]);
}
- (NSString *)getProject
{
return self->project;
}
- (void)setLogstore:(NSString *)logstore
{
self->logstore = logstore;
log_producer_config_set_logstore(self->config, [logstore UTF8String]);
}
- (NSString *) getLogStore {
return self->logstore;
}
- (void)SetTopic:(NSString *) topic
{
const char *topicChar=[topic UTF8String];
log_producer_config_set_topic(self->config, topicChar);
}
- (void)SetSource:(NSString *)source
{
const char *sourceChar = [source UTF8String];
log_producer_config_set_source(self->config, sourceChar);
}
- (void)AddTag:(NSString *) key value:(NSString *)value
{
const char *keyChar=[key UTF8String];
const char *valueChar=[value UTF8String];
log_producer_config_add_tag(self->config, keyChar, valueChar);
}
- (void)SetPacketLogBytes:(int) num
{
log_producer_config_set_packet_log_bytes(self->config, num);
}
- (void)SetPacketLogCount:(int) num
{
log_producer_config_set_packet_log_count(self->config, num);
}
- (void)SetPacketTimeout:(int) num
{
log_producer_config_set_packet_timeout(self->config, num);
}
- (void)SetMaxBufferLimit:(int) num
{
log_producer_config_set_max_buffer_limit(self->config, num);
}
- (void)SetSendThreadCount:(int) num
{
if (_enablePersistent && 1 != num) {
num = 1;
}
log_producer_config_set_send_thread_count(self->config, num);
}
- (void)SetPersistent:(int) num
{
_enablePersistent = 1 == num;
log_producer_config_set_persistent(self->config, num);
if (_enablePersistent) {
[self SetSendThreadCount:1];
}
}
- (void)SetPersistentFilePath:(NSString *) path
{
const char *pathChar=[path UTF8String];
log_producer_config_set_persistent_file_path(self->config, pathChar);
}
- (void)SetPersistentForceFlush:(int) num
{
log_producer_config_set_persistent_force_flush(self->config, num);
}
- (void)SetPersistentMaxFileCount:(int ) num
{
log_producer_config_set_persistent_max_file_count(self->config, num);
}
- (void)SetPersistentMaxFileSize:(int) num
{
log_producer_config_set_persistent_max_file_size(self->config, num);
}
- (void)SetPersistentMaxLogCount:(int) num
{
log_producer_config_set_persistent_max_log_count(self->config, num);
}
- (void)SetUsingHttp:(int) num;
{
log_producer_config_set_using_http(self->config, num);
}
- (void)SetNetInterface:(NSString *) netInterface;
{
const char *netInterfaceChar=[netInterface UTF8String];
log_producer_config_set_net_interface(self->config, netInterfaceChar);
}
- (void)SetConnectTimeoutSec:(int) num;
{
log_producer_config_set_connect_timeout_sec(self->config, num);
}
- (void)SetSendTimeoutSec:(int) num;
{
log_producer_config_set_send_timeout_sec(self->config, num);
}
- (void)SetDestroyFlusherWaitSec:(int) num;
{
log_producer_config_set_destroy_flusher_wait_sec(self->config, num);
}
- (void)SetDestroySenderWaitSec:(int) num;
{
log_producer_config_set_destroy_sender_wait_sec(self->config, num);
}
- (void)SetCompressType:(int) num;
{
log_producer_config_set_compress_type(self->config, num);
}
- (void)SetNtpTimeOffset:(int) num;
{
log_producer_config_set_ntp_time_offset(self->config, num);
}
- (void)SetMaxLogDelayTime:(int) num;
{
log_producer_config_set_max_log_delay_time(self->config, num);
}
- (void)SetDropDelayLog:(int) num;
{
log_producer_config_set_drop_delay_log(self->config, num);
}
- (void)SetDropUnauthorizedLog:(int) num;
{
log_producer_config_set_drop_unauthorized_log(self->config, num);
}
- (void)SetGetTimeUnixFunc:(unsigned int (*)()) f;
{
log_set_get_time_unix_func(f);
}
- (int)IsValid;
{
return log_producer_config_is_valid(self->config);
}
- (int)IsEnabled;
{
return log_producer_persistent_config_is_enabled(self->config);
}
- (void)setAccessKeyId:(NSString *)accessKeyId
{
log_producer_config_set_access_id(self->config, [accessKeyId UTF8String]);
}
- (void)setAccessKeySecret:(NSString *)accessKeySecret
{
log_producer_config_set_access_key(self->config, [accessKeySecret UTF8String]);
}
- (void) setUseWebtracking: (BOOL) enable {
log_producer_config_set_use_webtracking(self->config, enable ? 1 : 0);
}
- (void)ResetSecurityToken:(NSString *) accessKeyID accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken
{
if ([accessKeyID length] == 0 || [accessKeySecret length] == 0 || [securityToken length] == 0) {
return;
}
const char *accessKeyIDChar=[accessKeyID UTF8String];
const char *accessKeySecretChar=[accessKeySecret UTF8String];
const char *securityTokenChar=[securityToken UTF8String];
log_producer_config_reset_security_token(self->config, accessKeyIDChar, accessKeySecretChar, securityTokenChar);
}
+ (void)Debug
{
aos_log_set_level(AOS_LOG_DEBUG);
}
@end
//
// NSDateFormatter+SLS.m
// AliyunLogProducer
//
// Created by gordon on 2022/6/23.
//
#import "NSDateFormatter+SLS.h"
@interface NSDateFormatter()
@end
@implementation NSDateFormatter (SLS)
+ (instancetype) sharedInstance {
NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
NSDateFormatter *formater = [threadDict objectForKey:@"sls_date_formater"];
if (!formater) {
@synchronized (self) {
if (!formater) {
formater = [[NSDateFormatter alloc] init];
[formater setTimeZone:[NSTimeZone systemTimeZone]];
[threadDict setObject:formater forKey:@"sls_date_formater"];
}
}
}
return formater;
}
- (NSDate *) fromString: (NSString *) date {
[self setDateFormat:@"YYYY-MM-dd HH:mm:ss:SSS"];
return [self dateFromString:date];
}
- (NSDate *) fromString: (NSString *) date formatter: (NSString *) formatter {
[self setDateFormat:formatter];
return [self dateFromString:date];
}
- (NSDate *) fromStringZ: (NSString *) date {
[self setDateFormat:@"YYYY-MM-dd HH:mm:ss.SSS Z"];
return [self dateFromString:date];
}
- (NSString *) fromDate: (NSDate *) date {
[self setDateFormat:@"YYYY-MM-dd HH:mm:ss:SSS"];
return [self stringFromDate:date];
}
- (NSString *) fromDate: (NSDate *) date formatter: (NSString *) formatter {
[self setDateFormat:formatter];
return [self stringFromDate:date];
}
@end
//
// NSDictionary+SLS.m
// AliyunLogProducer
//
// Created by gordon on 2022/8/16.
//
#import "NSDictionary+SLS.h"
@implementation NSDictionary (SLS)
+ (NSDictionary *) dictionaryWithNSString: (NSString *) string {
if (!string) {
return nil;
}
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error
];
if (nil != error) {
return nil;
}
return dict;
}
@end
//
// NSString+SLS.m
// AliyunLogProducer
//
// Created by gordon on 2022/8/11.
//
#import "NSString+SLS.h"
@implementation NSString (SLS)
- (NSString *) base64Encode {
return [[self dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
- (NSString *) base64Decode {
return [[NSString alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:self
options:NSDataBase64DecodingIgnoreUnknownCharacters
]
encoding:NSUTF8StringEncoding
];
}
- (NSDictionary *) toDictionary {
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error
];
if (error) {
NSLog(@"NSString to NSDictionary error. %@", error);
return [NSDictionary dictionary];
}
return dict;
}
+ (NSString *) stringWithDictionary: (NSDictionary *) dictionary {
if (![NSJSONSerialization isValidJSONObject:dictionary]) {
return [NSString string];
}
NSJSONWritingOptions options = kNilOptions;
if (@available(iOS 11.0, macOS 10.13, watchOS 4.0, tvOS 11.0, *)) {
options = NSJSONWritingSortedKeys;
}
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary
options:options
error:&error
];
if (nil != error) {
return [NSString string];
}
return [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding
];
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
</dict>
</array>
</dict>
</plist>
//
// HttpHeader.m
// Pods
//
// Created by gordon on 2022/9/21.
//
#import "SLSHttpHeader.h"
#import "SLSUtils.h"
@implementation SLSHttpHeader
+ (NSArray<NSString *> *) getHeaders: (NSArray<NSString *> *) srcHeaders, ... NS_REQUIRES_NIL_TERMINATION {
NSMutableArray<NSString *> *headers = [srcHeaders mutableCopy];
#if SLS_HOST_MAC
NSMutableString *userAgent = [NSMutableString stringWithFormat:@"sls-ios-sdk/%@/macOS", [SLSUtils getSdkVersion]];
#elif SLS_HOST_TV
NSMutableString *userAgent = [NSMutableString stringWithFormat:@"sls-ios-sdk/%@/tvOS", [SLSUtils getSdkVersion]];
#else
NSMutableString *userAgent = [NSMutableString stringWithFormat:@"sls-ios-sdk/%@", [SLSUtils getSdkVersion]];
#endif
[userAgent appendString:@";"];
[headers addObject:@"User-agent"];
va_list args;
NSString *arg;
va_start(args, srcHeaders);
while ((arg = va_arg(args, NSString*))) {
[userAgent appendString:arg];
[userAgent appendString:@";"];
}
va_end(args);
[headers addObject:[userAgent substringToIndex:userAgent.length-1]];
return headers;
}
@end
//
// SLSURLSession.h
// AliyunLogProducer
//
// Created by gordon on 2022/8/16.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SLSURLSession : NSObject
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse *_Nullable*_Nullable)response
error:(NSError **)error;
@end
NS_ASSUME_NONNULL_END
//
// SLSURLSession.m
// AliyunLogProducer
//
// Created by gordon on 2022/8/16.
//
#import "SLSURLSession.h"
@implementation SLSURLSession
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse *_Nullable*_Nullable)response
error:(NSError **)error {
// ref: https://stackoverflow.com/a/37829399/1760982
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
NSError __block *err = NULL;
NSData __block *data;
NSURLResponse __block *resp;
[[[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData* _data, NSURLResponse* _response, NSError* _error) {
resp = _response;
err = _error;
data = _data;
dispatch_group_leave(group);
}] resume];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if (response)
{
*response = resp;
}
if (error)
{
*error = err;
}
return data;
}
@end
//
// SLSUtils.m
// Pods
//
// Created by gordon on 2022/9/21.
//
#import "SLSUtils.h"
#import "AliyunLogProducer.h"
@implementation SLSUtils
+ (NSString *) getSdkVersion {
return SLS_SDK_VERSION;
}
@end
//
// TimeUtils.m
// AliyunLogProducer
//
// Created by gordon on 2021/6/8.
// Copyright © 2021 lichao. All rights reserved.
//
#import "TimeUtils.h"
#import "LogProducerConfig.h"
#import <sys/sysctl.h>
#import "NSDateFormatter+SLS.h"
@interface TimeUtils ()
+(NSTimeInterval) elapsedRealtime;
@end
static NSInteger serverTime = 0;
static NSTimeInterval elapsedRealtime = 0;
@implementation TimeUtils
+(void) startUpdateServerTime: (NSString *)endpoint project:(nonnull NSString *)project
{
if (!endpoint || endpoint.length <=0 ) {
return;
}
NSURL *url = [NSURL URLWithString:endpoint];
if (nil == url || !url.host || url.host.length <= 0) {
return;
}
NSString *urlString = [NSString stringWithFormat:@"https://%@.%@/servertime", project, url.host];
// NSString *url = @"https://cn-shanghai-staging-share.sls.aliyuncs.com/servertime";
// NSString *urlString = [NSString stringWithUTF8String:[url UTF8String]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod: @"GET"];
[request setURL:[NSURL URLWithString:urlString]];
[request addValue:@"0.6.0" forHTTPHeaderField:@"x-log-apiversion"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (response != nil) {
NSHTTPURLResponse *httpResponse = response;
NSDictionary *fields = [httpResponse allHeaderFields];
NSString *timeVal = fields[@"x-log-time"];
if ([timeVal length] != 0) {
NSInteger serverTime = [timeVal integerValue];
if (serverTime > 1500000000 && serverTime < 4294967294) {
[TimeUtils updateServerTime:serverTime];
}
}
}
}];
}
+(void) updateServerTime: (NSInteger) timeInMillis
{
serverTime = timeInMillis;
elapsedRealtime = [self elapsedRealtime];
}
+(NSInteger) getTimeInMilliis
{
if( 0L == elapsedRealtime) {
NSInteger time = [[NSDate date] timeIntervalSince1970];
return time;
}
NSInteger delta = [self elapsedRealtime] - elapsedRealtime;
return serverTime + delta;
}
+(void) fixTime: (AliyunLog *)log
{
if(!log) {
return;
}
NSMutableDictionary *dictionary = [log getContent];
if (!dictionary || [dictionary count] == 0) {
return;
}
if (![dictionary objectForKey:@"local_timestamp"]) {
return;
}
NSString *local_timestamp = [NSString stringWithString:[[log getContent] objectForKey:@"local_timestamp"]];
if ([local_timestamp length] < 10) {
return;
}
NSLog(@"log.getTime: %d", [log getTime]);
NSDate *date = [NSDate date];
NSString *timestamp = [local_timestamp substringWithRange:NSMakeRange(0, 10)];
NSString *timestampMillisPart = [[NSString stringWithFormat:@"%.0f", [date timeIntervalSince1970] * 1000] substringFromIndex:10];
local_timestamp = [timestamp stringByAppendingString:timestampMillisPart];
NSDateFormatter *dateFormatter = [NSDateFormatter sharedInstance];
date = [NSDate dateWithTimeIntervalSince1970:[local_timestamp doubleValue] / 1000];
NSString *local_time = [dateFormatter fromDate:date];
[log PutContent:@"local_timestamp_fixed" value:local_timestamp];
[log PutContent:@"local_time_fixed" value:local_time];
}
+ (NSTimeInterval)elapsedRealtime {
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
struct timeval now;
struct timezone tz;
gettimeofday(&now, &tz);
double uptime = -1;
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0)
{
uptime = now.tv_sec - boottime.tv_sec;
uptime += (double)(now.tv_usec - boottime.tv_usec) / 1000000.0;
return uptime;
}
return [[NSProcessInfo processInfo] systemUptime];
}
@end
//
// AliyunLog.h
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#ifndef AliyunLog_h
#define AliyunLog_h
#endif /* AliyunLog_h */
@interface AliyunLog : NSObject
+ (instancetype) log;
/// Put string value to log with NSString key. This method will be removed in the future.
/// @param key NSString
/// @param value BOOL
/// swift compile error, ref: https://stackoverflow.com/questions/52557738/objective-c-framework-used-in-swift-ambiguous-use-of-method-error
- (void) PutContent: (NSString *) key value: (NSString *) value __attribute__((deprecated("use method putContent:value:"))) NS_SWIFT_UNAVAILABLE("deprecated method not available in Swift");
/// Put string value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key value: (NSString *) value;
/// Put int value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key intValue: (int) value;
/// Put long value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key longValue: (long) value;
/// Put long long value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key longlongValue: (long long) value;
/// Put float value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key floatValue: (float) value;
/// Put double value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key doubleValue: (double) value;
/// Put bool value to log with NSString key.
/// @param key NSString
/// @param value BOOL
- (void) putContent: (NSString *) key boolValue: (BOOL) value;
/// Put NSData contents to log. All K-V from this dictionaray will be added to the root node.
/// @param value NSData, must be able to convert to JSON, if not will return NO.
/// @return BOOL YES, put success; NO, put fails.
- (BOOL) putContent: (NSData *) value;
/// Put NSData with key to log. All K-V from this array will be added to the node with the given specified key.
/// @param key NSString
/// @param value NSData, must be able to convert to JSON, if not will return NO.
- (BOOL) putContent: (NSString *) key dataValue: (NSData *) value;
/// Put NSArray with key to log. All K-V from this array will be added to the node with the given specified key.
/// @param key NSString
/// @param value NSArray, must be able to convert to JSON, if not will return NO.
- (BOOL) putContent: (NSString *) key arrayValue: (NSArray *) value;
/// Put NSDictionaray with key to log. All K-V from this dictionaray will be added to the node with the given specified key.
/// @param key NSString
/// @param value NSDictionaray, must be able to convert to JSON, if not will return NO.
- (BOOL) putContent: (NSString *) key dictValue: (NSDictionary *) value;
/// Put NSDictionaray contents to log. All K-V from this dictionaray will be added to the root node.
/// @param dict NSDictionaray, must be able to convert to JSON, if not will return NO.
/// @return BOOL YES, put success; NO, put fails.
- (BOOL) putContents: (NSDictionary *) dict;
- (NSMutableDictionary *) getContent;
/// Should not SetTime directly. This method will be removed in the future.
- (void)SetTime:(unsigned int) logTime;
- (unsigned int) getTime;
@end
//
// AliyunLogProducer.h
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for AliyunLogProducer.
FOUNDATION_EXPORT double AliyunLogProducerVersionNumber;
//! Project version string for AliyunLogProducer.
FOUNDATION_EXPORT const unsigned char AliyunLogProducerVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <AliyunLogProducer/PublicHeader.h>
#import "SLSProducer.h"
//// AliyunLogCore
//#if __has_include("AliyunLogCore/AliyunLogCore.h")
//#import "AliyunLogCore/AliyunLogCore.h"
//#elif __has_include("AliyunLogCore.h")
//#import "AliyunLogCore.h"
//#endif
//// AliyunLogCrashReporter
//#if __has_include("AliyunLogCrashReporter/AliyunLogCrashReporter.h")
//#import "AliyunLogCrashReporter/AliyunLogCrashReporter.h"
//#elif __has_include("AliyunLogCrashReporter.h")
//#import "AliyunLogCrashReporter.h"
//#endif
//
//// AliyunLogNetworkDiagnosis
//#if __has_include("AliyunLogNetworkDiagnosis/AliyunLogNetworkDiagnosis.h")
//#import "AliyunLogNetworkDiagnosis/AliyunLogNetworkDiagnosis.h"
//#elif __has_include("AliyunLogNetworkDiagnosis.h")
//#import "AliyunLogNetworkDiagnosis.h"
//#endif
//
//// AliyunLogTrace
//#if __has_include("AliyunLogTrace/AliyunLogTrace.h")
//#import "AliyunLogTrace/AliyunLogTrace.h"
//#elif __has_include("AliyunLogTrace.h")
//#import "AliyunLogTrace.h"
//#endif
//
//// Swift
//#if __has_include("AliyunLogProducer-Swift.h")
//#import "AliyunLogProducer-Swift.h"
//#endif
//
//// AliyunLogURLSession
//#if __has_include("AliyunLogURLSession/AliyunLogURLSession-Swift.h")
//#import "AliyunLogURLSession/AliyunLogURLSession-Swift.h"
//#endif
//
// LogProducerClient.h
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#ifndef LogProducerClient_h
#define LogProducerClient_h
#endif /* LogProducerClient_h */
#import "log_producer_client.h"
#import "LogProducerConfig.h"
#import "AliyunLog.h"
typedef void (^AddLogInterceptor)(AliyunLog *log);
@interface LogProducerClient : NSObject
{
@private log_producer* producer;
@private log_producer_config* config;
@private log_producer_client* client;
@private BOOL _enableTrack;
@private BOOL enable;
}
typedef NS_ENUM(NSInteger, LogProducerResult) {
LogProducerOK = 0,
LogProducerInvalid,
LogProducerWriteError,
LogProducerDropError,
LogProducerSendNetworkError,
LogProducerSendQuotaError,
LogProducerSendUnauthorized,
LogProducerSendServerError,
LogProducerSendDiscardError,
LogProducerSendTimeError,
LogProducerSendExitBufferdF,
LogProducerParametersInvalid,
LogProducerPERSISTENT_Error = 99
};
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig;
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig callback:(on_log_producer_send_done_function)callback;
- (id) initWithLogProducerConfig:(LogProducerConfig *)logProducerConfig callback:(on_log_producer_send_done_function)callback userparams: (NSObject *)params;
- (void)DestroyLogProducer;
- (LogProducerResult)AddLog:(AliyunLog *) log;
- (LogProducerResult)AddLog:(AliyunLog *) log flush:(int) flush;
@end
//
// LogProducerConfig.h
// AliyunLogProducer
//
// Created by lichao on 2020/9/27.
// Copyright © 2020 lichao. All rights reserved.
//
#ifndef LogProducerConfig_h
#define LogProducerConfig_h
#endif /* LogProducerConfig_h */
#import "log_producer_config.h"
#import "log_http_interface.h"
typedef NSArray<NSString *> * (^SLSHttpHeaderInjector) (NSArray<NSString *> *srcHeaders);
@interface LogProducerConfig : NSObject
{
@package log_producer_config* config;
@private NSString *endpoint;
@private NSString *project;
@private NSString *logstore;
}
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore accessKeyID:(NSString *)accessKeyID accessKeySecret:(NSString *)accessKeySecret;
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore accessKeyID:(NSString *)accessKeyID accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken;
- (id) initWithEndpoint:(NSString *) endpoint project:(NSString *)project logstore:(NSString *)logstore;
- (void)SetTopic:(NSString *) topic;
- (void)SetSource:(NSString *) source;
- (void)AddTag:(NSString *) key value:(NSString *)value;
- (void)SetPacketLogBytes:(int) num;
- (void)SetPacketLogCount:(int) num;
- (void)SetPacketTimeout:(int) num;
- (void)SetMaxBufferLimit:(int) num;
- (void)SetSendThreadCount:(int) num;
- (void)SetPersistent:(int) num;
- (void)SetPersistentFilePath:(NSString *) path;
- (void)SetPersistentForceFlush:(int) num;
- (void)SetPersistentMaxFileCount:(int) num;
- (void)SetPersistentMaxFileSize:(int) num;
- (void)SetPersistentMaxLogCount:(int) num;
- (void)SetUsingHttp:(int) num;
- (void)SetNetInterface:(NSString *) netInterface;
- (void)SetConnectTimeoutSec:(int) num;
- (void)SetSendTimeoutSec:(int) num;
- (void)SetDestroyFlusherWaitSec:(int) num;
- (void)SetDestroySenderWaitSec:(int) num;
- (void)SetCompressType:(int) num;
- (void)SetNtpTimeOffset:(int) num;
- (void)SetMaxLogDelayTime:(int) num;
- (void)SetDropDelayLog:(int) num;
- (void)SetDropUnauthorizedLog:(int) num;
- (void)SetGetTimeUnixFunc:(unsigned int (*)()) f;
- (int)IsValid;
- (int)IsEnabled;
- (void) setEndpoint: (NSString *)endpoint;
- (NSString *)getEndpoint;
- (void) setProject: (NSString *)project;
- (NSString *)getProject;
- (void) setLogstore: (NSString *)logstore;
- (NSString *) getLogStore;
- (void) ResetSecurityToken:(NSString *) accessKeyID accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken;
- (void) setAccessKeyId: (NSString *)accessKeyId;
- (void) setAccessKeySecret: (NSString *) accessKeySecret;
- (void) setUseWebtracking: (BOOL) enable;
- (void) setHttpHeaderInjector: (SLSHttpHeaderInjector) injector;
+ (void) Debug;
@end
//
// NSDateFormatter+SLS.h
// AliyunLogProducer
//
// Created by gordon on 2022/6/23.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDateFormatter (SLS)
+ (instancetype) sharedInstance;
- (NSDate *) fromString: (NSString *) date;
- (NSDate *) fromString: (NSString *) date formatter: (NSString *) formatter;
- (NSDate *) fromStringZ: (NSString *) date;
- (NSString *) fromDate: (NSDate *) date;
- (NSString *) fromDate: (NSDate *) date formatter: (NSString *) formatter;
@end
NS_ASSUME_NONNULL_END
//
// NSDictionary+SLS.h
// AliyunLogProducer
//
// Created by gordon on 2022/8/16.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (SLS)
+ (NSDictionary *) dictionaryWithNSString: (NSString *) string;
@end
NS_ASSUME_NONNULL_END
//
// NSString+SLS.h
// AliyunLogProducer
//
// Created by gordon on 2022/8/11.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (SLS)
/**
* Encode string with base64.
*/
- (NSString *) base64Encode;
/**
* Decode string with base64.
*/
- (NSString *) base64Decode;
/**
* String to dictionary.
*/
- (NSDictionary *) toDictionary;
/**
* String with dictionary.
*/
+ (NSString *) stringWithDictionary: (NSDictionary *) dictionary;
@end
NS_ASSUME_NONNULL_END
//
// HttpHeader.h
// Pods
//
// Created by gordon on 2022/9/21.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SLSHttpHeader : NSObject
+ (NSArray<NSString *> *) getHeaders: (NSArray<NSString *> *) srcHeaders, ... NS_REQUIRES_NIL_TERMINATION;
@end
NS_ASSUME_NONNULL_END
//
// SLSProducer.h
// AliyunLogProducer
//
// Created by gordon on 2023/1/18.
// Copyright © 2023 com.aysls.ios. All rights reserved.
//
#import <Foundation/Foundation.h>
#ifndef AliyunlogCommon_h
#define AliyunlogCommon_h
//! Xcode 13 has a new option called "Manage Version and Build Number" which is ticked by default.
//! If left checked, Xcode will automatically set your app's version number which (rather counter-intuitively), will also apply to all included frameworks
//! https://stackoverflow.com/a/31418789/1760982
#define SLS_SDK_VERSION @"3.1.19"
#define SLSLog(fmt, ...) NSLog((@"[SLSiOS] %s " fmt), __FUNCTION__, ##__VA_ARGS__);
#ifdef DEBUG
#define SLSLogV(fmt, ...) NSLog((@"[SLSiOS] %s:%d: " fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define SLSLogV(...);
#endif
#endif /* AliyunlogCommon_h */
#import "LogProducerClient.h"
#import "LogProducerConfig.h"
#import "AliyunLog.h"
#import "NSDateFormatter+SLS.h"
#import "NSDictionary+SLS.h"
#import "NSString+SLS.h"
#import "SLSHttpHeader.h"
#import "SLSSystemCapabilities.h"
#import "SLSUtils.h"
#import "TimeUtils.h"
//
// SLSSystemCapabilities.h
// Pods
//
// Created by gordon on 2022/3/9.
//
#ifndef SLSSystemCapabilities_h
#define SLSSystemCapabilities_h
#ifdef __APPLE__
#include <TargetConditionals.h>
#define SLS_HOST_APPLE 1
#endif
#define SLS_HOST_IOS (SLS_HOST_APPLE && TARGET_OS_IOS)
#define SLS_HOST_TV (SLS_HOST_APPLE && TARGET_OS_TV)
#define SLS_HOST_WATCH (SLS_HOST_APPLE && TARGET_OS_WATCH)
#define SLS_HOST_MAC (SLS_HOST_APPLE && TARGET_OS_MAC && !(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH)) || (SLS_HOST_APPLE && TARGET_OS_MACCATALYST)
#if SLS_HOST_IOS || SLS_HOST_TV || SLS_HOST_WATCH
#define SLS_HAS_UIKIT 1
#else
#define SLS_HAS_UIKIT 0
#endif
#if SLS_HOST_IOS && !TARGET_OS_MACCATALYST
#define SLS_HAS_CORE_TELEPHONY 1
#else
#define SLS_HAS_CORE_TELEPHONY 0
#endif
#endif /* SLSSystemCapabilities_h */
//
// SLSUtils.h
// Pods
//
// Created by gordon on 2022/9/21.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SLSUtils : NSObject
+ (NSString *) getSdkVersion;
@end
NS_ASSUME_NONNULL_END
//
// TimeUtils.h
// AliyunLogProducer
//
// Created by gordon on 2021/6/8.
// Copyright © 2021 lichao. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AliyunLog.h"
NS_ASSUME_NONNULL_BEGIN
@interface TimeUtils : NSObject
+(void) startUpdateServerTime: (NSString *)endpoint project: (NSString *)project;
+(void) updateServerTime: (NSInteger) timeInMillis;
+(NSInteger) getTimeInMilliis;
+(void) fixTime: (AliyunLog *)log;
@end
NS_ASSUME_NONNULL_END
#ifndef LIBAOS_LOG_H
#define LIBAOS_LOG_H
#include <string.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef enum {
AOS_LOG_OFF = 1,
AOS_LOG_FATAL,
AOS_LOG_ERROR,
AOS_LOG_WARN,
AOS_LOG_INFO,
AOS_LOG_DEBUG,
AOS_LOG_TRACE,
AOS_LOG_ALL
} aos_log_level_e;
extern aos_log_level_e aos_log_level;
void aos_log_format(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...);
void aos_print_log_android(int level, char *log);
void aos_log_set_level(aos_log_level_e level);
#ifdef __ANDROID__
#define print_log(level, log) aos_print_log_android(level, log)
#else
#define print_log(level, log) puts(log)
#endif
#ifdef WIN32
#define __FL_NME__ (strchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define aos_fatal_log(format, ...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_error_log(format, ...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_warn_log(format, ...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_info_log(format, ...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_debug_log(format, ...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_trace_log(format, ...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#else
#define __FL_NME__ (strchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#define aos_fatal_log(format, args...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_error_log(format, args...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_warn_log(format, args...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_info_log(format, args...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_debug_log(format, args...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_trace_log(format, args...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#endif
#ifdef __cplusplus
}
#endif
#endif
#ifndef LIBLOG_DEFINE_H
#define LIBLOG_DEFINE_H
#ifdef WIN32
#define LOG_EXPORT _declspec(dllexport)
#else
#define LOG_EXPORT
#endif
#ifdef __cplusplus
# define LOG_CPP_START extern "C" {
# define LOG_CPP_END }
#else
# define LOG_CPP_START
# define LOG_CPP_END
#endif
typedef int log_status_t;
struct _post_log_result
{
int statusCode;
char * errorMessage;
char * requestID;
};
typedef struct _post_log_result post_log_result;
#endif
#ifndef SLS_HTTP_INTERFACE_H
#define SLS_HTTP_INTERFACE_H
#include "log_define.h"
#include "log_producer_config.h"
LOG_CPP_START
/**
* register http post function for sending logs
* @param f function ptr to send http post request
*/
__attribute__ ((visibility("default")))
void log_set_http_post_func(int (*f)(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response));
/**
* register get time function for get log time
* @param f function ptr to get time unix seconds, like time(NULL)
*/
__attribute__ ((visibility("default")))
void log_set_get_time_unix_func(unsigned int (*f)());
__attribute__ ((visibility("default")))
void log_set_http_header_inject_func(void (*f) (log_producer_config *config,
char **src_headers,
int src_count,
char **dest_headers,
int *dest_count)
);
__attribute__ ((visibility("default")))
void log_set_http_header_release_inject_func(void (*f) (log_producer_config *config,
char **dest_headers,
int dest_count)
);
LOG_CPP_END
#endif//SLS_HTTP_INTERFACE_H
#ifndef LOG_INNER_INCLUDE_H
#define LOG_INNER_INCLUDE_H
//操作系统头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#ifdef WIN32
#define inline __inline
#include <winsock2.h>
#include <sys/timeb.h>
#include <windows.h>
#include <process.h>
#include <assert.h>
typedef int socklen_t;
#elif defined(_VXWORKS)
#include <vxworks.h>
#include <netdb.h>
#include <string.h>
#include <ctype.h>
#include <types.h>
#include <sockLib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <hostLib.h>
#include <ticklib.h>
#include <drv/timer/ppcDecTimer.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <tipc/tipc.h>
#include <taskLib.h>
#include <selectLib.h>//for vx6
#include <ioLib.h>
#include <ioctl.h>
#else
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <assert.h>
#include <sys/time.h>
#include <stdint.h>
#endif
#if defined WIN32 || defined _VXWORKS
typedef unsigned char u_char;
typedef unsigned char u_int8;
typedef unsigned short u_int16;
typedef unsigned int u_int32;
typedef unsigned __int64 u_int64;
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef signed __int64 int64;
#elif defined __linux__
typedef unsigned char u_char;
typedef unsigned char u_int8;
typedef unsigned short u_int16;
typedef unsigned int u_int32;
typedef unsigned long long u_int64;
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef long long int64;
typedef int SOCKET;
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#define __in // 参数输入
#define __out // 参数输出
#define closesocket close
#define stricmp strcasecmp
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define Sleep(param) usleep(1000*(param))
#define strcpy_s(a, b, c) strcpy(a, c)
#define sprintf_s(a, b, c) sprintf(a, c)
#define strncpy_s(a, b, c, d) strncpy(a, c, d)
#define vsprintf_s(a, b, c, d) vsprintf(a, c, d)
#define _strdup strdup
#define _stricmp stricmp
#endif
#endif //LOG_INNER_INCLUDE_H
#ifndef LOG_MULTI_THREAD_UTIL_H
#define LOG_MULTI_THREAD_UTIL_H
#include "log_inner_include.h"
//不同操作系统资源相关的工具宏定义
#ifdef WIN32
//临界区资源
#define CRITICALSECTION LPCRITICAL_SECTION
#define INVALID_CRITSECT NULL
/**
********************************************************************
* 创建互斥锁
********************************************************************
*/
static inline CRITICALSECTION CreateCriticalSection()
{
CRITICALSECTION cs = (CRITICALSECTION)malloc(sizeof(RTL_CRITICAL_SECTION));
InitializeCriticalSection(cs);
return cs;
}
/**
********************************************************************
* 删除互斥锁
********************************************************************
*/
static inline void ReleaseCriticalSection(CRITICALSECTION cs) {
if (cs != INVALID_CRITSECT) {
DeleteCriticalSection(cs);
free(cs);
}
}
/// * @brief 加锁
#define CS_ENTER(cs) EnterCriticalSection(cs)
/// * @brief 解锁
#define CS_LEAVE(cs) LeaveCriticalSection(cs)
/// * @brief 互斥锁
#define MUTEX CRITICAL_SECTION
/// * @brief 加锁
#define MUTEX_LOCK(mutex) EnterCriticalSection(&mutex)
/// * @brief 解锁
#define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex)
/// * @brief 互斥锁初始化
#define MUTEX_INIT(mutex) InitializeCriticalSection(&mutex)
/// * @brief 互斥锁销毁
#define MUTEX_DESTROY(mutex) ReleaseCriticalSection(&mutex)
//信号量资源
/// * @brief 信号量
typedef HANDLE SEMA;
/// * @brief 等待信号量一定时间
#define SEMA_WAIT_TIME(sema, delay) WaitForSingleObject(sema, delay)
/// * @brief 一直阻塞地进行等待信号量
#define SEMA_WAIT(sema) WaitForSingleObject(sema, INFINITE)
/// * @brief 释放信号量
#define SEMA_POST(sema) ReleaseSemaphore(sema, 1, NULL)
/// * @brief 尝试获取一个信号量
#define SEMA_TRYWAIT(sema) WaitForSingleObject(sema, 0)
/// * @brief 销毁信号量
#define SEMA_DESTROY(sema) CloseHandle(sema)
/// * @brief 初始化信号量, 输入的为:信号量的最大值,初始信号量个数
#define SEMA_INIT(sema, initCount, maxCount) sema = CreateSemaphore(NULL, initCount, maxCount, NULL)
/// * @brief 初始一个带有名称的信号量,用于多进程交互
#define SEMA_INIT_NAME(sema, initCount, maxCount, semaName) sema = CreateSemaphore(NULL, initCount, maxCount, semaName)
/// * @brief 信号量等待超时
#define SEMA_WAIT_TIMEOUT WAIT_TIMEOUT
/// * @brief 等待到信号量
#define SEMA_WAIT_OK WAIT_OBJECT_0
//条件量
typedef struct windows_event{
HANDLE event;
}*COND;
//typedef PRTL_CONDITION_VARIABLE COND;
typedef int COND_WAIT_T;
#define COND_WAIT_OK 0
#define COND_WAIT_TIMEOUT ETIMEDOUT
#define INVALID_COND NULL
static inline COND CreateCond() {
COND cond = NULL;
if (!(cond = (COND)malloc(sizeof(struct windows_event))))
return cond;
if ((cond->event = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
free(cond);
return NULL;
}
return cond;
}
static inline void DeleteCond(COND cond) {
if (cond != INVALID_COND) {
CloseHandle(cond->event);
free(cond);
}
}
#define COND_SIGNAL(cond) COND_WAKE(cond)
static inline COND_WAIT_T COND_WAIT_TIME(COND cond, CRITICALSECTION cs, int32_t waitMs) {
if (cond == INVALID_COND)
{
return EINVAL;
}
DWORD ret;
DWORD startTime, endTime, totalWaitMs, remainMs;
int result = -1;
LeaveCriticalSection(cs);
ret = WaitForSingleObject((HANDLE)cond->event, waitMs);
if (ret == WAIT_TIMEOUT)
{
result = ETIMEDOUT;
}
else if (ret != WAIT_OBJECT_0)
{
result = EINVAL;
}
EnterCriticalSection(cs);
return result;
}
static inline COND_WAIT_T COND_WAKE(COND cond) {
if (cond == INVALID_COND)
{
return EINVAL;
}
if (!SetEvent((HANDLE)cond->event))
return EINVAL;
return 0;
}
typedef HANDLE THREAD;
static inline void Win32CreateThread(HANDLE* hpThread, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_opt_ __drv_aliasesMem LPVOID lpParameter) {
*hpThread = CreateThread(NULL, 0, lpStartAddress, lpParameter, 0, NULL);
}
#define THREAD_INIT(thread, func, param) Win32CreateThread(&thread, func, param)
#define THREAD_JOIN(thread) WaitForSingleObject(thread, INFINITE)
#define snprintf sprintf_s
#define ATOMICINT volatile long
#define ATOMICINT_INC(pAtopicInt) InterlockedIncrement(pAtopicInt)
#define ATOMICINT_DEC(pAtopicInt) InterlockedDecrement(pAtopicInt)
#define ATOMICINT_ADD(pAtopicInt, addVal) InterlockedAdd(pAtopicInt, addVal)
#define ATOMICINT_EXCHANGEADD(pAtopicInt, addVal) InterlockedExchangeAdd(pAtopicInt, addVal)
#define ATOMICINT_EXCHANGE(pAtopicInt, exchangeVal) InterlockedExchange(pAtopicInt, exchangeVal)
#define ATOMICINT_COMPAREEXCAHNGE(pAtopicInt, exchangeVal, cmpVal) InterlockedCompareExchange(pAtopicInt, exchangeVal, cmpVal)
#elif defined(_VXWORKS)
//临界区资源
typedef SEM_ID CRITICALSECTION;
#define INVALID_CRITSECT NULL
static inline CRITICALSECTION CreateCriticalSection(int spinCount = 0)
{
CRITICALSECTION cs = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
if (cs == NULL)
{
perror("vxworks create MUTUAL EXCLUSION SEMAPHORE failed\n");
}
return cs;
}
static inline void ReleaseCriticalSection(CRITICALSECTION & cs)
{
semDelete(cs);
cs = INVALID_CRITSECT;
}
#define CS_ENTER(cs) semTake(cs, WAIT_FOREVER)
#define CS_LEAVE(cs) semGive(cs)
#define MUTEX SEM_ID
#define MUTEX_LOCK(mutex) semTake(mutex, WAIT_FOREVER)
#define MUTEX_UNLOCK(mutex) semGive(mutex)
#define MUTEX_INIT(mutex) mutex = semBCreate(SEM_Q_FIFO,SEM_FULL)
#define MUTEX_DESTROY(mutex) semDelete(mutex)
//信号量资源
#define SEMA SEM_ID
#define SEMA_WAIT_TIME(sema,delay) semTake(sema, delay)
#define SEMA_WAIT(sema) semTake(sema, WAIT_FOREVER)
#define SEMA_POST(sema) semGive(sema)
#define SEMA_DESTROY(sema) semDelete(sema)
#define SEMA_INIT(sema, initCount, maxCount) sema = semCCreate(SEM_Q_FIFO,initCount)
#define SEMA_WAIT_TIMEOUT ERROR
//线程资源
#define THREADID int
#define SOCKET int
#define closesocket(s_) close(s_)
#define SOCKET_ERROR -1
#else
//临界区资源
typedef pthread_mutex_t* CRITICALSECTION;
#define INVALID_CRITSECT NULL
static inline CRITICALSECTION CreateCriticalSection() {
CRITICALSECTION cs = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
assert(cs != INVALID_CRITSECT);
pthread_mutex_init(cs, NULL);
return cs;
}
static inline void ReleaseCriticalSection(CRITICALSECTION cs) {
if (cs != INVALID_CRITSECT) {
pthread_mutex_destroy(cs);
free(cs);
}
}
#define CS_ENTER(cs) pthread_mutex_lock(cs)
#define CS_LEAVE(cs) pthread_mutex_unlock(cs)
typedef pthread_cond_t* COND;
typedef int COND_WAIT_T;
#define COND_WAIT_OK 0
#define COND_WAIT_TIMEOUT ETIMEDOUT
#define INVALID_COND NULL
static inline COND CreateCond() {
COND cond = (COND)malloc(sizeof(pthread_cond_t));
assert(cond != INVALID_CRITSECT);
pthread_cond_init(cond, NULL);
return cond;
}
static inline void DeleteCond(COND cond) {
if (cond != INVALID_COND) {
pthread_cond_destroy(cond);
free(cond);
}
}
#define COND_SIGNAL(cond) pthread_cond_signal(cond)
#define COND_SIGNAL_ALL(cond) pthread_cond_broadcast(cond)
static inline COND_WAIT_T COND_WAIT_TIME(COND cond, CRITICALSECTION cs, int32_t waitMs) {
struct timeval now;
struct timespec outTime;
gettimeofday(&now, NULL);
now.tv_usec += ((waitMs) % 1000) * 1000;
if (now.tv_usec > 1000000)
{
now.tv_usec -= 1000000;
++now.tv_sec;
}
outTime.tv_sec = now.tv_sec + (waitMs) / 1000;
outTime.tv_nsec = now.tv_usec * 1000;
return pthread_cond_timedwait(cond, cs, &outTime);
}
static inline int64_t GET_TIME_US() {
struct timeval now;
gettimeofday(&now, NULL);
return (int64_t)now.tv_sec * 1000000 + now.tv_usec;
}
#define MUTEX pthread_mutex_t
#define SEMA sem_t
#define MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex)
#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex)
#define MUTEX_INIT(mutex) pthread_mutex_init(&mutex,NULL)
#define MUTEX_DESTROY(mutex) pthread_mutex_destroy(&mutex)
// not supported in mac os
#ifdef __linux__
static inline int sema_wait_time_(sem_t* sema, unsigned int delayMs)
{
struct timespec ts;
struct timeval tv;
gettimeofday(&tv, NULL);
tv.tv_usec += (delayMs % 1000) * 1000;
tv.tv_sec += delayMs / 1000;
if (tv.tv_usec > 1000000) {
tv.tv_usec -= 1000000;
++tv.tv_sec;
}
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
return sem_timedwait(sema, &ts) == 0 ? 0 : ETIMEDOUT;
}
#define SEMA_WAIT_TIME(sema,delay) sema_wait_time_(&sema,delay)
#endif
#define SEMA_WAIT(sema) sem_wait(&sema)
#define SEMA_POST(sema) sem_post(&sema)
#define SEMA_TRYWAIT(sema) sem_trywait(&sema)
#define SEMA_DESTROY(sema) sem_destroy(&sema)
#define SEMA_INIT(sema, initCount, maxCount) sem_init(&sema,0,initCount)
#define SEMA_INIT_NAME(sema, initCount, maxCount, semaName) sema = sem_open(semaName, O_CREAT, 0, initCount)
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT ETIMEDOUT
#define SEMA_WAIT_TIMEOUT ETIMEDOUT
#define SEMA_WAIT_OK 0
typedef pthread_t THREAD;
#define THREAD_INIT(thread, func, param) pthread_create(&(thread), NULL, func, param)
#define THREAD_JOIN(thread) pthread_join(thread, NULL)
#define ATOMICINT volatile long
#define ATOMICINT_INC(pAtopicInt) __sync_add_and_fetch(pAtopicInt, 1)
#define ATOMICINT_DEC(pAtopicInt) __sync_add_and_fetch(pAtopicInt, -1)
#define ATOMICINT_ADD(pAtopicInt, addVal) __sync_add_and_fetch(pAtopicInt, addVal)
#define ATOMICINT_EXCHANGEADD(pAtopicInt, addVal) __sync_fetch_and_add(pAtopicInt, addVal)
#define ATOMICINT_EXCHANGE(pAtopicInt, exchangeVal) __sync_val_compare_and_swap(pAtopicInt, *pAtopicInt, exchangeVal)
#define ATOMICINT_COMPAREEXCAHNGE(pAtopicInt, exchangeVal, cmpVal) __sync_val_compare_and_swap(pAtopicInt, cmpVal, exchangeVal)
typedef struct _FILETIME
{
unsigned long dwLowDateTime;
unsigned long dwHighDateTime;
} FILETIME;
#endif //WIN32
#endif //LOG_MULTI_THREAD_UTIL_H
//
// Created by ZhangCheng on 20/11/2017.
//
#ifndef LOG_C_SDK_LOG_PRODUCER_CLIENT_H
#define LOG_C_SDK_LOG_PRODUCER_CLIENT_H
#include "log_define.h"
#include "log_producer_config.h"
LOG_CPP_START
/**
* log producer client
*/
typedef struct _log_producer_client
{
volatile int32_t valid_flag;
int32_t log_level;
void * private_data;
}log_producer_client;
typedef struct _log_producer log_producer;
/**
* init log producer environment
* @note should been called before create any log producer client
* @note no multi thread safe
* @return OK if success, others the error code
*/
LOG_EXPORT log_producer_result log_producer_env_init();
/**
* destroy log producer environment
* @note should been called after all log producer clients destroyed
* @note no multi thread safe
*/
LOG_EXPORT void log_producer_env_destroy();
/**
* create log producer with a producer config
* @param config log_producer_config
* @param send_done_function this function will be called when send done(can be ok or fail), set to NULL if you don't care about it
* @param user_param this param will send back in send_done_function
* @return producer client ptr, NULL if create fail
*/
LOG_EXPORT log_producer * create_log_producer(log_producer_config * config, on_log_producer_send_done_function send_done_function, void *user_param);
/**
* destroy log producer
* @param producer
* @note no multi thread safe
*/
LOG_EXPORT void destroy_log_producer(log_producer * producer);
/**
* get client from producer
* @param producer
* @param config_name useless now, set NULL
* @return the specific producer client, root client if config_name is NULL or no specific config,
*/
LOG_EXPORT log_producer_client * get_log_producer_client(log_producer * producer, const char * config_name);
/**
* force send data when network recover
* @param client
*/
LOG_EXPORT void log_producer_client_network_recover(log_producer_client * client);
/**
* add log to producer, this may return LOG_PRODUCER_DROP_ERROR if buffer is full.
* if you care about this log very much, retry when return LOG_PRODUCER_DROP_ERROR.
*
* @example log_producer_client_add_log(client, 4, "key_1", "value_1", "key_2", "value_2")
* @note log param ... must be const char * or char * with '\0' ended
* @note multi thread safe
* @param client
* @param kv_count key value count
* @param ... log params : key, value pairs, must be const char * or char *
* @return ok if success, LOG_PRODUCER_DROP_ERROR if buffer is full, LOG_PRODUCER_INVALID if client is destroyed.
*/
LOG_EXPORT log_producer_result log_producer_client_add_log(log_producer_client * client, int32_t kv_count, ...);
/**
* add log to producer, this may return LOG_PRODUCER_DROP_ERROR if buffer is full.
* if you care about this log very much, retry when return LOG_PRODUCER_DROP_ERROR.
*
* @param client
* @param pair_count key value pair count
* @note pair_count not kv_count
* @param keys the key array
* @param key_lens the key len array
* @param values the value array
* @param value_lens the value len array
* @param flush if this log info need to send right, 1 mean flush and 0 means NO
* @return ok if success, LOG_PRODUCER_DROP_ERROR if buffer is full, LOG_PRODUCER_INVALID if client is destroyed, LOG_PRODUCER_PERSISTENT_ERROR is save binlog failed.
*/
LOG_EXPORT log_producer_result log_producer_client_add_log_with_len(log_producer_client * client, int32_t pair_count, char ** keys, size_t * key_lens, char ** values, size_t * value_lens, int flush);
/**
* @note same with log_producer_client_add_log_with_len but use int32_t as length
* add log to producer, this may return LOG_PRODUCER_DROP_ERROR if buffer is full.
* if you care about this log very much, retry when return LOG_PRODUCER_DROP_ERROR.
*
* @param client
* @param pair_count key value pair count
* @note pair_count not kv_count
* @param keys the key array
* @param key_lens the key len array
* @param values the value array
* @param value_lens the value len array
* @param flush if this log info need to send right, 1 mean flush and 0 means NO
* @return ok if success, LOG_PRODUCER_DROP_ERROR if buffer is full, LOG_PRODUCER_INVALID if client is destroyed, LOG_PRODUCER_PERSISTENT_ERROR is save binlog failed.
*/
LOG_EXPORT log_producer_result log_producer_client_add_log_with_len_int32(log_producer_client * client, int32_t pair_count, char ** keys, int32_t * key_lens, char ** values, int32_t * value_lens, int flush);
/**
* @note same with log_producer_client_add_log_with_len_int32 but set time
* add log to producer, this may return LOG_PRODUCER_DROP_ERROR if buffer is full.
* if you care about this log very much, retry when return LOG_PRODUCER_DROP_ERROR.
*
* @param client
* @param pair_count key value pair count
* @note pair_count not kv_count
* @param keys the key array
* @param key_lens the key len array
* @param values the value array
* @param value_lens the value len array
* @param flush if this log info need to send right, 1 mean flush and 0 means NO
* @return ok if success, LOG_PRODUCER_DROP_ERROR if buffer is full, LOG_PRODUCER_INVALID if client is destroyed, LOG_PRODUCER_PERSISTENT_ERROR is save binlog failed.
*/
LOG_EXPORT log_producer_result log_producer_client_add_log_with_len_time_int32(log_producer_client * client, uint32_t time_sec, int32_t pair_count, char ** keys, int32_t * key_lens, char ** values, int32_t * value_lens, int flush);
/**
* add raw pb log buffer
* @param client
* @param logBuf
* @param logSize
* @param flush
* @return same as log_producer_client_add_log_with_len
*/
LOG_EXPORT log_producer_result log_producer_client_add_log_raw(log_producer_client * client,
char * logBuf,
size_t logSize,
int flush);
/**
* add raw log with string buffer
* @param client
* @param logTime
* @param logItemCount
* @param logItemsBuf
* @param logItemsSize
* @param flush
* @return same as log_producer_client_add_log_with_len
*/
LOG_EXPORT log_producer_result log_producer_client_add_log_with_array(log_producer_client * client,
uint32_t logTime,
size_t logItemCount,
const char * logItemsBuf,
const uint32_t * logItemsSize,
int flush);
/**
* add raw log buffer to client, this function is used to send buffers which can not send out when producer has destroyed
* @param client
* @param log_bytes
* @param compressed_bytes
* @param raw_buffer
* @return ok if success, LOG_PRODUCER_DROP_ERROR if buffer is full, LOG_PRODUCER_INVALID if client is destroyed, LOG_PRODUCER_PERSISTENT_ERROR is save binlog failed.
*/
LOG_EXPORT log_producer_result log_producer_client_add_raw_log_buffer(log_producer_client * client, size_t log_bytes, size_t compressed_bytes, const unsigned char * raw_buffer);
LOG_CPP_END
#endif //LOG_C_SDK_LOG_PRODUCER_CLIENT_H
//
// Created by ZhangCheng on 21/11/2017.
//
#ifndef LOG_C_SDK_LOG_PRODUCER_COMMON_H_H
#define LOG_C_SDK_LOG_PRODUCER_COMMON_H_H
#include "log_define.h"
#include <stdint.h>
#include <stddef.h>
LOG_CPP_START
/**
* log producer result for all operation
*/
typedef int log_producer_result;
/**
* callback function for producer client
* @param result send result
* @param log_bytes log group packaged bytes
* @param compressed_bytes lz4 compressed bytes
* @param error_message if send result is not ok, error message is set. must check if is NULL when use it
* @param raw_buffer lz4 buffer
* @note you can only read raw_buffer, but can't modify or free it
*/
typedef void(*on_log_producer_send_done_function)(const char * config_name, log_producer_result result, size_t log_bytes, size_t compressed_bytes, const char * req_id, const char * error_message, const unsigned char * raw_buffer, void *user_param);
typedef void(*on_log_producer_send_done_uuid_function)(const char * config_name,
log_producer_result result,
size_t log_bytes,
size_t compressed_bytes,
const char * req_id,
const char * error_message,
const unsigned char * raw_buffer,
void *user_param,
int64_t startId,
int64_t endId);
extern log_producer_result LOG_PRODUCER_OK;
extern log_producer_result LOG_PRODUCER_INVALID;
extern log_producer_result LOG_PRODUCER_WRITE_ERROR;
extern log_producer_result LOG_PRODUCER_DROP_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_NETWORK_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_QUOTA_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_UNAUTHORIZED;
extern log_producer_result LOG_PRODUCER_SEND_SERVER_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_DISCARD_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_TIME_ERROR;
extern log_producer_result LOG_PRODUCER_SEND_EXIT_BUFFERED;
extern log_producer_result LOG_PRODUCER_PARAMETERS_INVALID;
extern log_producer_result LOG_PRODUCER_PERSISTENT_ERROR;
/**
* check if rst if ok
* @param rst
* @return 1 if ok, 0 not ok
*/
LOG_EXPORT int is_log_producer_result_ok(log_producer_result rst);
LOG_CPP_END
#endif //LOG_C_SDK_LOG_PRODUCER_COMMON_H_H
//
// Created by ZhangCheng on 20/11/2017.
//
#ifndef LOG_C_SDK_LOG_PRODUCER_CONFIG_H
#define LOG_C_SDK_LOG_PRODUCER_CONFIG_H
#include "log_define.h"
#include "log_producer_common.h"
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include "log_multi_thread.h"
// change from 100ms to 1000s, reduce wake up when app switch to back
#define LOG_PRODUCER_FLUSH_INTERVAL_MS 1000
#define LOG_PRODUCER_QUEUE_POP_INTERVAL_MS 1000
LOG_CPP_START
typedef struct _log_producer_config_tag
{
char * key;
char * value;
}log_producer_config_tag;
typedef struct _log_producer_config
{
char * endpoint;
char * project;
char * logstore;
char * accessKeyId;
char * accessKey;
char * securityToken;
char * topic;
char * source;
CRITICALSECTION securityTokenLock;
log_producer_config_tag * tags;
int32_t tagAllocSize;
int32_t tagCount;
int32_t sendThreadCount;
int32_t packageTimeoutInMS;
int32_t logCountPerPackage;
int32_t logBytesPerPackage;
int32_t maxBufferBytes;
int32_t flushIntervalInMS;
int32_t logQueuePopIntervalInMS;
char * netInterface;
int32_t connectTimeoutSec;
int32_t sendTimeoutSec;
int32_t destroyFlusherWaitTimeoutSec;
int32_t destroySenderWaitTimeoutSec;
int32_t compressType; // 0 no compress, 1 lz4
int32_t ntpTimeOffset;
int using_https; // 0 http, 1 https
// for persistent feature
int32_t usePersistent; // 0 no, 1 yes
char * persistentFilePath;
int32_t maxPersistentLogCount;
int32_t maxPersistentFileSize; // max persistent size is maxPersistentFileSize * maxPersistentFileCount
int32_t maxPersistentFileCount; // max persistent size is maxPersistentFileSize * maxPersistentFileCount
int32_t forceFlushDisk; // force flush disk
// if log's time if before than nowTime, it's time will be rewrite to nowTime if delta > maxLogDelayTime
// the default value is 7*24*3600
int32_t maxLogDelayTime;
int32_t dropDelayLog; // 1 true, 0 false, default 1
int32_t dropUnauthorizedLog; // 1 true, 0 false, default 0
int32_t callbackFromSenderThread; // 1 true, 0 false, default 1int32_t callbackFromSenderThread;
int32_t webTracking; // 1 webtracking, default 0
int32_t mode; // 0, LoadBalance; 1, KeyShard
char *shardKey;
void *user_params; // user params pass to c
}log_producer_config;
/**
* create a empty producer config, should set config params manually
* @return empty producer config
*/
LOG_EXPORT log_producer_config * create_log_producer_config();
/**
* set producer config endpoint
* @note if endpoint start with "https", then set using_https 1
* @note strlen(endpoint) must >= 8
* @param config
* @param endpoint
*/
LOG_EXPORT void log_producer_config_set_endpoint(log_producer_config * config, const char * endpoint);
/**
* default http, 0 http, 1 https
* @param config
* @param using_https
*/
LOG_EXPORT void log_producer_config_set_using_http(log_producer_config * config, int32_t using_https);
/**
* set producer config project
* @param config
* @param project
*/
LOG_EXPORT void log_producer_config_set_project(log_producer_config * config, const char * project);
/**
* set producer config logstore
* @param config
* @param logstore
*/
LOG_EXPORT void log_producer_config_set_logstore(log_producer_config * config, const char * logstore);
/**
* set producer config access id
* @param config
* @param access_id
*/
LOG_EXPORT void log_producer_config_set_access_id(log_producer_config * config, const char * access_id);
/**
* set producer config access key
* @param config
* @param access_id
*/
LOG_EXPORT void log_producer_config_set_access_key(log_producer_config * config, const char * access_id);
/**
* reset producer config security token (thread safe)
* @note if you want to use security token to send logs, you must call this function when create config and reset token before expired.
* if token has expired, producer will drop logs after 6 hours
* @param config
* @param access_id
*/
LOG_EXPORT void log_producer_config_reset_security_token(log_producer_config * config, const char * access_id, const char * access_secret, const char * security_token);
/**
* inner api
*/
LOG_EXPORT void log_producer_config_get_security(log_producer_config * config, char ** access_id, char ** access_secret, char ** security_token);
/**
* set producer config topic
* @param config
* @param topic
*/
LOG_EXPORT void log_producer_config_set_topic(log_producer_config * config, const char * topic);
/**
* set producer source, this source will been set to every loggroup's "source" field
* @param config
* @param source
*/
LOG_EXPORT void log_producer_config_set_source(log_producer_config * config, const char * source);
/**
* add tag, this tag will been set to every loggroup's "tag" field
* @param config
* @param key
* @param value
*/
LOG_EXPORT void log_producer_config_add_tag(log_producer_config * config, const char * key, const char * value);
/**
* set loggroup timeout, if delta time from first log's time >= time_out_ms, current loggroup will been flushed out
* @param config
* @param time_out_ms
*/
LOG_EXPORT void log_producer_config_set_packet_timeout(log_producer_config * config, int32_t time_out_ms);
/**
* set loggroup max log count, if loggoup's logs count >= log_count, current loggroup will been flushed out
* @param config
* @param log_count
*/
LOG_EXPORT void log_producer_config_set_packet_log_count(log_producer_config * config, int32_t log_count);
/**
* set loggroup max log bytes, if loggoup's log bytes >= log_bytes, current loggroup will been flushed out
* @param config
* @param log_bytes
*/
LOG_EXPORT void log_producer_config_set_packet_log_bytes(log_producer_config * config, int32_t log_bytes);
/**
* set max buffer size, if total buffer size > max_buffer_bytes, all send will fail immediately
* @param config
* @param max_buffer_bytes
*/
LOG_EXPORT void log_producer_config_set_max_buffer_limit(log_producer_config * config, int64_t max_buffer_bytes);
/**
* set flush interval time in ms.
* @note interval time should > 30ms.
* @param config
* @param flush_interval_in_ms
*/
LOG_EXPORT void log_producer_config_set_flush_interval(log_producer_config * config, int32_t flush_interval_in_ms);
/**
* set log queue pop interval time in ms.
* @note interval time should > 30ms.
* @param config
* @param log_queue_in_ms
*/
LOG_EXPORT void log_producer_config_set_log_queue_interval(log_producer_config * config, int32_t log_queue_in_ms);
/**
* set send thread count, default is 0.
* @note if thread count is 0, flusher thread is in the charge of send logs.
* @note if thread count > 1, then producer will create $(thread_count) threads to send logs.
* @param config
* @param thread_count
*/
LOG_EXPORT void log_producer_config_set_send_thread_count(log_producer_config * config, int32_t thread_count);
/**
* set interface to send log out
* @param config
* @param net_interface
*/
LOG_EXPORT void log_producer_config_set_net_interface(log_producer_config * config, const char * net_interface);
/**
* set connect timeout seconds
* @param config
* @param connect_timeout_sec
*/
LOG_EXPORT void log_producer_config_set_connect_timeout_sec(log_producer_config * config, int32_t connect_timeout_sec);
/**
* set send timeout seconds
* @param config
* @param send_timeout_sec
*/
LOG_EXPORT void log_producer_config_set_send_timeout_sec(log_producer_config * config, int32_t send_timeout_sec);
/**
* set wait seconds when destroy flusher
* @param config
* @param destroy_flusher_wait_sec
*/
LOG_EXPORT void log_producer_config_set_destroy_flusher_wait_sec(log_producer_config * config, int32_t destroy_flusher_wait_sec);
/**
* set wait seconds when destroy sender
* @param config
* @param destroy_sender_wait_sec
*/
LOG_EXPORT void log_producer_config_set_destroy_sender_wait_sec(log_producer_config * config, int32_t destroy_sender_wait_sec);
/**
* set compress type, default 1 (lz4)
* @param config
* @param compress_type only support 1 or 0. 1 -> lz4, 0 -> no compress
*/
LOG_EXPORT void log_producer_config_set_compress_type(log_producer_config * config, int32_t compress_type);
/**
* set time offset between local time and server ntp time
* @param config
* @param ntp_time_diff
*/
LOG_EXPORT void log_producer_config_set_ntp_time_offset(log_producer_config * config, int32_t ntp_time_offset);
/**
* set persistent flag, 0 disable, 1 enable
* @param config
* @param persistent
*/
LOG_EXPORT void log_producer_config_set_persistent(log_producer_config * config, int32_t persistent);
/**
* set persistent file path
* @param config
* @param file_path full file path, eg : "/app/test/data.dat"
* @note the file dir must exist
*/
LOG_EXPORT void log_producer_config_set_persistent_file_path(log_producer_config * config, const char * file_path);
/**
* set max persistent file count, max size in disk is file_count * file_size
* @param config
* @param file_count 1-1000
*/
LOG_EXPORT void log_producer_config_set_persistent_max_file_count(log_producer_config * config, int32_t file_count);
/**
* set max persistent file size, max size in disk is file_count * file_size
* @param config
* @param file_size
*/
LOG_EXPORT void log_producer_config_set_persistent_max_file_size(log_producer_config * config, int32_t file_size);
/**
* force flush disk when add a log, 0 disable, 1 enable
* @param config
* @param force
*/
LOG_EXPORT void log_producer_config_set_persistent_force_flush(log_producer_config * config, int32_t force);
/**
* set max log count saved in disk
* @param config
* @param max_log_count
*/
LOG_EXPORT void log_producer_config_set_persistent_max_log_count(log_producer_config * config, int32_t max_log_count);
/**
* set max log delay time
* @param config
* @param max_log_delay_time
*/
LOG_EXPORT void log_producer_config_set_max_log_delay_time(log_producer_config * config, int32_t max_log_delay_time);
/**
* set drop delay log or not
* @param config
* @param drop_or_rewrite
*/
LOG_EXPORT void log_producer_config_set_drop_delay_log(log_producer_config * config, int32_t drop_or_rewrite);
/**
* set drop unauthorized log or not
* @param config
* @param drop_or_not
*/
LOG_EXPORT void log_producer_config_set_drop_unauthorized_log(log_producer_config * config, int32_t drop_or_not);
/**
* set callback thread. default from sender thread.
* @param config
* @param callback_from_sender_thread
*/
LOG_EXPORT void log_producer_config_set_callback_from_sender_thread(log_producer_config * config, int32_t callback_from_sender_thread);
LOG_EXPORT void log_producer_config_set_use_webtracking(log_producer_config * config, int32_t webtracking);
LOG_EXPORT void log_producer_config_set_mode(log_producer_config *config, int32_t mode);
LOG_EXPORT void log_producer_config_set_shardkey(log_producer_config *config, const char *shardKey);
/**
* destroy config, this will free all memory allocated by this config
* @param config
*/
LOG_EXPORT void destroy_log_producer_config(log_producer_config * config);
#ifdef LOG_PRODUCER_DEBUG
/**
* print this config
* @param config
*/
void log_producer_config_print(log_producer_config * config, FILE * pFile);
#endif
/**
* check if given config is valid
* @param config
* @return 1 valid, 0 invalid
*/
LOG_EXPORT int log_producer_config_is_valid(log_producer_config * config);
/**
*
* @return
*/
LOG_EXPORT int log_producer_persistent_config_is_enabled(log_producer_config * config);
LOG_CPP_END
#endif //LOG_C_SDK_LOG_PRODUCER_CONFIG_H
#include "inner_log.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
aos_log_level_e aos_log_level = AOS_LOG_WARN;
static const char * _aos_log_level_str[] = {
"NONE",
"NONE",
"FATAL",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE",
"NONE"
};
void aos_log_set_level(aos_log_level_e level)
{
aos_log_level = level;
}
void aos_log_format(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...)
{
va_list args;
char buffer[1024];
int maxLen = 1020;
// @note return value maybe < 0 || > maxLen
int len = snprintf(buffer, maxLen, "[%s] [%s][%s:%d] ",
_aos_log_level_str[level],
file, function, line);
// should never happen
if (len < 0 || len > maxLen) {
print_log(AOS_LOG_ERROR, "[aos_log_format] error log fmt\n");
return;
}
va_start(args, fmt);
// @note return value maybe < 0 || > maxLen
int rst = vsnprintf(buffer + len, maxLen - len, fmt, args);
va_end(args);
if (rst < 0) {
print_log(AOS_LOG_ERROR, "[aos_log_format] error log fmt\n");
return;
}
if (rst > maxLen - len) {
rst = maxLen - len;
}
len += rst;
while (len > 0 && buffer[len -1] == '\n')
{
len--;
}
buffer[len++] = '\n';
buffer[len] = '\0';
print_log(level, buffer);
}
\ No newline at end of file
#ifndef LIBAOS_LOG_H
#define LIBAOS_LOG_H
#include <string.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef enum {
AOS_LOG_OFF = 1,
AOS_LOG_FATAL,
AOS_LOG_ERROR,
AOS_LOG_WARN,
AOS_LOG_INFO,
AOS_LOG_DEBUG,
AOS_LOG_TRACE,
AOS_LOG_ALL
} aos_log_level_e;
extern aos_log_level_e aos_log_level;
void aos_log_format(int level,
const char *file,
int line,
const char *function,
const char *fmt, ...);
void aos_print_log_android(int level, char *log);
void aos_log_set_level(aos_log_level_e level);
#ifdef __ANDROID__
#define print_log(level, log) aos_print_log_android(level, log)
#else
#define print_log(level, log) puts(log)
#endif
#ifdef WIN32
#define __FL_NME__ (strchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define aos_fatal_log(format, ...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_error_log(format, ...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_warn_log(format, ...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_info_log(format, ...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_debug_log(format, ...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#define aos_trace_log(format, ...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FL_NME__, __LINE__, __FUNCTION__, format, __VA_ARGS__)
#else
#define __FL_NME__ (strchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#define aos_fatal_log(format, args...) if(aos_log_level>=AOS_LOG_FATAL) \
aos_log_format(AOS_LOG_FATAL, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_error_log(format, args...) if(aos_log_level>=AOS_LOG_ERROR) \
aos_log_format(AOS_LOG_ERROR, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_warn_log(format, args...) if(aos_log_level>=AOS_LOG_WARN) \
aos_log_format(AOS_LOG_WARN, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_info_log(format, args...) if(aos_log_level>=AOS_LOG_INFO) \
aos_log_format(AOS_LOG_INFO, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_debug_log(format, args...) if(aos_log_level>=AOS_LOG_DEBUG) \
aos_log_format(AOS_LOG_DEBUG, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#define aos_trace_log(format, args...) if(aos_log_level>=AOS_LOG_TRACE) \
aos_log_format(AOS_LOG_TRACE, __FL_NME__, __LINE__, __FUNCTION__, format, ## args)
#endif
#ifdef __cplusplus
}
#endif
#endif
#include "log_util.h"
#include "log_api.h"
#include <string.h>
#include "log_sds.h"
#include "inner_log.h"
int LOG_OS_HttpPost(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response);
unsigned int LOG_GET_TIME();
void log_http_inject_headers(log_producer_config *config, char **src_headers, int src_count, char **dest_headers, int *dest_count);
void log_http_release_inject_headers(log_producer_config *config, char **dest_headers, int dest_count);
log_status_t sls_log_init(int32_t log_global_flag)
{
#if 0
CURLcode ecode;
if ((ecode = curl_global_init(log_global_flag)) != CURLE_OK)
{
aos_error_log("curl_global_init failure, code:%d %s.\n", ecode, curl_easy_strerror(ecode));
return -1;
}
#endif
return 0;
}
void sls_log_destroy()
{
#if 0
curl_global_cleanup();
#endif
}
#if 0
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t totalLen = size * nmemb;
//printf("body ----> %d %s \n", (int) (totalLen, (const char*) ptr);
log_sds * buffer = (log_sds *)stream;
if (*buffer == NULL)
{
*buffer = log_sdsnewEmpty(256);
}
*buffer = log_sdscpylen(*buffer, ptr, totalLen);
return totalLen;
}
static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t totalLen = size * nmemb;
//printf("header ----> %d %s \n", (int) (totalLen), (const char*) ptr);
log_sds * buffer = (log_sds *)stream;
// only copy header start with x-log-
if (totalLen > 6 && memcmp(ptr, "x-log-", 6) == 0)
{
*buffer = log_sdscpylen(*buffer, ptr, totalLen);
}
return totalLen;
}
#endif
static const char sls_month_snames[12][4] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char sls_day_snames[7][4] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
void sls_rfc822_date(char *date_str, struct tm * xt)
{
const char *s = NULL;
int real_year = 2000;
/* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
/* 12345678901234567890123456789 */
s = &sls_day_snames[xt->tm_wday][0];
*date_str++ = *s++;
*date_str++ = *s++;
*date_str++ = *s++;
*date_str++ = ',';
*date_str++ = ' ';
*date_str++ = xt->tm_mday / 10 + '0';
*date_str++ = xt->tm_mday % 10 + '0';
*date_str++ = ' ';
s = &sls_month_snames[xt->tm_mon][0];
*date_str++ = *s++;
*date_str++ = *s++;
*date_str++ = *s++;
*date_str++ = ' ';
real_year = 1900 + xt->tm_year;
/* This routine isn't y10k ready. */
*date_str++ = real_year / 1000 + '0';
*date_str++ = real_year % 1000 / 100 + '0';
*date_str++ = real_year % 100 / 10 + '0';
*date_str++ = real_year % 10 + '0';
*date_str++ = ' ';
*date_str++ = xt->tm_hour / 10 + '0';
*date_str++ = xt->tm_hour % 10 + '0';
*date_str++ = ':';
*date_str++ = xt->tm_min / 10 + '0';
*date_str++ = xt->tm_min % 10 + '0';
*date_str++ = ':';
*date_str++ = xt->tm_sec / 10 + '0';
*date_str++ = xt->tm_sec % 10 + '0';
*date_str++ = ' ';
*date_str++ = 'G';
*date_str++ = 'M';
*date_str++ = 'T';
*date_str++ = 0;
return;
}
void get_now_time_str(char * buffer, int bufLen, int timeOffset)
{
time_t rawtime = LOG_GET_TIME();
struct tm timeinfo;
if (timeOffset != 0)
{
rawtime += timeOffset;
}
gmtime_r(&rawtime, &timeinfo);
sls_rfc822_date(buffer, &timeinfo);
}
void post_log_result_destroy(post_log_result * result)
{
if (result != NULL)
{
if (result->errorMessage != NULL)
{
log_sdsfree(result->errorMessage);
}
if (result->requestID != NULL)
{
log_sdsfree(result->requestID);
}
free(result);
}
}
#if 0
post_log_result * post_logs_from_lz4buf(const char *endpoint, const char * accesskeyId, const char *accessKey, const char *stsToken, const char *project, const char *logstore, lz4_log_buf * buffer, log_post_option * option)
{
post_log_result * result = (post_log_result *)malloc(sizeof(post_log_result));
memset(result, 0, sizeof(post_log_result));
CURL *curl = curl_easy_init();
if (curl != NULL)
{
// url
log_sds url = NULL;
if (option->using_https) {
url = log_sdsnew("https://");
} else {
url = log_sdsnew("http://");
}
url = log_sdscat(url, project);
url = log_sdscat(url, ".");
url = log_sdscat(url, endpoint);
url = log_sdscat(url, "/logstores/");
url = log_sdscat(url, logstore);
url = log_sdscat(url, "/shards/lb");
curl_easy_setopt(curl, CURLOPT_URL, url);
struct curl_slist *connect_to = NULL;
if (option->remote_address != NULL)
{
// example.com::192.168.1.5:
log_sds connect_to_item = log_sdsnew(project);
connect_to_item = log_sdscat(connect_to_item, ".");
connect_to_item = log_sdscat(connect_to_item, endpoint);
connect_to_item = log_sdscat(connect_to_item, "::");
connect_to_item = log_sdscat(connect_to_item, option->remote_address);
connect_to_item = log_sdscat(connect_to_item, ":");
connect_to = curl_slist_append(NULL, connect_to_item);
curl_easy_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
log_sdsfree(connect_to_item);
}
char nowTime[64];
get_now_time_str(nowTime, 64);
char md5Buf[33];
md5Buf[32] = '\0';
int lz4Flag = option == NULL || option->compress_type == 1;
md5_to_string((const char *)buffer->data, buffer->length, (char *)md5Buf);
//puts(md5Buf);
//puts(nowTime);
struct curl_slist* headers = NULL;
headers=curl_slist_append(headers, "Content-Type:application/x-protobuf");
headers=curl_slist_append(headers, "x-log-apiversion:0.6.0");
if (lz4Flag)
{
headers=curl_slist_append(headers, "x-log-compresstype:lz4");
}
if (stsToken != NULL)
{
log_sds tokenHeader = log_sdsnew("x-acs-security-token:");
tokenHeader = log_sdscat(tokenHeader, stsToken);
headers=curl_slist_append(headers, tokenHeader);
log_sdsfree(tokenHeader);
}
headers=curl_slist_append(headers, "x-log-signaturemethod:hmac-sha1");
log_sds headerTime = log_sdsnew("Date:");
headerTime = log_sdscat(headerTime, nowTime);
headers=curl_slist_append(headers, headerTime);
log_sds headerMD5 = log_sdsnew("Content-MD5:");
headerMD5 = log_sdscat(headerMD5, md5Buf);
headers=curl_slist_append(headers, headerMD5);
log_sds headerLen= log_sdsnewEmpty(64);
headerLen = log_sdscatprintf(headerLen, "Content-Length:%d", (int)buffer->length);
headers=curl_slist_append(headers, headerLen);
log_sds headerRawLen = log_sdsnewEmpty(64);
headerRawLen = log_sdscatprintf(headerRawLen, "x-log-bodyrawsize:%d", (int)buffer->raw_length);
headers=curl_slist_append(headers, headerRawLen);
log_sds headerHost = log_sdsnewEmpty(128);
headerHost = log_sdscatprintf(headerHost, "Host:%s.%s", project, endpoint);
headers=curl_slist_append(headers, headerHost);
char sha1Buf[65];
sha1Buf[64] = '\0';
log_sds sigContent = log_sdsnewEmpty(512);
if (lz4Flag)
{
if (stsToken == NULL)
{
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, (int)buffer->raw_length, logstore);
}
else
{
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore);
}
}
else
{
if (stsToken == NULL)
{
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, (int)buffer->raw_length, logstore);
}
else
{
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore);
}
}
//puts("#######################");
//puts(sigContent);
int destLen = signature_to_base64(sigContent, log_sdslen(sigContent), accessKey, strlen(accessKey), sha1Buf);
sha1Buf[destLen] = '\0';
//puts(sha1Buf);
log_sds headerSig = log_sdsnewEmpty(256);
headerSig = log_sdscatprintf(headerSig, "Authorization:LOG %s:%s", accesskeyId, sha1Buf);
//puts(headerSig);
headers=curl_slist_append(headers, headerSig);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)buffer->data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, buffer->length);
curl_easy_setopt(curl, CURLOPT_FILETIME, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "log-c-lite_0.1.0");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15);
if (option != NULL)
{
// interface
if (option->interface != NULL)
{
curl_easy_setopt(curl, CURLOPT_INTERFACE, option->interface);
}
if (option->operation_timeout > 0)
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT, option->operation_timeout);
}
if (option->connect_timeout > 0)
{
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, option->connect_timeout);
}
}
log_sds header = log_sdsnewEmpty(64);
log_sds body = NULL;
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
//curl_easy_setopt(curl,CURLOPT_VERBOSE,1); //打印调试信息
CURLcode res = curl_easy_perform(curl);
//printf("result : %s \n", curl_easy_strerror(res));
long http_code;
if (res == CURLE_OK)
{
if ((res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code)) != CURLE_OK)
{
printf("get info result : %s \n", curl_easy_strerror(res));
result->statusCode = -2;
} else {
result->statusCode = http_code;
}
}
else
{
if (body == NULL)
{
body = log_sdsnew(curl_easy_strerror(res));
}
else
{
body = log_sdscpy(body, curl_easy_strerror(res));
}
result->statusCode = -1 * (int)res;
}
// header and body 's pointer may be modified in callback (size > 256)
if (log_sdslen(header) > 0)
{
result->requestID = header;
}
else
{
log_sdsfree(header);
header = NULL;
}
// body will be NULL or a error string(net error or request error)
result->errorMessage = body;
curl_slist_free_all(headers); /* free the list again */
log_sdsfree(url);
log_sdsfree(headerTime);
log_sdsfree(headerMD5);
log_sdsfree(headerLen);
log_sdsfree(headerRawLen);
log_sdsfree(headerHost);
log_sdsfree(sigContent);
log_sdsfree(headerSig);
/* always cleanup */
curl_easy_cleanup(curl);
if (connect_to != NULL)
{
curl_slist_free_all(connect_to);
}
}
return result;
}
#else
struct cur_slist {
char *data;
struct cur_slist *next;
};
struct cur_slist * cur_slist_append(struct cur_slist *lst, const char *s)
{
struct cur_slist *t = (struct cur_slist *)malloc(sizeof(struct cur_slist));
t->data = strdup(s);
t->next = NULL;
if(lst == NULL)
return t;
struct cur_slist *orig = lst;
while(lst->next) {
lst = lst->next;
}
lst->next = t;
return orig;
}
void cur_slist_free_all(struct cur_slist *lst)
{
while(lst != NULL) {
struct cur_slist *n = lst->next;
free(lst->data);
free(lst);
lst = n;
}
}
static int is_str_empty(const char *str)
{
if (!str)
{
return 1;
}
if (strcmp(str, "") == 0) {
return 1;
}
return 0;
}
post_log_result * post_logs_from_lz4buf(const char *endpoint, const char * accesskeyId, const char *accessKey, const char *stsToken, const char *project, const char *logstore, lz4_log_buf * buffer, log_post_option * option)
{
return post_logs_from_lz4buf_with_config(NULL, endpoint, project, logstore, accesskeyId, accessKey, stsToken, buffer, option);
}
post_log_result * post_logs_from_lz4buf_with_config(log_producer_config *config, const char *endpoint, const char *project, const char *logstore, const char *accessKeyId, const char *accessKeySecret, const char *stsToken, lz4_log_buf *buffer, log_post_option *option)
{
aos_info_log("start post_logs_from_lz4buf.");
post_log_result * result = (post_log_result *)malloc(sizeof(post_log_result));
memset(result, 0, sizeof(post_log_result));
// pre-check parameters
if (is_str_empty(endpoint) || is_str_empty(project) || is_str_empty(logstore))
{
result->statusCode = 405;
result->requestID = log_sdsnewEmpty(64);
result->errorMessage = log_sdsnew("Invalid producer config destination params");
return result;
}
if (is_str_empty(accessKeyId) || is_str_empty(accessKeySecret))
{
result->statusCode = 405;
result->requestID = log_sdsnewEmpty(64);
result->errorMessage = log_sdsnew("Invalid producer config authority params");
return result;
}
{
// url
log_sds url = NULL;
if (option->using_https) {
url = log_sdsnew("https://");
} else {
url = log_sdsnew("http://");
}
url = log_sdscat(url, project);
url = log_sdscat(url, ".");
url = log_sdscat(url, endpoint);
url = log_sdscat(url, "/logstores/");
url = log_sdscat(url, logstore);
int shardkeyMode = option->mode == 1 && !is_str_empty(option->shardKey);
if (shardkeyMode) {
aos_info_log("key hash: %s", option->shardKey);
url = log_sdscat(url, "/shards/route?key=");
url = log_sdscat(url, option->shardKey);
} else {
url = log_sdscat(url, "/shards/lb");
}
// TODO: url
char nowTime[64];
get_now_time_str(nowTime, 64, option->ntp_time_offset);
char md5Buf[33];
md5Buf[32] = '\0';
int lz4Flag = option == NULL || option->compress_type == 1;
md5_to_string((const char *)buffer->data, buffer->length, (char *)md5Buf);
//puts(md5Buf);
//puts(nowTime);
struct cur_slist* headers = NULL;
headers=cur_slist_append(headers, "Content-Type:application/x-protobuf");
headers=cur_slist_append(headers, "x-log-apiversion:0.6.0");
if (lz4Flag)
{
headers=cur_slist_append(headers, "x-log-compresstype:lz4");
}
if (stsToken != NULL)
{
log_sds tokenHeader = log_sdsnew("x-acs-security-token:");
tokenHeader = log_sdscat(tokenHeader, stsToken);
headers=cur_slist_append(headers, tokenHeader);
log_sdsfree(tokenHeader);
}
headers=cur_slist_append(headers, "x-log-signaturemethod:hmac-sha1");
log_sds headerTime = log_sdsnew("Date:");
headerTime = log_sdscat(headerTime, nowTime);
headers=cur_slist_append(headers, headerTime);
log_sds headerMD5 = log_sdsnew("Content-MD5:");
headerMD5 = log_sdscat(headerMD5, md5Buf);
headers=cur_slist_append(headers, headerMD5);
log_sds headerLen= log_sdsnewEmpty(64);
headerLen = log_sdscatprintf(headerLen, "Content-Length:%d", (int)buffer->length);
headers=cur_slist_append(headers, headerLen);
log_sds headerRawLen = log_sdsnewEmpty(64);
headerRawLen = log_sdscatprintf(headerRawLen, "x-log-bodyrawsize:%d", (int)buffer->raw_length);
headers=cur_slist_append(headers, headerRawLen);
log_sds headerHost = log_sdsnewEmpty(128);
headerHost = log_sdscatprintf(headerHost, "Host:%s.%s", project, endpoint);
headers=cur_slist_append(headers, headerHost);
char sha1Buf[65];
sha1Buf[64] = '\0';
log_sds sigContent = log_sdsnewEmpty(512);
if (lz4Flag)
{
if (stsToken == NULL)
{
if (shardkeyMode) {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/route?key=%s",
md5Buf, nowTime, (int)buffer->raw_length, logstore, option->shardKey);
} else {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, (int)buffer->raw_length, logstore);
}
}
else
{
if (shardkeyMode) {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/route?key=%s",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore, option->shardKey);
} else {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-compresstype:lz4\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore);
}
}
}
else
{
if (stsToken == NULL)
{
if (shardkeyMode) {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/route?key=%s",
md5Buf, nowTime, (int)buffer->raw_length, logstore, option->shardKey);
} else {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, (int)buffer->raw_length, logstore);
}
}
else
{
if (shardkeyMode) {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/route?key=%s",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore, option->shardKey);
} else {
sigContent = log_sdscatprintf(sigContent,
"POST\n%s\napplication/x-protobuf\n%s\nx-acs-security-token:%s\nx-log-apiversion:0.6.0\nx-log-bodyrawsize:%d\nx-log-signaturemethod:hmac-sha1\n/logstores/%s/shards/lb",
md5Buf, nowTime, stsToken, (int)buffer->raw_length, logstore);
}
}
}
//puts("#######################");
//puts(sigContent);
int destLen = signature_to_base64(sigContent, log_sdslen(sigContent), accessKeySecret, strlen(accessKeySecret), sha1Buf);
sha1Buf[destLen] = '\0';
//puts(sha1Buf);
log_sds headerSig = log_sdsnewEmpty(256);
headerSig = log_sdscatprintf(headerSig, "Authorization:LOG %s:%s", accessKeyId, sha1Buf);
//puts(headerSig);
headers=cur_slist_append(headers, headerSig);
// TODO: headers
// curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// TODO: data
// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)buffer->data);
// curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, buffer->length);
const int max_header_count = 50;
char *header_array[max_header_count];
int header_count = 0;
struct cur_slist *h = headers;
while(h != NULL) {
header_array[header_count] = h->data;
header_count++;
h = h->next;
}
char *dest_header_array[max_header_count];
int *dest_count = (int *)malloc(sizeof(int));
memset(dest_count, 0, sizeof(int));
log_http_inject_headers(config, header_array, header_count, dest_header_array, dest_count);
char **final_header_array = (*dest_count) == 0 ? header_array : dest_header_array;
int final_header_count = (*dest_count) == 0 ? header_count : (*dest_count);
post_log_result *http_response = (post_log_result*)malloc(sizeof(post_log_result));
int res = LOG_OS_HttpPost(url, final_header_array, final_header_count, (const void *) buffer->data, buffer->length, http_response);
log_http_release_inject_headers(config, dest_header_array, *dest_count);
result->statusCode = res;
result->requestID = log_sdsnew(http_response->requestID);
log_sds error_message = log_sdsnew("status: ");
error_message = log_sdscatprintf(error_message, "%d, ", res);
error_message = log_sdscat(error_message, http_response->errorMessage);
result->errorMessage = error_message;
cur_slist_free_all(headers); /* free the list again */
log_sdsfree(url);
log_sdsfree(headerTime);
log_sdsfree(headerMD5);
log_sdsfree(headerLen);
log_sdsfree(headerRawLen);
log_sdsfree(headerHost);
log_sdsfree(sigContent);
log_sdsfree(headerSig);
free(http_response->requestID);
free(http_response->errorMessage);
free(http_response);
free(dest_count);
}
return result;
}
post_log_result * post_logs_from_lz4buf_webtracking(const char *endpoint, const char *project, const char *logstore, lz4_log_buf *buffer, log_post_option *option)
{
aos_info_log("post_logs_from_lz4buf_webtracking start.");
post_log_result * result = (post_log_result *)malloc(sizeof(post_log_result));
memset(result, 0, sizeof(post_log_result));
// pre-check parameters
if (is_str_empty(endpoint) || is_str_empty(project) || is_str_empty(logstore))
{
result->statusCode = 405;
result->requestID = log_sdsnewEmpty(64);
result->errorMessage = log_sdsnew("Invalid producer config destination params");
return result;
}
{
// url
log_sds url = NULL;
if (option->using_https) {
url = log_sdsnew("https://");
} else {
url = log_sdsnew("http://");
}
url = log_sdscat(url, project);
url = log_sdscat(url, ".");
url = log_sdscat(url, endpoint);
url = log_sdscat(url, "/logstores/");
url = log_sdscat(url, logstore);
url = log_sdscat(url, "/track");
char nowTime[64];
get_now_time_str(nowTime, 64, option->ntp_time_offset);
int lz4Flag = option->compress_type == 1;
struct cur_slist* headers = NULL;
headers=cur_slist_append(headers, "x-log-apiversion:0.6.0");
if (lz4Flag)
{
headers=cur_slist_append(headers, "x-log-compresstype:lz4");
}
log_sds headerRawLen = log_sdsnewEmpty(64);
headerRawLen = log_sdscatprintf(headerRawLen, "x-log-bodyrawsize:%d", (int)buffer->raw_length);
headers=cur_slist_append(headers, headerRawLen);
const int max_header_count = 50;
char *header_array[max_header_count];
int header_count = 0;
struct cur_slist *h = headers;
while(h != NULL) {
header_array[header_count] = h->data;
header_count++;
h = h->next;
}
aos_info_log("post_logs_from_lz4buf_webtracking, start LOG_OS_HttpPost.");
post_log_result *http_response = (post_log_result*)malloc(sizeof(post_log_result));
int res = LOG_OS_HttpPost(url, header_array, header_count,
(const void *) buffer->data, buffer->length, http_response);
aos_info_log("post_logs_from_lz4buf_webtracking, LOG_OS_HttpPost res: %d.", res);
result->statusCode = res;
result->requestID = log_sdsnew(http_response->requestID);
log_sds error_message = log_sdsnew("status: ");
error_message = log_sdscatprintf(error_message, "%d, ", res);
error_message = log_sdscat(error_message, http_response->errorMessage);
result->errorMessage = error_message;
cur_slist_free_all(headers); /* free the list again */
log_sdsfree(url);
log_sdsfree(headerRawLen);
}
return result;
}
#endif
#ifndef LIBLOG_API_H
#define LIBLOG_API_H
#include "log_define.h"
#include "log_producer_config.h"
#include "log_builder.h"
LOG_CPP_START
#ifdef WIN32
#undef interface
#endif // WIN32
struct _log_post_option
{
char * interface; // net interface to send log, NULL as default
int connect_timeout; // connection timeout seconds, 0 as default
int operation_timeout; // operation timeout seconds, 0 as default
int compress_type; // 0 no compress, 1 lz4
int ntp_time_offset; //time offset between local time and server time
int using_https; // 0 http, 1 https
int mode; // 0, LoadBalance; 1 KeyShard
char *shardKey;
};
typedef struct _log_post_option log_post_option;
log_status_t sls_log_init();
void sls_log_destroy();
post_log_result * post_logs_from_lz4buf(const char *endpoint, const char * accesskeyId, const char *accessKey, const char *stsToken, const char *project, const char *logstore, lz4_log_buf * buffer, log_post_option * option);
post_log_result * post_logs_from_lz4buf_with_config(log_producer_config *config, const char *endpoint, const char *project, const char *logstore, const char *accessKeyId, const char *accessKeySecret, const char *stsToken, lz4_log_buf *buffer, log_post_option *option);
post_log_result * post_logs_from_lz4buf_webtracking(const char *endpoint, const char *project, const char *logstore, lz4_log_buf *buffer, log_post_option *option);
void post_log_result_destroy(post_log_result * result);
LOG_CPP_END
#endif
#include "log_builder.h"
#include "log_lz4.h"
#include "log_sds.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "inner_log.h"
// 1+3( 1 ---> header; 2 ---> 128 * 128 = 16KB)
#define INIT_LOG_SIZE_BYTES 3
/**
* Return the number of bytes required to store a variable-length unsigned
* 32-bit integer in base-128 varint encoding.
*
* \param v
* Value to encode.
* \return
* Number of bytes required.
*/
static inline size_t uint32_size(uint32_t v)
{
if (v < (1UL << 7)) {
return 1;
} else if (v < (1UL << 14)) {
return 2;
} else if (v < (1UL << 21)) {
return 3;
} else if (v < (1UL << 28)) {
return 4;
} else {
return 5;
}
}
/**
* Pack an unsigned 32-bit integer in base-128 varint encoding and return the
* number of bytes written, which must be 5 or less.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t uint32_pack(uint32_t value, uint8_t *out)
{
unsigned rv = 0;
if (value >= 0x80) {
out[rv++] = value | 0x80;
value >>= 7;
if (value >= 0x80) {
out[rv++] = value | 0x80;
value >>= 7;
if (value >= 0x80) {
out[rv++] = value | 0x80;
value >>= 7;
if (value >= 0x80) {
out[rv++] = value | 0x80;
value >>= 7;
}
}
}
}
/* assert: value<128 */
out[rv++] = value;
return rv;
}
static inline uint32_t parse_uint32(unsigned len, const uint8_t *data)
{
uint32_t rv = data[0] & 0x7f;
if (len > 1) {
rv |= ((uint32_t) (data[1] & 0x7f) << 7);
if (len > 2) {
rv |= ((uint32_t) (data[2] & 0x7f) << 14);
if (len > 3) {
rv |= ((uint32_t) (data[3] & 0x7f) << 21);
if (len > 4)
rv |= ((uint32_t) (data[4]) << 28);
}
}
}
return rv;
}
static unsigned scan_varint(unsigned len, const uint8_t *data)
{
unsigned i;
if (len > 10)
len = 10;
for (i = 0; i < len; i++)
if ((data[i] & 0x80) == 0)
break;
if (i == len)
return 0;
return i + 1;
}
log_group_builder* log_group_create()
{
log_group_builder* bder = (log_group_builder*)malloc(sizeof(log_group_builder)+sizeof(log_group));
memset(bder, 0, sizeof(log_group_builder)+sizeof(log_group));
bder->grp = (log_group*)((char *)(bder) + sizeof(log_group_builder));
bder->loggroup_size = sizeof(log_group) + sizeof(log_group_builder);
bder->builder_time = time(NULL);
bder->start_uuid = -1;
bder->end_uuid = -1;
return bder;
}
void log_group_destroy(log_group_builder* bder)
{
// free tag
log_group* group = bder->grp;
if (group->tags.buffer != NULL)
{
free(group->tags.buffer);
}
// free log
if (group->logs.buffer != NULL)
{
free(group->logs.buffer);
}
if (group->topic != NULL)
{
log_sdsfree(group->topic);
}
if (group->source != NULL)
{
log_sdsfree(group->source);
}
// free self
free(bder);
}
/**
* adjust buffer, this function will ensure tag's buffer size >= tag->now_buffer_len + new_len
* @param tag
* @param new_len new buffer len
*/
void _adjust_buffer(log_tag * tag, uint32_t new_len)
{
if (tag->buffer == NULL)
{
tag->buffer = (char *)malloc(new_len << 2);
tag->max_buffer_len = new_len << 2;
tag->now_buffer = tag->buffer;
tag->now_buffer_len = 0;
return;
}
uint32_t new_buffer_len = tag->max_buffer_len << 1;
if (new_buffer_len < tag->now_buffer_len + new_len)
{
new_buffer_len = tag->now_buffer_len + new_len;
}
tag->buffer = (char *)realloc(tag->buffer, new_buffer_len);
tag->now_buffer = tag->buffer + tag->now_buffer_len;
tag->max_buffer_len = new_buffer_len;
}
void add_log_raw(log_group_builder *bder, const char *buffer, size_t size)
{
++bder->grp->n_logs;
log_tag * log = &(bder->grp->logs);
if (log->now_buffer == NULL || log->max_buffer_len < log->now_buffer_len + size)
{
_adjust_buffer(log, size);
}
memcpy(log->now_buffer, buffer, size);
bder->loggroup_size += size;
log->now_buffer_len += size;
log->now_buffer += size;
}
void add_log_full(log_group_builder* bder, uint32_t logTime, int32_t pair_count, char ** keys, size_t * key_lens, char ** values, size_t * val_lens)
{
++bder->grp->n_logs;
// limit logTime's min value, ensure varint size is 5
if (logTime < 1263563523)
{
logTime = 1263563523;
}
int32_t i = 0;
int32_t logSize = 6;
for (; i < pair_count; ++i)
{
uint32_t contSize = uint32_size(key_lens[i]) + uint32_size(val_lens[i]) + key_lens[i] + val_lens[i] + 2;
logSize += 1 + uint32_size(contSize) + contSize;
}
int32_t totalBufferSize = logSize + 1 + uint32_size(logSize);
log_tag * log = &(bder->grp->logs);
if (log->now_buffer == NULL || log->max_buffer_len < log->now_buffer_len + totalBufferSize)
{
_adjust_buffer(log, totalBufferSize);
}
bder->loggroup_size += totalBufferSize;
uint8_t * buf = (uint8_t*)log->now_buffer;
*buf++ = 0x0A;
buf += uint32_pack(logSize, buf);
// time
*buf++=0x08;
buf += uint32_pack(logTime, buf);
// Content
// header
i = 0;
for (; i < pair_count; ++i)
{
*buf++ = 0x12;
buf += uint32_pack(uint32_size(key_lens[i]) + uint32_size(val_lens[i]) + 2 + key_lens[i] + val_lens[i], buf);
*buf++ = 0x0A;
buf += uint32_pack(key_lens[i], buf);
memcpy(buf, keys[i], key_lens[i]);
buf += key_lens[i];
*buf++ = 0x12;
buf += uint32_pack(val_lens[i], buf);
memcpy(buf, values[i], val_lens[i]);
buf += val_lens[i];
}
assert(buf - (uint8_t*)log->now_buffer == totalBufferSize);
log->now_buffer_len += totalBufferSize;
log->now_buffer = (char *)buf;
}
void add_source(log_group_builder* bder,const char* src,size_t len)
{
bder->loggroup_size += sizeof(char)*(len) + uint32_size((uint32_t)len) + 1;
bder->grp->source = log_sdsnewlen(src, len);
}
void add_topic(log_group_builder* bder,const char* tpc,size_t len)
{
bder->loggroup_size += sizeof(char)*(len) + uint32_size((uint32_t)len) + 1;
bder->grp->topic = log_sdsnewlen(tpc, len);
}
void add_pack_id(log_group_builder* bder, const char* pack, size_t pack_len, size_t packNum)
{
char packStr[128];
packStr[127] = '\0';
snprintf(packStr, 127, "%s-%X", pack, (unsigned int)packNum);
add_tag(bder, "__pack_id__", strlen("__pack_id__"), packStr, strlen(packStr));
}
void add_tag(log_group_builder* bder, const char* k, size_t k_len, const char* v, size_t v_len)
{
// use only 1 malloc
uint32_t tag_size = sizeof(char) * (k_len + v_len) + uint32_size((uint32_t)k_len) + uint32_size((uint32_t)v_len) + 2;
uint32_t n_buffer = 1 + uint32_size(tag_size) + tag_size;
log_tag * tag = &(bder->grp->tags);
if (tag->now_buffer == NULL || tag->now_buffer_len + n_buffer > tag->max_buffer_len)
{
_adjust_buffer(tag, n_buffer);
}
uint8_t * buf = (uint8_t *)tag->now_buffer;
*buf++ = 0x32;
buf += uint32_pack(tag_size, buf);
*buf++ = 0x0A;
buf += uint32_pack((uint32_t)k_len, buf);
memcpy(buf, k, k_len);
buf += k_len;
*buf++ = 0x12;
buf += uint32_pack((uint32_t)v_len, buf);
memcpy(buf, v, v_len);
buf += v_len;
assert((uint8_t *)tag->now_buffer + n_buffer == buf);
tag->now_buffer = (char *)buf;
tag->now_buffer_len += n_buffer;
bder->loggroup_size += n_buffer;
}
static uint32_t _log_pack(log_group * grp, uint8_t * buf)
{
uint8_t * start_buf = buf;
if (grp->logs.buffer != NULL)
{
buf += grp->logs.now_buffer_len;
}
else
{
return 0;
}
if (grp->topic != NULL)
{
*buf++ = 0x1A;
buf+= uint32_pack((uint32_t)log_sdslen(grp->topic), buf);
memcpy(buf, grp->topic, log_sdslen(grp->topic));
buf += log_sdslen(grp->topic);
}
if (grp->source != NULL)
{
*buf++ = 0x22;
buf+= uint32_pack((uint32_t)log_sdslen(grp->source), buf);
memcpy(buf, grp->source, log_sdslen(grp->source));
buf += log_sdslen(grp->source);
}
if (grp->tags.buffer != NULL)
{
memcpy(buf, grp->tags.buffer, grp->tags.now_buffer_len);
buf += grp->tags.now_buffer_len;
}
return buf - start_buf;
}
void fix_log_group_time(char * pb_buffer, size_t len, uint32_t new_time)
{
if (len == 0 || pb_buffer == NULL || new_time < 1263563523)
{
return;
}
if (pb_buffer[0] != 0x0A)
{
return;
}
uint8_t * buf = (uint8_t *)pb_buffer;
uint8_t * startBuf = (uint8_t *)pb_buffer;
while (buf - startBuf < len && *buf == 0x0A)
{
++buf;
unsigned logSizeLen = scan_varint(5, buf);
uint32_t logSize = parse_uint32(logSizeLen, buf);
buf += logSizeLen;
// time
if (*buf == 0x08)
{
uint32_pack(new_time, buf + 1);
}
buf += logSize;
}
}
log_sds put_val(log_sds s, char* val)
{
s = log_sdscat(s, "\"");
s = log_sdscat(s, val);
s = log_sdscat(s, "\"");
return s;
}
log_sds put_kv_with_comma(log_sds s, char *key, char *val, int comma)
{
s = put_val(s, key);
s = log_sdscat(s, ":");
s = put_val(s, val);
if (comma)
{
s = log_sdscat(s, ",");
}
return s;
}
log_sds escape_json(char **value) {
size_t len = strlen(*value);
log_sds result = log_sdsnewEmpty(len);
for (int i = 0; i < len; i ++) {
switch ((*value)[i]) {
case '"': result = log_sdscat(result, "\\\""); break;
case '\\': result = log_sdscat(result, "\\\\"); break;
case '\b': result = log_sdscat(result, "\\b"); break;
case '\f': result = log_sdscat(result, "\\f"); break;
case '\n': result = log_sdscat(result, "\\n"); break;
case '\r': result = log_sdscat(result, "\\r"); break;
case '\t': result = log_sdscat(result, "\\t"); break;
default:
if ('\x00' <= (*value)[i] && (*value)[i] <= '\x1f') {
result = log_sdscatprintf(result, "%s%04X","\\u", (int)(*value)[i]);
} else {
result = log_sdscatchar(result, (*value)[i]);
}
}
}
return result;
}
log_sds put_kv(log_sds s, char *key, char *val)
{
log_sds v = escape_json(&val);
s = put_kv_with_comma(s, key, v, 1);
log_sdsfree(v);
return s;
}
log_sds put_kv_no_comma(log_sds s, char *key, char *val)
{
return put_kv_with_comma(s, key, val, 0);
}
log_sds put_array(log_sds s, char *key, log_sds array)
{
s = put_val(s, key);
s = log_sdscat(s, ":");
s = log_sdscat(s, array);
return s;
}
log_sds remove_comma(log_sds s) {
log_sds ns = log_sdsnewlen(s, log_sdslen(s) - 1);
log_sdsfree(s);
return ns;
}
unsigned int read_length_from_pb(const uint8_t *data)
{
return scan_varint(5, data);
}
uint32_t read_chars_from_pb(uint8_t **data, char **chars)
{
(*data) ++;
unsigned int len = read_length_from_pb(*data);
uint32_t _len = parse_uint32(len, *data);
(*data) += len;
*chars = (char *) malloc(sizeof (char) * (_len + 1) );
memset(*chars, 0, _len + 1);
memcpy(*chars, *data, _len + 1);
(*chars)[_len] = '\0';
(*data) += _len;
return _len;
}
extern size_t serialize_pb_buffer_to_webtracking(char *pb_buffer, size_t len, char **new_buffer)
{
if (0 == len || NULL == pb_buffer)
{
return 0;
}
if (0x0A != pb_buffer[0])
{
return 0;
}
log_sds root = log_sdsnew("{");
log_sds _root_logs_ = log_sdsnew("[");
log_sds _root_tags_ = log_sdsnew("{");
uint8_t * buf = (uint8_t *)pb_buffer;
uint8_t * startBuf = (uint8_t *)pb_buffer;
// log package
while (buf - startBuf < len && *buf == 0x0A)
{
aos_info_log("serialize_pb_buffer_to_webtracking, start process single log.");
++buf;
unsigned logSizeLen = read_length_from_pb(buf);
buf += logSizeLen;
uint32_t time = 0;
// time
if (*buf == 0x08)
{
buf++;
unsigned timeLen = read_length_from_pb(buf);
if (timeLen != 5)
{
return 0;
}
time = parse_uint32(timeLen, buf);
buf += timeLen;
aos_info_log("serialize_pb_buffer_to_webtracking, time: %d", time);
}
log_sds _log_ = log_sdsnew("{");
if (time)
{
_log_ = log_sdscatprintf(_log_, "\"__time__\":%u,", time);
}
// Content
// Header
while (*buf == 0x12)
{
buf++;
unsigned kvLen = read_length_from_pb(buf);
buf += kvLen;
char *key = NULL;
char *val = NULL;
// key
if (*buf == 0x0A)
{
read_chars_from_pb(&buf, &key);
}
// value
if (*buf == 0x12)
{
read_chars_from_pb(&buf, &val);
}
if (key && val)
{
_log_ = put_kv(_log_, key, val);
}
aos_info_log("serialize_pb_buffer_to_webtracking, content {%s: %s}", key, val);
free(key);
free(val);
}
if (log_sdslen(_log_) > 1)
{
// remove last ','
_log_ = remove_comma(_log_);
}
_log_ = log_sdscat(_log_, "}");
_root_logs_ = log_sdscat(_root_logs_, _log_);
_root_logs_ = log_sdscat(_root_logs_, ",");
log_sdsfree(_log_);
// Topic
if (0x1A == *buf)
{
char *topic;
read_chars_from_pb(&buf, &topic);
aos_info_log("serialize_pb_buffer_to_webtracking, topic: %s", topic);
root = put_kv(root, "__topic__", topic);
free(topic);
}
// Source
if (0x22 == *buf)
{
char *source;
read_chars_from_pb(&buf, &source);
aos_info_log("serialize_pb_buffer_to_webtracking, source: %s", source);
root = put_kv(root, "__source__", source);
free(source);
}
// Tag
while (0x32 == *buf)
{
buf ++;
unsigned int tagLen = read_length_from_pb(buf);
buf += tagLen;
char *key = NULL;
char *val = NULL;
// key
if (*buf == 0x0A)
{
read_chars_from_pb(&buf, &key);
}
// value
if (*buf == 0x12)
{
read_chars_from_pb(&buf, &val);
}
if (key && val)
{
_root_tags_ = put_kv(_root_tags_, key, val);
}
aos_info_log("serialize_pb_buffer_to_webtracking, tag {%s: %s}", key, val);
free(key);
free(val);
}
}
aos_info_log("serialize_pb_buffer_to_webtracking, log package has been processed.");
if (log_sdslen(_root_logs_) > 1)
{
_root_logs_ = remove_comma(_root_logs_);
}
_root_logs_ = log_sdscat(_root_logs_, "]");
_root_logs_ = log_sdscat(_root_logs_, ",");
root = put_array(root, "__logs__", _root_logs_);
if (log_sdslen(_root_tags_) > 1)
{
_root_tags_ = remove_comma(_root_tags_);
}
_root_tags_ = log_sdscat(_root_tags_, "}");
root = put_array(root, "__tags__", _root_tags_);
root = log_sdscat(root, "}");
size_t root_len = log_sdslen(root);
*new_buffer = (char *)malloc(sizeof(char) * root_len);
memcpy(*new_buffer, root, root_len);
log_sdsfree(_root_logs_);
log_sdsfree(_root_tags_);
log_sdsfree(root);
aos_info_log("serialize_pb_buffer_to_webtracking, json: %s", *new_buffer);
return root_len;
}
void fix_log_time(char * pb_buffer, size_t len, uint32_t new_time)
{
if (len == 0 || pb_buffer == NULL || new_time < 1263563523)
{
return;
}
if (pb_buffer[0] != 0x0A)
{
return;
}
++pb_buffer;
uint8_t * buf = (uint8_t *)pb_buffer;
unsigned logSizeLen = scan_varint(5, buf);
buf += logSizeLen;
// time
if (*buf == 0x08)
{
unsigned timeLen = scan_varint(5, buf + 1);
if (timeLen != 5)
{
return;
}
uint32_pack(new_time, buf + 1);
}
}
uint32_t get_log_time(const char * pb_buffer, size_t len)
{
if (len == 0 || pb_buffer == NULL)
{
return time(NULL);
}
if (pb_buffer[0] != 0x0A)
{
return time(NULL);
}
++pb_buffer;
uint8_t * buf = (uint8_t *)pb_buffer;
unsigned logSizeLen = scan_varint(5, buf);
buf += logSizeLen;
// time
if (*buf == 0x08)
{
unsigned timeLen = scan_varint(5, buf + 1);
return parse_uint32(timeLen, buf + 1);
}
return time(NULL);
}
log_buf serialize_to_proto_buf_with_malloc(log_group_builder* bder)
{
log_buf buf;
buf.buffer = NULL;
buf.n_buffer = 0;
log_tag * log = &(bder->grp->logs);
if (log->buffer == NULL)
{
return buf;
}
if (log->max_buffer_len < bder->loggroup_size)
{
_adjust_buffer(log, bder->loggroup_size - log->now_buffer_len);
}
buf.n_buffer = _log_pack(bder->grp, (uint8_t *)log->buffer);
buf.buffer = log->buffer;
return buf;
}
lz4_log_buf* serialize_to_proto_buf_with_malloc_no_lz4(log_group_builder* bder)
{
log_buf buf = serialize_to_proto_buf_with_malloc(bder);
lz4_log_buf* pLogbuf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + buf.n_buffer);
pLogbuf->length = buf.n_buffer;
pLogbuf->raw_length = buf.n_buffer;
memcpy(pLogbuf->data, buf.buffer, buf.n_buffer);
return pLogbuf;
}
lz4_log_buf* serialize_to_proto_buf_with_malloc_lz4(log_group_builder* bder)
{
log_tag * log = &(bder->grp->logs);
if (log->buffer == NULL)
{
return NULL;
}
if (log->max_buffer_len < bder->loggroup_size)
{
_adjust_buffer(log, bder->loggroup_size - log->now_buffer_len);
}
size_t length = _log_pack(bder->grp, (uint8_t *)log->buffer);
// @debug
//FILE * pFile = fopen("dump.dat", "wb+");
//fwrite(log->buffer, 1, length, pFile);
//fclose(pFile);
// @debug end
int compress_bound = LOG_LZ4_compressBound(length);
char *compress_data = (char *)malloc(compress_bound);
int compressed_size = LOG_LZ4_compress_default((char *)log->buffer, compress_data, length, compress_bound);
if(compressed_size <= 0)
{
free(compress_data);
return NULL;
}
lz4_log_buf* pLogbuf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + compressed_size);
pLogbuf->length = compressed_size;
pLogbuf->raw_length = length;
memcpy(pLogbuf->data, compress_data, compressed_size);
free(compress_data);
return pLogbuf;
}
void free_lz4_log_buf(lz4_log_buf* pBuf)
{
free(pBuf);
}
#ifdef LOG_KEY_VALUE_FLAG
void add_log_begin(log_group_builder * bder)
{
log_tag * logs = &bder->grp->logs;
if (logs->buffer == NULL || logs->now_buffer_len + INIT_LOG_SIZE_BYTES > logs->max_buffer_len)
{
_adjust_buffer(logs, INIT_LOG_SIZE_BYTES);
}
bder->grp->log_now_buffer = logs->now_buffer + INIT_LOG_SIZE_BYTES;
}
void add_log_time(log_group_builder * bder, uint32_t logTime)
{
log_tag * logs = &bder->grp->logs;
// 1 header and 5 time
if (bder->grp->log_now_buffer - logs->buffer + 6 > logs->max_buffer_len)
{
// reset log_now_buffer
size_t delta = bder->grp->log_now_buffer - logs->buffer;
_adjust_buffer(logs, delta + 6);
bder->grp->log_now_buffer = logs->buffer + delta;
}
uint8_t * buf = (uint8_t *)bder->grp->log_now_buffer;
// time
*buf++=0x08;
buf += uint32_pack(logTime, buf);
bder->grp->log_now_buffer = (char *)buf;
}
void add_log_key_value(log_group_builder *bder, const char * key, size_t key_len, const char * value, size_t value_len)
{
// sum total size
uint32_t kv_size = sizeof(char) * (key_len + value_len) + uint32_size((uint32_t)key_len) + uint32_size((uint32_t)value_len) + 2;
kv_size += 1 + uint32_size(kv_size);
log_tag * logs = &bder->grp->logs;
// ensure buffer size
if (bder->grp->log_now_buffer - logs->buffer + kv_size > logs->max_buffer_len )
{
// reset log_now_buffer
size_t delta = bder->grp->log_now_buffer - logs->buffer;
_adjust_buffer(logs, delta + kv_size);
bder->grp->log_now_buffer = logs->buffer + delta;
}
uint8_t * buf = (uint8_t *)bder->grp->log_now_buffer;
// key_value header
*buf++ = 0x12;
buf += uint32_pack(uint32_size(key_len) + uint32_size(value_len) + 2 + key_len + value_len, buf);
// key len
*buf++ = 0x0A;
buf += uint32_pack(key_len, buf);
// key
memcpy(buf, key, key_len);
buf += key_len;
// value len
*buf++ = 0x12;
buf += uint32_pack(value_len, buf);
// value
memcpy(buf, value, value_len);
buf += value_len;
bder->grp->log_now_buffer = (char *)buf;
}
void add_log_end(log_group_builder * bder)
{
log_tag * logs = &bder->grp->logs;
uint32_t log_size = bder->grp->log_now_buffer - logs->now_buffer - INIT_LOG_SIZE_BYTES;
// check total size and uint32_size(total size)
int32_t header_size = uint32_size(log_size) + 1;
if (header_size != INIT_LOG_SIZE_BYTES)
{
int32_t delta_header_size = header_size - (int32_t)INIT_LOG_SIZE_BYTES;
// need check buffer size
if (delta_header_size > 0 && bder->grp->log_now_buffer - logs->buffer + delta_header_size > logs->max_buffer_len)
{
// reset log_now_buffer
size_t delta = bder->grp->log_now_buffer - logs->buffer;
_adjust_buffer(logs, delta + delta_header_size);
bder->grp->log_now_buffer = logs->buffer + delta;
}
// move buffer
memmove(logs->now_buffer + header_size, logs->now_buffer + INIT_LOG_SIZE_BYTES, log_size);
}
// set log header
uint8_t * buf = (uint8_t *)logs->now_buffer;
*buf++ = 0x0A;
buf += uint32_pack(log_size, buf);
// do not need to add header_size
logs->now_buffer = (char *)buf + log_size;
logs->now_buffer_len += header_size + log_size;
// update loggroup size
bder->loggroup_size += header_size + log_size;
}
void clear_log_tag(log_tag *tag)
{
tag->now_buffer = tag->buffer;
tag->now_buffer_len = 0;
}
void
add_log_full_v2(log_group_builder *bder, uint32_t logTime, size_t logItemCount,
const char *logItemsBuf, const uint32_t *logItemsSize)
{
if (logTime < 1263563523)
{
logTime = time(NULL);
}
add_log_begin(bder);
add_log_time(bder, logTime);
size_t startOffset = 0;
logItemCount = (logItemCount >> 1) << 1;
for (size_t (i) = 0; (i) < logItemCount; i += 2)
{
uint32_t keySize = logItemsSize[i];
uint32_t valSize = logItemsSize[i+1];
add_log_key_value(bder, logItemsBuf + startOffset, keySize, logItemsBuf + startOffset + keySize, valSize);
startOffset += keySize + valSize;
}
add_log_end(bder);
}
void add_log_full_int32(log_group_builder *bder, uint32_t logTime,
int32_t pair_count, char **keys, int32_t *key_lens,
char **values, int32_t *val_lens)
{
++bder->grp->n_logs;
// limit logTime's min value, ensure varint size is 5
if (logTime < 1263563523)
{
logTime = 1263563523;
}
int32_t i = 0;
int32_t logSize = 6;
for (; i < pair_count; ++i)
{
uint32_t contSize = uint32_size(key_lens[i]) + uint32_size(val_lens[i]) + key_lens[i] + val_lens[i] + 2;
logSize += 1 + uint32_size(contSize) + contSize;
}
int32_t totalBufferSize = logSize + 1 + uint32_size(logSize);
log_tag * log = &(bder->grp->logs);
if (log->now_buffer == NULL || log->max_buffer_len < log->now_buffer_len + totalBufferSize)
{
_adjust_buffer(log, totalBufferSize);
}
bder->loggroup_size += totalBufferSize;
uint8_t * buf = (uint8_t*)log->now_buffer;
*buf++ = 0x0A;
buf += uint32_pack(logSize, buf);
// time
*buf++=0x08;
buf += uint32_pack(logTime, buf);
// Content
// header
i = 0;
for (; i < pair_count; ++i)
{
*buf++ = 0x12;
buf += uint32_pack(uint32_size(key_lens[i]) + uint32_size(val_lens[i]) + 2 + key_lens[i] + val_lens[i], buf);
*buf++ = 0x0A;
buf += uint32_pack(key_lens[i], buf);
memcpy(buf, keys[i], key_lens[i]);
buf += key_lens[i];
*buf++ = 0x12;
buf += uint32_pack(val_lens[i], buf);
memcpy(buf, values[i], val_lens[i]);
buf += val_lens[i];
}
assert(buf - (uint8_t*)log->now_buffer == totalBufferSize);
log->now_buffer_len += totalBufferSize;
log->now_buffer = (char *)buf;
}
#endif
//
// log_builder.h
// log-c-sdk
//
// Created by 王佳玮 on 16/8/23.
// Copyright © 2016年 wangjwchn. All rights reserved.
//
#ifndef LOG_BUILDER_H
#define LOG_BUILDER_H
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include "log_define.h"
// always build
#define LOG_KEY_VALUE_FLAG
LOG_CPP_START
typedef struct _log_tag{
char * buffer;
char * now_buffer;
uint32_t max_buffer_len;
uint32_t now_buffer_len;
}log_tag;
typedef struct _log_group{
char * source;
char * topic;
log_tag tags;
log_tag logs;
size_t n_logs;
#ifdef LOG_KEY_VALUE_FLAG
char * log_now_buffer;
#endif
}log_group;
typedef struct _lz4_log_buf{
size_t length;
size_t raw_length;
unsigned char data[0];
}lz4_log_buf;
typedef struct _log_group_builder{
log_group* grp;
size_t loggroup_size;
void * private_value;
uint32_t builder_time;
int64_t start_uuid;
int64_t end_uuid;
}log_group_builder;
typedef struct _log_buffer {
char * buffer;
uint32_t n_buffer;
}log_buf;
extern log_buf serialize_to_proto_buf_with_malloc(log_group_builder* bder);
extern lz4_log_buf* serialize_to_proto_buf_with_malloc_lz4(log_group_builder* bder);
extern lz4_log_buf* serialize_to_proto_buf_with_malloc_no_lz4(log_group_builder* bder);
extern void free_lz4_log_buf(lz4_log_buf* pBuf);
extern log_group_builder* log_group_create();
extern void log_group_destroy(log_group_builder* bder);
extern void add_log_full(log_group_builder* bder, uint32_t logTime, int32_t pair_count, char ** keys, size_t * key_lens, char ** values, size_t * val_lens);
extern void add_log_full_int32(log_group_builder* bder, uint32_t logTime, int32_t pair_count, char ** keys, int32_t * key_lens, char ** values, int32_t * val_lens);
extern void add_log_full_v2(log_group_builder* bder, uint32_t logTime, size_t logItemCount, const char * logItemsBuf, const uint32_t * logItemsSize);
extern void add_log_raw(log_group_builder* bder, const char * buffer, size_t size);
extern void add_source(log_group_builder* bder,const char* src,size_t len);
extern void add_topic(log_group_builder* bder,const char* tpc,size_t len);
extern void add_tag(log_group_builder* bder,const char* k,size_t k_len,const char* v,size_t v_len);
extern void add_pack_id(log_group_builder* bder, const char* pack, size_t pack_len, size_t packNum);
extern void fix_log_group_time(char * pb_buffer, size_t len, uint32_t new_time);
extern size_t serialize_pb_buffer_to_webtracking(char *pb_buffer, size_t len, char **new_buffer);
extern void fix_log_time(char * pb_buffer, size_t len, uint32_t new_time);
extern uint32_t get_log_time(const char * pb_buffer, size_t len);
extern void clear_log_tag(log_tag * tag);
// if you want to use this functions, add `-DADD_LOG_KEY_VALUE_FUN=ON` for cmake. eg `cmake . -DADD_LOG_KEY_VALUE_FUN=ON`
#ifdef LOG_KEY_VALUE_FLAG
/**
* call it when you want to add a new log
* @note sequence must be : add_log_begin -> add_log_time/add_log_key_value..... -> add_log_end
* @param bder
*/
extern void add_log_begin(log_group_builder * bder);
/**
* set log's time, must been called only once in one log
* @param bder
* @param logTime
*/
extern void add_log_time(log_group_builder * bder, uint32_t logTime);
/**
* add key&value pair to log tail
* @param bder
* @param key
* @param key_len
* @param value
* @param value_len
*/
extern void add_log_key_value(log_group_builder *bder, const char * key, size_t key_len, const char * value, size_t value_len);
/**
* add log end, call it when you add time and key&value done
* @param bder
*/
extern void add_log_end(log_group_builder * bder);
#endif
LOG_CPP_END
#endif /* log_builder_h */
#include <stdint.h>
#include <string.h>
#include "log_sha1.h"
#include "log_hmac-sha.h"
#define LOG_IPAD 0x36
#define LOG_OPAD 0x5C
#ifndef HMAC_SHORTONLY
void log_hmac_sha1_init(log_hmac_sha1_ctx_t *s, const void *key, uint16_t keylength_b){
uint8_t buffer[LOG_SHA1_BLOCK_BYTES];
uint8_t i;
memset(buffer, 0, LOG_SHA1_BLOCK_BYTES);
if (keylength_b > LOG_SHA1_BLOCK_BITS){
log_sha1((void*)buffer, key, keylength_b);
} else {
memcpy(buffer, key, (keylength_b+7)/8);
}
for (i=0; i<LOG_SHA1_BLOCK_BYTES; ++i){
buffer[i] ^= LOG_IPAD;
}
log_sha1_init(&(s->a));
log_sha1_nextBlock(&(s->a), buffer);
for (i=0; i<LOG_SHA1_BLOCK_BYTES; ++i){
buffer[i] ^= LOG_IPAD^LOG_OPAD;
}
log_sha1_init(&(s->b));
log_sha1_nextBlock(&(s->b), buffer);
#if defined SECURE_WIPE_BUFFER
memset(buffer, 0, LOG_SHA1_BLOCK_BYTES);
#endif
}
void log_hmac_sha1_nextBlock(log_hmac_sha1_ctx_t *s, const void *block){
log_sha1_nextBlock(&(s->a), block);
}
void log_hmac_sha1_lastBlock(log_hmac_sha1_ctx_t *s, const void *block, uint16_t length_b){
while(length_b>=LOG_SHA1_BLOCK_BITS){
log_sha1_nextBlock(&s->a, block);
block = (uint8_t*)block + LOG_SHA1_BLOCK_BYTES;
length_b -= LOG_SHA1_BLOCK_BITS;
}
log_sha1_lastBlock(&s->a, block, length_b);
}
void log_hmac_sha1_final(void *dest, log_hmac_sha1_ctx_t *s){
log_sha1_ctx2hash(dest, &s->a);
log_sha1_lastBlock(&s->b, dest, LOG_SHA1_HASH_BITS);
log_sha1_ctx2hash(dest, &(s->b));
}
#endif
/*
* keylength in bits!
* message length in bits!
*/
void log_hmac_sha1(void *dest, const void *key, uint16_t keylength_b, const void *msg, uint32_t msglength_b){ /* a one-shot*/
log_sha1_ctx_t s;
uint8_t i;
uint8_t buffer[LOG_SHA1_BLOCK_BYTES];
memset(buffer, 0, LOG_SHA1_BLOCK_BYTES);
/* if key is larger than a block we have to hash it*/
if (keylength_b > LOG_SHA1_BLOCK_BITS){
log_sha1((void*)buffer, key, keylength_b);
} else {
memcpy(buffer, key, (keylength_b+7)/8);
}
for (i=0; i<LOG_SHA1_BLOCK_BYTES; ++i){
buffer[i] ^= LOG_IPAD;
}
log_sha1_init(&s);
log_sha1_nextBlock(&s, buffer);
while (msglength_b >= LOG_SHA1_BLOCK_BITS){
log_sha1_nextBlock(&s, msg);
msg = (uint8_t*)msg + LOG_SHA1_BLOCK_BYTES;
msglength_b -= LOG_SHA1_BLOCK_BITS;
}
log_sha1_lastBlock(&s, msg, msglength_b);
/* since buffer still contains key xor ipad we can do ... */
for (i=0; i<LOG_SHA1_BLOCK_BYTES; ++i){
buffer[i] ^= LOG_IPAD ^ LOG_OPAD;
}
log_sha1_ctx2hash(dest, &s); /* save inner hash temporary to dest */
log_sha1_init(&s);
log_sha1_nextBlock(&s, buffer);
log_sha1_lastBlock(&s, dest, LOG_SHA1_HASH_BITS);
log_sha1_ctx2hash(dest, &s);
}
#ifndef LOG_HMACSHA1_H_
#define LOG_HMACSHA1_H_
#include "log_sha1.h"
#define LOG_HMAC_SHA1_BITS LOG_SHA1_HASH_BITS
#define LOG_HMAC_SHA1_BYTES LOG_SHA1_HASH_BYTES
#define LOG_HMAC_SHA1_BLOCK_BITS LOG_SHA1_BLOCK_BITS
#define LOG_HMAC_SHA1_BLOCK_BYTES LOG_SHA1_BLOCK_BYTES
typedef struct{
log_sha1_ctx_t a, b;
} log_hmac_sha1_ctx_t;
void log_hmac_sha1_init(log_hmac_sha1_ctx_t *s, const void *key, uint16_t keylength_b);
void log_hmac_sha1_nextBlock(log_hmac_sha1_ctx_t *s, const void *block);
void log_hmac_sha1_lastBlock(log_hmac_sha1_ctx_t *s, const void *block, uint16_t length_b);
void log_hmac_sha1_final(void *dest, log_hmac_sha1_ctx_t *s);
void log_hmac_sha1(void *dest, const void *key, uint16_t keylength_b, const void *msg, uint32_t msglength_b);
#endif /*LOG_HMACSHA1_H_*/
#include "log_http_interface.h"
#include <string.h>
#include <time.h>
LOG_CPP_START
// register external function
__attribute__ ((visibility("default")))
void log_set_http_post_func(int (*f)(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response));
__attribute__ ((visibility("default")))
void log_set_get_time_unix_func(unsigned int (*f)());
__attribute__ ((visibility("default")))
void log_set_http_header_inject_func(void (*f) (log_producer_config *config,
char **src_headers,
int src_count,
char **dest_headers,
int *dest_count)
);
void log_set_http_header_release_inject_func(void (*f) (log_producer_config *config,
char **dest_headers,
int dest_count)
);
static int (*__LOG_OS_HttpPost)(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response) = NULL;
static unsigned int (*__LOG_GET_TIME)() = NULL;
static void (*__log_http_header_injector)(log_producer_config *config, char **src_headers, int src_count, char **dest_headers, int *dest_count) = NULL;
static void (*__log_http_header_release_injector)(log_producer_config *config, char **dest_headers, int dest_count) = NULL;
void log_set_http_post_func(int (*f)(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response))
{
__LOG_OS_HttpPost = f;
}
void log_set_get_time_unix_func(unsigned int (*f)())
{
__LOG_GET_TIME = f;
}
unsigned int LOG_GET_TIME() {
if (__LOG_GET_TIME == NULL) {
return time(NULL);
}
return __LOG_GET_TIME();
}
int LOG_OS_HttpPost(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response)
{
int (*f)(const char *url,
char **header_array,
int header_count,
const void *data,
int data_len,
post_log_result *http_response) = NULL;
f = __LOG_OS_HttpPost;
int ret = 506;
if(f != NULL) {
ret = f(url, header_array, header_count, data, data_len, http_response);
}
return ret;
}
void log_set_http_header_inject_func(void (*f) (log_producer_config *config,
char **src_headers,
int src_count,
char **dest_header,
int *dest_count)
)
{
__log_http_header_injector = f;
}
void log_set_http_header_release_inject_func(void (*f) (log_producer_config *config,
char **dest_headers,
int dest_count)
)
{
__log_http_header_release_injector = f;
}
void log_http_inject_headers(log_producer_config *config, char **src_headers, int src_count, char **dest_headers, int *dest_count)
{
void (*f)(log_producer_config *config, char** src_headers, int src_count, char **dest_headers, int *dest_count) = NULL;
f = __log_http_header_injector;
if (NULL != f)
{
f(config, src_headers, src_count, dest_headers, dest_count);
}
}
void log_http_release_inject_headers(log_producer_config *config, char **dest_headers, int dest_count)
{
void (*f)(log_producer_config *config, char **dest_headers, int dest_count) = NULL;
f = __log_http_header_release_injector;
if (NULL != f) {
f(config, dest_headers, dest_count);
}
}
LOG_CPP_END
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2015, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/Cyan4973/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/**************************************
* Tuning parameters
**************************************/
/*
* LOG_HEAPMODE :
* Select how default compression functions will allocate memory for their hash table,
* in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
*/
#define LOG_HEAPMODE 0
/*
* LOG_ACCELERATION_DEFAULT :
* Select "acceleration" for LOG_LZ4_compress_fast() when parameter value <= 0
*/
#define LOG_ACCELERATION_DEFAULT 1
/**************************************
* CPU Feature Detection
**************************************/
/*
* LOG_LZ4_FORCE_SW_BITCOUNT
* Define this parameter if your target system or compiler does not support hardware bit count
*/
#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
# define LOG_LZ4_FORCE_SW_BITCOUNT
#endif
/**************************************
* Includes
**************************************/
#include "log_lz4.h"
/**************************************
* Compiler Options
**************************************/
#ifdef _MSC_VER /* Visual Studio */
# define FORCE_INLINE static __forceinline
# include <intrin.h>
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
#else
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
# if defined(__GNUC__) || defined(__clang__)
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
# else
# define FORCE_INLINE static
# endif /* __STDC_VERSION__ */
#endif /* _MSC_VER */
/* LOG_LZ4_GCC_VERSION is defined into lz4.h */
#if (LOG_LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
#else
# define expect(expr,value) (expr)
#endif
#define likely(expr) expect((expr) != 0, 1)
#define unlikely(expr) expect((expr) != 0, 0)
/**************************************
* Memory routines
**************************************/
#include <stdlib.h> /* malloc, calloc, free */
#define ALLOCATOR(n,s) calloc(n,s)
#define FREEMEM free
#include <string.h> /* memset, memcpy */
#define MEM_INIT memset
/**************************************
* Basic Types
**************************************/
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
#else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef unsigned int U32;
typedef signed int S32;
typedef unsigned long long U64;
#endif
/**************************************
* Reading and writing into memory
**************************************/
#define STEPSIZE sizeof(size_t)
static unsigned LZ4_64bits(void) { return sizeof(void*)==8; }
static unsigned LZ4_isLittleEndian(void)
{
const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
return one.c[0];
}
static U16 LZ4_read16(const void* memPtr)
{
U16 val16;
memcpy(&val16, memPtr, 2);
return val16;
}
static U16 LZ4_readLE16(const void* memPtr)
{
if (LZ4_isLittleEndian())
{
return LZ4_read16(memPtr);
}
else
{
const BYTE* p = (const BYTE*)memPtr;
return (U16)((U16)p[0] + (p[1]<<8));
}
}
static void LZ4_writeLE16(void* memPtr, U16 value)
{
if (LZ4_isLittleEndian())
{
memcpy(memPtr, &value, 2);
}
else
{
BYTE* p = (BYTE*)memPtr;
p[0] = (BYTE) value;
p[1] = (BYTE)(value>>8);
}
}
static U32 LZ4_read32(const void* memPtr)
{
U32 val32;
memcpy(&val32, memPtr, 4);
return val32;
}
static U64 LZ4_read64(const void* memPtr)
{
U64 val64;
memcpy(&val64, memPtr, 8);
return val64;
}
static size_t LZ4_read_ARCH(const void* p)
{
if (LZ4_64bits())
return (size_t)LZ4_read64(p);
else
return (size_t)LZ4_read32(p);
}
static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); }
static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); }
/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
{
BYTE* d = (BYTE*)dstPtr;
const BYTE* s = (const BYTE*)srcPtr;
BYTE* e = (BYTE*)dstEnd;
do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
}
/**************************************
* Common Constants
**************************************/
#define LOG_MINMATCH 4
#define LOG_COPYLENGTH 8
#define LOG_LASTLITERALS 5
#define LOG_MFLIMIT (LOG_COPYLENGTH+LOG_MINMATCH)
static const int LOG_LZ4_minLength = (LOG_MFLIMIT+1);
#define LOG_KB *(1 <<10)
#define LOG_MB *(1 <<20)
#define LOG_GB *(1U<<30)
#define LOG_MAXD_LOG 16
#define LOG_MAX_DISTANCE ((1 << LOG_MAXD_LOG) - 1)
#define LOG_ML_BITS 4
#define LOG_ML_MASK ((1U<<LOG_ML_BITS)-1)
#define LOG_RUN_BITS (8-LOG_ML_BITS)
#define LOG_RUN_MASK ((1U<<LOG_RUN_BITS)-1)
/**************************************
* Common Utils
**************************************/
#define LOG_LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
/**************************************
* Common functions
**************************************/
static unsigned LZ4_NbCommonBytes (register size_t val)
{
if (LZ4_isLittleEndian())
{
if (LZ4_64bits())
{
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanForward64( &r, (U64)val );
return (int)(r>>3);
# elif (defined(__clang__) || (LOG_LZ4_GCC_VERSION >= 304)) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctzll((U64)val) >> 3);
# else
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
# endif
}
else /* 32 bits */
{
# if defined(_MSC_VER) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
unsigned long r;
_BitScanForward( &r, (U32)val );
return (int)(r>>3);
# elif (defined(__clang__) || (LOG_LZ4_GCC_VERSION >= 304)) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctz((U32)val) >> 3);
# else
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
# endif
}
}
else /* Big Endian CPU */
{
if (LZ4_64bits())
{
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse64( &r, val );
return (unsigned)(r>>3);
# elif (defined(__clang__) || (LOG_LZ4_GCC_VERSION >= 304)) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clzll((U64)val) >> 3);
# else
unsigned r;
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
r += (!val);
return r;
# endif
}
else /* 32 bits */
{
# if defined(_MSC_VER) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse( &r, (unsigned long)val );
return (unsigned)(r>>3);
# elif (defined(__clang__) || (LOG_LZ4_GCC_VERSION >= 304)) && !defined(LOG_LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clz((U32)val) >> 3);
# else
unsigned r;
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
r += (!val);
return r;
# endif
}
}
}
static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
{
const BYTE* const pStart = pIn;
while (likely(pIn<pInLimit-(STEPSIZE-1)))
{
size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
pIn += LZ4_NbCommonBytes(diff);
return (unsigned)(pIn - pStart);
}
if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
return (unsigned)(pIn - pStart);
}
#ifndef LZ4_COMMONDEFS_ONLY
/**************************************
* Local Constants
**************************************/
#define LOG_LZ4_HASHLOG (LOG_LZ4_MEMORY_USAGE-2)
#define LOG_HASHTABLESIZE (1 << LOG_LZ4_MEMORY_USAGE)
#define LOG_HASH_SIZE_U32 (1 << LOG_LZ4_HASHLOG) /* required as macro for static allocation */
static const int LZ4_64Klimit = ((64 LOG_KB) + (LOG_MFLIMIT-1));
static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
/**************************************
* Local Structures and types
**************************************/
typedef struct {
U32 hashTable[LOG_HASH_SIZE_U32];
U32 currentOffset;
U32 initCheck;
const BYTE* dictionary;
BYTE* bufferStart; /* obsolete, used for slideInputBuffer */
U32 dictSize;
} LZ4_stream_t_internal;
typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
typedef enum { byPtr, byU32, byU16 } tableType_t;
typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
/**************************************
* Local Utils
**************************************/
int LOG_LZ4_versionNumber (void) { return LOG_LZ4_VERSION_NUMBER; }
int LOG_LZ4_compressBound(int isize) { return LOG_LZ4_COMPRESSBOUND(isize); }
int LOG_LZ4_sizeofState() { return LOG_LZ4_STREAMSIZE; }
/********************************
* Compression functions
********************************/
static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
{
if (tableType == byU16)
return (((sequence) * 2654435761U) >> ((LOG_MINMATCH*8)-(LOG_LZ4_HASHLOG+1)));
else
return (((sequence) * 2654435761U) >> ((LOG_MINMATCH*8)-LOG_LZ4_HASHLOG));
}
static const U64 prime5bytes = 889523592379ULL;
static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
{
const U32 hashLog = (tableType == byU16) ? LOG_LZ4_HASHLOG+1 : LOG_LZ4_HASHLOG;
const U32 hashMask = (1<<hashLog) - 1;
return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
}
static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
{
if (LZ4_64bits())
return LZ4_hashSequence64(sequence, tableType);
return LZ4_hashSequence((U32)sequence, tableType);
}
static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); }
static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
{
switch (tableType)
{
case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
}
}
static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
{
U32 h = LZ4_hashPosition(p, tableType);
LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
}
static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
{
if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
{ U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
}
static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
{
U32 h = LZ4_hashPosition(p, tableType);
return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
}
FORCE_INLINE int LZ4_compress_generic(
void* const ctx,
const char* const source,
char* const dest,
const int inputSize,
const int maxOutputSize,
const limitedOutput_directive outputLimited,
const tableType_t tableType,
const dict_directive dict,
const dictIssue_directive dictIssue,
const U32 acceleration)
{
LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx;
const BYTE* ip = (const BYTE*) source;
const BYTE* base;
const BYTE* lowLimit;
const BYTE* const lowRefLimit = ip - dictPtr->dictSize;
const BYTE* const dictionary = dictPtr->dictionary;
const BYTE* const dictEnd = dictionary + dictPtr->dictSize;
const size_t dictDelta = dictEnd - (const BYTE*)source;
const BYTE* anchor = (const BYTE*) source;
const BYTE* const iend = ip + inputSize;
const BYTE* const mflimit = iend - LOG_MFLIMIT;
const BYTE* const matchlimit = iend - LOG_LASTLITERALS;
BYTE* op = (BYTE*) dest;
BYTE* const olimit = op + maxOutputSize;
U32 forwardH;
size_t refDelta=0;
/* Init conditions */
if ((U32)inputSize > (U32)LOG_LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
switch(dict)
{
case noDict:
default:
base = (const BYTE*)source;
lowLimit = (const BYTE*)source;
break;
case withPrefix64k:
base = (const BYTE*)source - dictPtr->currentOffset;
lowLimit = (const BYTE*)source - dictPtr->dictSize;
break;
case usingExtDict:
base = (const BYTE*)source - dictPtr->currentOffset;
lowLimit = (const BYTE*)source;
break;
}
if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
if (inputSize<LOG_LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
/* First Byte */
LZ4_putPosition(ip, ctx, tableType, base);
ip++; forwardH = LZ4_hashPosition(ip, tableType);
/* Main Loop */
for ( ; ; )
{
const BYTE* match;
BYTE* token;
{
const BYTE* forwardIp = ip;
unsigned step = 1;
unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
/* Find a match */
do {
U32 h = forwardH;
ip = forwardIp;
forwardIp += step;
step = (searchMatchNb++ >> LZ4_skipTrigger);
if (unlikely(forwardIp > mflimit)) goto _last_literals;
match = LZ4_getPositionOnHash(h, ctx, tableType, base);
if (dict==usingExtDict)
{
if (match<(const BYTE*)source)
{
refDelta = dictDelta;
lowLimit = dictionary;
}
else
{
refDelta = 0;
lowLimit = (const BYTE*)source;
}
}
forwardH = LZ4_hashPosition(forwardIp, tableType);
LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
} while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
|| ((tableType==byU16) ? 0 : (match + LOG_MAX_DISTANCE < ip))
|| (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
}
/* Catch up */
while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
{
/* Encode Literal length */
unsigned litLength = (unsigned)(ip - anchor);
token = op++;
if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LOG_LASTLITERALS) + (litLength/255) > olimit)))
return 0; /* Check output limit */
if (litLength>=LOG_RUN_MASK)
{
int len = (int)litLength-LOG_RUN_MASK;
*token=(LOG_RUN_MASK<<LOG_ML_BITS);
for(; len >= 255 ; len-=255) *op++ = 255;
*op++ = (BYTE)len;
}
else *token = (BYTE)(litLength<<LOG_ML_BITS);
/* Copy Literals */
LZ4_wildCopy(op, anchor, op+litLength);
op+=litLength;
}
_next_match:
/* Encode Offset */
LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
/* Encode MatchLength */
{
unsigned matchLength;
if ((dict==usingExtDict) && (lowLimit==dictionary))
{
const BYTE* limit;
match += refDelta;
limit = ip + (dictEnd-match);
if (limit > matchlimit) limit = matchlimit;
matchLength = LZ4_count(ip+LOG_MINMATCH, match+LOG_MINMATCH, limit);
ip += LOG_MINMATCH + matchLength;
if (ip==limit)
{
unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit);
matchLength += more;
ip += more;
}
}
else
{
matchLength = LZ4_count(ip+LOG_MINMATCH, match+LOG_MINMATCH, matchlimit);
ip += LOG_MINMATCH + matchLength;
}
if ((outputLimited) && (unlikely(op + (1 + LOG_LASTLITERALS) + (matchLength>>8) > olimit)))
return 0; /* Check output limit */
if (matchLength>=LOG_ML_MASK)
{
*token += LOG_ML_MASK;
matchLength -= LOG_ML_MASK;
for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
if (matchLength >= 255) { matchLength-=255; *op++ = 255; }
*op++ = (BYTE)matchLength;
}
else *token += (BYTE)(matchLength);
}
anchor = ip;
/* Test end of chunk */
if (ip > mflimit) break;
/* Fill table */
LZ4_putPosition(ip-2, ctx, tableType, base);
/* Test next position */
match = LZ4_getPosition(ip, ctx, tableType, base);
if (dict==usingExtDict)
{
if (match<(const BYTE*)source)
{
refDelta = dictDelta;
lowLimit = dictionary;
}
else
{
refDelta = 0;
lowLimit = (const BYTE*)source;
}
}
LZ4_putPosition(ip, ctx, tableType, base);
if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
&& (match+LOG_MAX_DISTANCE>=ip)
&& (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
{ token=op++; *token=0; goto _next_match; }
/* Prepare next loop */
forwardH = LZ4_hashPosition(++ip, tableType);
}
_last_literals:
/* Encode Last Literals */
{
const size_t lastRun = (size_t)(iend - anchor);
if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-LOG_RUN_MASK)/255) > (U32)maxOutputSize))
return 0; /* Check output limit */
if (lastRun >= LOG_RUN_MASK)
{
size_t accumulator = lastRun - LOG_RUN_MASK;
*op++ = LOG_RUN_MASK << LOG_ML_BITS;
for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
*op++ = (BYTE) accumulator;
}
else
{
*op++ = (BYTE)(lastRun<<LOG_ML_BITS);
}
memcpy(op, anchor, lastRun);
op += lastRun;
}
/* End */
return (int) (((char*)op)-dest);
}
int LOG_LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
LOG_LZ4_resetStream((LOG_LZ4_stream_t*)state);
if (acceleration < 1) acceleration = LOG_ACCELERATION_DEFAULT;
if (maxOutputSize >= LOG_LZ4_compressBound(inputSize))
{
if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
else
return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
}
else
{
if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
else
return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
}
}
int LOG_LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
#if (LOG_HEAPMODE)
void* ctxPtr = ALLOCATOR(1, sizeof(LOG_LZ4_stream_t)); /* malloc-calloc always properly aligned */
#else
LOG_LZ4_stream_t ctx;
void* ctxPtr = &ctx;
#endif
int result = LOG_LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
#if (LOG_HEAPMODE)
FREEMEM(ctxPtr);
#endif
return result;
}
int LOG_LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
{
return LOG_LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
}
/* hidden debug function */
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
int LOG_LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
LOG_LZ4_stream_t ctx;
LOG_LZ4_resetStream(&ctx);
if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
else
return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
}
/********************************
* destSize variant
********************************/
static int LZ4_compress_destSize_generic(
void* const ctx,
const char* const src,
char* const dst,
int* const srcSizePtr,
const int targetDstSize,
const tableType_t tableType)
{
const BYTE* ip = (const BYTE*) src;
const BYTE* base = (const BYTE*) src;
const BYTE* lowLimit = (const BYTE*) src;
const BYTE* anchor = ip;
const BYTE* const iend = ip + *srcSizePtr;
const BYTE* const mflimit = iend - LOG_MFLIMIT;
const BYTE* const matchlimit = iend - LOG_LASTLITERALS;
BYTE* op = (BYTE*) dst;
BYTE* const oend = op + targetDstSize;
BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+LOG_MINMATCH==LOG_MFLIMIT */ - 1 /* token */;
BYTE* const oMaxMatch = op + targetDstSize - (LOG_LASTLITERALS + 1 /* token */);
BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
U32 forwardH;
/* Init conditions */
if (targetDstSize < 1) return 0; /* Impossible to store anything */
if ((U32)*srcSizePtr > (U32)LOG_LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
if (*srcSizePtr<LOG_LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
/* First Byte */
*srcSizePtr = 0;
LZ4_putPosition(ip, ctx, tableType, base);
ip++; forwardH = LZ4_hashPosition(ip, tableType);
/* Main Loop */
for ( ; ; )
{
const BYTE* match;
BYTE* token;
{
const BYTE* forwardIp = ip;
unsigned step = 1;
unsigned searchMatchNb = 1 << LZ4_skipTrigger;
/* Find a match */
do {
U32 h = forwardH;
ip = forwardIp;
forwardIp += step;
step = (searchMatchNb++ >> LZ4_skipTrigger);
if (unlikely(forwardIp > mflimit))
goto _last_literals;
match = LZ4_getPositionOnHash(h, ctx, tableType, base);
forwardH = LZ4_hashPosition(forwardIp, tableType);
LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
} while ( ((tableType==byU16) ? 0 : (match + LOG_MAX_DISTANCE < ip))
|| (LZ4_read32(match) != LZ4_read32(ip)) );
}
/* Catch up */
while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
{
/* Encode Literal length */
unsigned litLength = (unsigned)(ip - anchor);
token = op++;
if (op + ((litLength+240)/255) + litLength > oMaxLit)
{
/* Not enough space for a last match */
op--;
goto _last_literals;
}
if (litLength>=LOG_RUN_MASK)
{
unsigned len = litLength - LOG_RUN_MASK;
*token=(LOG_RUN_MASK<<LOG_ML_BITS);
for(; len >= 255 ; len-=255) *op++ = 255;
*op++ = (BYTE)len;
}
else *token = (BYTE)(litLength<<LOG_ML_BITS);
/* Copy Literals */
LZ4_wildCopy(op, anchor, op+litLength);
op += litLength;
}
_next_match:
/* Encode Offset */
LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
/* Encode MatchLength */
{
size_t matchLength;
matchLength = LZ4_count(ip+LOG_MINMATCH, match+LOG_MINMATCH, matchlimit);
if (op + ((matchLength+240)/255) > oMaxMatch)
{
/* Match description too long : reduce it */
matchLength = (15-1) + (oMaxMatch-op) * 255;
}
//printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + LOG_MINMATCH);
ip += LOG_MINMATCH + matchLength;
if (matchLength>=LOG_ML_MASK)
{
*token += LOG_ML_MASK;
matchLength -= LOG_ML_MASK;
while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
*op++ = (BYTE)matchLength;
}
else *token += (BYTE)(matchLength);
}
anchor = ip;
/* Test end of block */
if (ip > mflimit) break;
if (op > oMaxSeq) break;
/* Fill table */
LZ4_putPosition(ip-2, ctx, tableType, base);
/* Test next position */
match = LZ4_getPosition(ip, ctx, tableType, base);
LZ4_putPosition(ip, ctx, tableType, base);
if ( (match+LOG_MAX_DISTANCE>=ip)
&& (LZ4_read32(match)==LZ4_read32(ip)) )
{ token=op++; *token=0; goto _next_match; }
/* Prepare next loop */
forwardH = LZ4_hashPosition(++ip, tableType);
}
_last_literals:
/* Encode Last Literals */
{
size_t lastRunSize = (size_t)(iend - anchor);
if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)
{
/* adapt lastRunSize to fill 'dst' */
lastRunSize = (oend-op) - 1;
lastRunSize -= (lastRunSize+240)/255;
}
ip = anchor + lastRunSize;
if (lastRunSize >= LOG_RUN_MASK)
{
size_t accumulator = lastRunSize - LOG_RUN_MASK;
*op++ = LOG_RUN_MASK << LOG_ML_BITS;
for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
*op++ = (BYTE) accumulator;
}
else
{
*op++ = (BYTE)(lastRunSize<<LOG_ML_BITS);
}
memcpy(op, anchor, lastRunSize);
op += lastRunSize;
}
/* End */
*srcSizePtr = (int) (((const char*)ip)-src);
return (int) (((char*)op)-dst);
}
static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
{
LOG_LZ4_resetStream((LOG_LZ4_stream_t*)state);
if (targetDstSize >= LOG_LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
{
return LOG_LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
}
else
{
if (*srcSizePtr < LZ4_64Klimit)
return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
else
return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr);
}
}
int LOG_LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
{
#if (LOG_HEAPMODE)
void* ctx = ALLOCATOR(1, sizeof(LOG_LZ4_stream_t)); /* malloc-calloc always properly aligned */
#else
LOG_LZ4_stream_t ctxBody;
void* ctx = &ctxBody;
#endif
int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
#if (LOG_HEAPMODE)
FREEMEM(ctx);
#endif
return result;
}
/********************************
* Streaming functions
********************************/
LOG_LZ4_stream_t* LOG_LZ4_createStream(void)
{
LOG_LZ4_stream_t* lz4s = (LOG_LZ4_stream_t*)ALLOCATOR(8, LOG_LZ4_STREAMSIZE_U64);
LOG_LZ4_STATIC_ASSERT(LOG_LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LOG_LZ4_STREAMSIZE is not large enough */
LOG_LZ4_resetStream(lz4s);
return lz4s;
}
void LOG_LZ4_resetStream (LOG_LZ4_stream_t* LZ4_stream)
{
MEM_INIT(LZ4_stream, 0, sizeof(LOG_LZ4_stream_t));
}
int LOG_LZ4_freeStream (LOG_LZ4_stream_t* LZ4_stream)
{
FREEMEM(LZ4_stream);
return (0);
}
#define HASH_UNIT sizeof(size_t)
int LOG_LZ4_loadDict (LOG_LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
{
LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
const BYTE* p = (const BYTE*)dictionary;
const BYTE* const dictEnd = p + dictSize;
const BYTE* base;
if ((dict->initCheck) || (dict->currentOffset > 1 LOG_GB)) /* Uninitialized structure, or reuse overflow */
LOG_LZ4_resetStream(LZ4_dict);
if (dictSize < (int)HASH_UNIT)
{
dict->dictionary = NULL;
dict->dictSize = 0;
return 0;
}
if ((dictEnd - p) > 64 LOG_KB) p = dictEnd - 64 LOG_KB;
dict->currentOffset += 64 LOG_KB;
base = p - dict->currentOffset;
dict->dictionary = p;
dict->dictSize = (U32)(dictEnd - p);
dict->currentOffset += dict->dictSize;
while (p <= dictEnd-HASH_UNIT)
{
LZ4_putPosition(p, dict->hashTable, byU32, base);
p+=3;
}
return dict->dictSize;
}
static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
{
if ((LZ4_dict->currentOffset > 0x80000000) ||
((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
{
/* rescale hash table */
U32 delta = LZ4_dict->currentOffset - 64 LOG_KB;
const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
int i;
for (i=0; i<LOG_HASH_SIZE_U32; i++)
{
if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
else LZ4_dict->hashTable[i] -= delta;
}
LZ4_dict->currentOffset = 64 LOG_KB;
if (LZ4_dict->dictSize > 64 LOG_KB) LZ4_dict->dictSize = 64 LOG_KB;
LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
}
}
int LOG_LZ4_compress_fast_continue (LOG_LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{
LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream;
const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
const BYTE* smallest = (const BYTE*) source;
if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
LZ4_renormDictT(streamPtr, smallest);
if (acceleration < 1) acceleration = LOG_ACCELERATION_DEFAULT;
/* Check overlapping input/dictionary space */
{
const BYTE* sourceEnd = (const BYTE*) source + inputSize;
if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))
{
streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
if (streamPtr->dictSize > 64 LOG_KB) streamPtr->dictSize = 64 LOG_KB;
if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
streamPtr->dictionary = dictEnd - streamPtr->dictSize;
}
}
/* prefix mode : source data follows dictionary */
if (dictEnd == (const BYTE*)source)
{
int result;
if ((streamPtr->dictSize < 64 LOG_KB) && (streamPtr->dictSize < streamPtr->currentOffset))
result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
else
result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
streamPtr->dictSize += (U32)inputSize;
streamPtr->currentOffset += (U32)inputSize;
return result;
}
/* external dictionary mode */
{
int result;
if ((streamPtr->dictSize < 64 LOG_KB) && (streamPtr->dictSize < streamPtr->currentOffset))
result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
else
result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
streamPtr->dictionary = (const BYTE*)source;
streamPtr->dictSize = (U32)inputSize;
streamPtr->currentOffset += (U32)inputSize;
return result;
}
}
/* Hidden debug function, to force external dictionary mode */
int LOG_LZ4_compress_forceExtDict (LOG_LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
{
LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict;
int result;
const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
const BYTE* smallest = dictEnd;
if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest);
result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
streamPtr->dictionary = (const BYTE*)source;
streamPtr->dictSize = (U32)inputSize;
streamPtr->currentOffset += (U32)inputSize;
return result;
}
int LOG_LZ4_saveDict (LOG_LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
{
LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
const BYTE* previousDictEnd = dict->dictionary + dict->dictSize;
if ((U32)dictSize > 64 LOG_KB) dictSize = 64 LOG_KB; /* useless to define a dictionary > 64 KB */
if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
dict->dictionary = (const BYTE*)safeBuffer;
dict->dictSize = (U32)dictSize;
return dictSize;
}
/*******************************
* Decompression functions
*******************************/
/*
* This generic decompression function cover all use cases.
* It shall be instantiated several times, using different sets of directives
* Note that it is essential this generic function is really inlined,
* in order to remove useless branches during compilation optimization.
*/
FORCE_INLINE int LZ4_decompress_generic(
const char* const source,
char* const dest,
int inputSize,
int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
int endOnInput, /* endOnOutputSize, endOnInputSize */
int partialDecoding, /* full, partial */
int targetOutputSize, /* only used if partialDecoding==partial */
int dict, /* noDict, withPrefix64k, usingExtDict */
const BYTE* const lowPrefix, /* == dest if dict == noDict */
const BYTE* const dictStart, /* only if dict==usingExtDict */
const size_t dictSize /* note : = 0 if noDict */
)
{
/* Local Variables */
const BYTE* ip = (const BYTE*) source;
const BYTE* const iend = ip + inputSize;
BYTE* op = (BYTE*) dest;
BYTE* const oend = op + outputSize;
BYTE* cpy;
BYTE* oexit = op + targetOutputSize;
const BYTE* const lowLimit = lowPrefix - dictSize;
const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
const int safeDecode = (endOnInput==endOnInputSize);
const int checkOffset = ((safeDecode) && (dictSize < (int)(64 LOG_KB)));
/* Special cases */
if ((partialDecoding) && (oexit> oend-LOG_MFLIMIT)) oexit = oend-LOG_MFLIMIT; /* targetOutputSize too high => decode everything */
if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
/* Main Loop */
while (1)
{
unsigned token;
size_t length;
const BYTE* match;
/* get literal length */
token = *ip++;
if ((length=(token>>LOG_ML_BITS)) == LOG_RUN_MASK)
{
unsigned s;
do
{
s = *ip++;
length += s;
}
while (likely((endOnInput)?ip<iend-LOG_RUN_MASK:1) && (s==255));
if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
}
/* copy literals */
cpy = op+length;
if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-LOG_MFLIMIT)) || (ip+length>iend-(2+1+LOG_LASTLITERALS))) )
|| ((!endOnInput) && (cpy>oend-LOG_COPYLENGTH)))
{
if (partialDecoding)
{
if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
}
else
{
if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
}
memcpy(op, ip, length);
ip += length;
op += length;
break; /* Necessarily EOF, due to parsing restrictions */
}
LZ4_wildCopy(op, ip, cpy);
ip += length; op = cpy;
/* get offset */
match = cpy - LZ4_readLE16(ip); ip+=2;
if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
/* get matchlength */
length = token & LOG_ML_MASK;
if (length == LOG_ML_MASK)
{
unsigned s;
do
{
if ((endOnInput) && (ip > iend-LOG_LASTLITERALS)) goto _output_error;
s = *ip++;
length += s;
} while (s==255);
if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
}
length += LOG_MINMATCH;
/* check external dictionary */
if ((dict==usingExtDict) && (match < lowPrefix))
{
if (unlikely(op+length > oend-LOG_LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
if (length <= (size_t)(lowPrefix-match))
{
/* match can be copied as a single segment from external dictionary */
match = dictEnd - (lowPrefix-match);
memmove(op, match, length); op += length;
}
else
{
/* match encompass external dictionary and current segment */
size_t copySize = (size_t)(lowPrefix-match);
memcpy(op, dictEnd - copySize, copySize);
op += copySize;
copySize = length - copySize;
if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
{
BYTE* const endOfMatch = op + copySize;
const BYTE* copyFrom = lowPrefix;
while (op < endOfMatch) *op++ = *copyFrom++;
}
else
{
memcpy(op, lowPrefix, copySize);
op += copySize;
}
}
continue;
}
/* copy repeated sequence */
cpy = op + length;
if (unlikely((op-match)<8))
{
const size_t dec64 = dec64table[op-match];
op[0] = match[0];
op[1] = match[1];
op[2] = match[2];
op[3] = match[3];
match += dec32table[op-match];
LZ4_copy4(op+4, match);
op += 8; match -= dec64;
} else { LZ4_copy8(op, match); op+=8; match+=8; }
if (unlikely(cpy>oend-12))
{
if (cpy > oend-LOG_LASTLITERALS) goto _output_error; /* Error : last LOG_LASTLITERALS bytes must be literals */
if (op < oend-8)
{
LZ4_wildCopy(op, match, oend-8);
match += (oend-8) - op;
op = oend-8;
}
while (op<cpy) *op++ = *match++;
}
else
LZ4_wildCopy(op, match, cpy);
op=cpy; /* correction */
}
/* end of decoding */
if (endOnInput)
return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
else
return (int) (((const char*)ip)-source); /* Nb of input bytes read */
/* Overflow error detected */
_output_error:
return (int) (-(((const char*)ip)-source))-1;
}
int LOG_LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
{
return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
}
int LOG_LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
{
return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
}
int LOG_LZ4_decompress_fast(const char* source, char* dest, int originalSize)
{
return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 LOG_KB), NULL, 64 LOG_KB);
}
/* streaming decompression functions */
typedef struct
{
const BYTE* externalDict;
size_t extDictSize;
const BYTE* prefixEnd;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
/*
* If you prefer dynamic allocation methods,
* LOG_LZ4_createStreamDecode()
* provides a pointer (void*) towards an initialized LOG_LZ4_streamDecode_t structure.
*/
LOG_LZ4_streamDecode_t* LOG_LZ4_createStreamDecode(void)
{
LOG_LZ4_streamDecode_t* lz4s = (LOG_LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LOG_LZ4_streamDecode_t));
return lz4s;
}
int LOG_LZ4_freeStreamDecode (LOG_LZ4_streamDecode_t* LZ4_stream)
{
FREEMEM(LZ4_stream);
return 0;
}
/*
* LOG_LZ4_setStreamDecode
* Use this function to instruct where to find the dictionary
* This function is not necessary if previous data is still available where it was decoded.
* Loading a size of 0 is allowed (same effect as no dictionary).
* Return : 1 if OK, 0 if error
*/
int LOG_LZ4_setStreamDecode (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
{
LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
lz4sd->prefixSize = (size_t) dictSize;
lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
lz4sd->externalDict = NULL;
lz4sd->extDictSize = 0;
return 1;
}
/*
*_continue() :
These decoding functions allow decompression of multiple blocks in "streaming" mode.
Previously decoded blocks must still be available at the memory position where they were decoded.
If it's not possible, save the relevant part of decoded data into a safe buffer,
and indicate where it stands using LOG_LZ4_setStreamDecode()
*/
int LOG_LZ4_decompress_safe_continue (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
{
LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
int result;
if (lz4sd->prefixEnd == (BYTE*)dest)
{
result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
endOnInputSize, full, 0,
usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize += result;
lz4sd->prefixEnd += result;
}
else
{
lz4sd->extDictSize = lz4sd->prefixSize;
lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
endOnInputSize, full, 0,
usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize = result;
lz4sd->prefixEnd = (BYTE*)dest + result;
}
return result;
}
int LOG_LZ4_decompress_fast_continue (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
{
LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
int result;
if (lz4sd->prefixEnd == (BYTE*)dest)
{
result = LZ4_decompress_generic(source, dest, 0, originalSize,
endOnOutputSize, full, 0,
usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize += originalSize;
lz4sd->prefixEnd += originalSize;
}
else
{
lz4sd->extDictSize = lz4sd->prefixSize;
lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
result = LZ4_decompress_generic(source, dest, 0, originalSize,
endOnOutputSize, full, 0,
usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
if (result <= 0) return result;
lz4sd->prefixSize = originalSize;
lz4sd->prefixEnd = (BYTE*)dest + originalSize;
}
return result;
}
/*
Advanced decoding functions :
*_usingDict() :
These decoding functions work the same as "_continue" ones,
the dictionary must be explicitly provided within parameters
*/
FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
{
if (dictSize==0)
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
if (dictStart+dictSize == dest)
{
if (dictSize >= (int)(64 LOG_KB - 1))
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 LOG_KB, NULL, 0);
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
}
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
}
int LOG_LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
{
return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
}
int LOG_LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
{
return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
}
/* debug function */
int LOG_LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
{
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
}
/***************************************************
* Obsolete Functions
***************************************************/
/* obsolete compression functions */
int LOG_LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LOG_LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
int LOG_LZ4_compress(const char* source, char* dest, int inputSize) { return LOG_LZ4_compress_default(source, dest, inputSize, LOG_LZ4_compressBound(inputSize)); }
int LOG_LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LOG_LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }
int LOG_LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LOG_LZ4_compress_fast_extState(state, src, dst, srcSize, LOG_LZ4_compressBound(srcSize), 1); }
int LOG_LZ4_compress_limitedOutput_continue (LOG_LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LOG_LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); }
int LOG_LZ4_compress_continue (LOG_LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LOG_LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LOG_LZ4_compressBound(inputSize), 1); }
/*
These function names are deprecated and should no longer be used.
They are only provided here for compatibility with older user programs.
- LOG_LZ4_uncompress is totally equivalent to LOG_LZ4_decompress_fast
- LOG_LZ4_uncompress_unknownOutputSize is totally equivalent to LOG_LZ4_decompress_safe
*/
int LOG_LZ4_uncompress (const char* source, char* dest, int outputSize) { return LOG_LZ4_decompress_fast(source, dest, outputSize); }
int LOG_LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LOG_LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
/* Obsolete Streaming functions */
int LOG_LZ4_sizeofStreamState() { return LOG_LZ4_STREAMSIZE; }
static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base)
{
MEM_INIT(lz4ds, 0, LOG_LZ4_STREAMSIZE);
lz4ds->bufferStart = base;
}
int LOG_LZ4_resetStreamState(void* state, char* inputBuffer)
{
if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */
LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer);
return 0;
}
void* LOG_LZ4_create (char* inputBuffer)
{
void* lz4ds = ALLOCATOR(8, LOG_LZ4_STREAMSIZE_U64);
LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer);
return lz4ds;
}
char* LOG_LZ4_slideInputBuffer (void* LZ4_Data)
{
LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data;
int dictSize = LOG_LZ4_saveDict((LOG_LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 LOG_KB);
return (char*)(ctx->bufferStart + dictSize);
}
/* Obsolete streaming decompression functions */
int LOG_LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
{
return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 LOG_KB, NULL, 64 LOG_KB);
}
int LOG_LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
{
return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 LOG_KB, NULL, 64 LOG_KB);
}
#endif /* LZ4_COMMONDEFS_ONLY */
/*
LZ4 - Fast LZ compression algorithm
Header File
Copyright (C) 2011-2015, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/Cyan4973/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#pragma once
#if defined (__cplusplus)
extern "C" {
#endif
/*
* lz4.h provides block compression functions, and gives full buffer control to programmer.
* If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
* and can let the library handle its own memory, please use lz4frame.h instead.
*/
/**************************************
* Version
**************************************/
#define LOG_LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LOG_LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
#define LOG_LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
#define LOG_LZ4_VERSION_NUMBER (LOG_LZ4_VERSION_MAJOR *100*100 + LOG_LZ4_VERSION_MINOR *100 + LOG_LZ4_VERSION_RELEASE)
int LOG_LZ4_versionNumber (void);
/**************************************
* Tuning parameter
**************************************/
/*
* LOG_LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
* Increasing memory usage improves compression ratio
* Reduced memory usage can improve speed, due to cache effect
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/
#define LOG_LZ4_MEMORY_USAGE 14
/**************************************
* Simple Functions
**************************************/
int LOG_LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
int LOG_LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
/*
LOG_LZ4_compress_default() :
Compresses 'sourceSize' bytes from buffer 'source'
into already allocated 'dest' buffer of size 'maxDestSize'.
Compression is guaranteed to succeed if 'maxDestSize' >= LOG_LZ4_compressBound(sourceSize).
It also runs faster, so it's a recommended setting.
If the function cannot compress 'source' into a more limited 'dest' budget,
compression stops *immediately*, and the function result is zero.
As a consequence, 'dest' content is not valid.
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
or 0 if compression fails
LOG_LZ4_decompress_safe() :
compressedSize : is the precise full size of the compressed block.
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
If destination buffer is not large enough, decoding will stop and output an error code (<0).
If the source stream is detected malformed, the function will stop decoding and return a negative result.
This function is protected against buffer overflow exploits, including malicious data packets.
It never writes outside output buffer, nor reads outside input buffer.
*/
/**************************************
* Advanced Functions
**************************************/
#define LOG_LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LOG_LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LOG_LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*
LOG_LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LOG_LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
Note that LOG_LZ4_compress_default() compress faster when dest buffer size is >= LOG_LZ4_compressBound(srcSize)
inputSize : max supported value is LOG_LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is too large ( > LOG_LZ4_MAX_INPUT_SIZE)
*/
int LOG_LZ4_compressBound(int inputSize);
/*
LOG_LZ4_compress_fast() :
Same as LOG_LZ4_compress_default(), but allows to select an "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LOG_LZ4_compress_default()
Values <= 0 will be replaced by LOG_ACCELERATION_DEFAULT (see lz4.c), which is 1.
*/
int LOG_LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
/*
LOG_LZ4_compress_fast_extState() :
Same compression function, just using an externally allocated memory space to store compression state.
Use LOG_LZ4_sizeofState() to know how much memory must be allocated,
and allocate it on 8-bytes boundaries (using malloc() typically).
Then, provide it as 'void* state' to compression function.
*/
int LOG_LZ4_sizeofState(void);
int LOG_LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
/*
LOG_LZ4_compress_destSize() :
Reverse the logic, by compressing as much data as possible from 'source' buffer
into already allocated buffer 'dest' of size 'targetDestSize'.
This function either compresses the entire 'source' content into 'dest' if it's large enough,
or fill 'dest' buffer completely with as much data as possible from 'source'.
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
New value is necessarily <= old value.
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
or 0 if compression fails
*/
int LOG_LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
/*
LOG_LZ4_decompress_fast() :
originalSize : is the original and therefore uncompressed size
return : the number of bytes read from the source buffer (in other words, the compressed size)
If the source stream is detected malformed, the function will stop decoding and return a negative result.
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
note : This function fully respect memory boundaries for properly formed compressed data.
It is a bit faster than LOG_LZ4_decompress_safe().
However, it does not provide any protection against intentionally modified data stream (malicious input).
Use this function in trusted environment only (data to decode comes from a trusted source).
*/
int LOG_LZ4_decompress_fast (const char* source, char* dest, int originalSize);
/*
LOG_LZ4_decompress_safe_partial() :
This function decompress a compressed block of size 'compressedSize' at position 'source'
into destination buffer 'dest' of size 'maxDecompressedSize'.
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
reducing decompression time.
return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
Always control how many bytes were decoded.
If the source stream is detected malformed, the function will stop decoding and return a negative result.
This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
*/
int LOG_LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
/***********************************************
* Streaming Compression Functions
***********************************************/
#define LOG_LZ4_STREAMSIZE_U64 ((1 << (LOG_LZ4_MEMORY_USAGE-3)) + 4)
#define LOG_LZ4_STREAMSIZE (LOG_LZ4_STREAMSIZE_U64 * sizeof(long long))
/*
* LOG_LZ4_stream_t
* information structure to track an LZ4 stream.
* important : init this structure content before first use !
* note : only allocated directly the structure if you are statically linking LZ4
* If you are using liblz4 as a DLL, please use below construction methods instead.
*/
typedef struct { long long table[LOG_LZ4_STREAMSIZE_U64]; } LOG_LZ4_stream_t;
/*
* LOG_LZ4_resetStream
* Use this function to init an allocated LOG_LZ4_stream_t structure
*/
void LOG_LZ4_resetStream (LOG_LZ4_stream_t* streamPtr);
/*
* LOG_LZ4_createStream will allocate and initialize an LOG_LZ4_stream_t structure
* LOG_LZ4_freeStream releases its memory.
* In the context of a DLL (liblz4), please use these methods rather than the static struct.
* They are more future proof, in case of a change of LOG_LZ4_stream_t size.
*/
LOG_LZ4_stream_t* LOG_LZ4_createStream(void);
int LOG_LZ4_freeStream (LOG_LZ4_stream_t* streamPtr);
/*
* LOG_LZ4_loadDict
* Use this function to load a static dictionary into LZ4_stream.
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
* Loading a size of 0 is allowed.
* Return : dictionary size, in bytes (necessarily <= 64 KB)
*/
int LOG_LZ4_loadDict (LOG_LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*
* LOG_LZ4_compress_fast_continue
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
* Important : Previous data blocks are assumed to still be present and unmodified !
* 'dst' buffer must be already allocated.
* If maxDstSize >= LOG_LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
*/
int LOG_LZ4_compress_fast_continue (LOG_LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
/*
* LOG_LZ4_saveDict
* If previously compressed data block is not guaranteed to remain available at its memory location
* save it into a safer place (char* safeBuffer)
* Note : you don't need to call LOG_LZ4_loadDict() afterwards,
* dictionary is immediately usable, you can therefore call LOG_LZ4_compress_fast_continue()
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
*/
int LOG_LZ4_saveDict (LOG_LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
/************************************************
* Streaming Decompression Functions
************************************************/
#define LOG_LZ4_STREAMDECODESIZE_U64 4
#define LOG_LZ4_STREAMDECODESIZE (LOG_LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
typedef struct { unsigned long long table[LOG_LZ4_STREAMDECODESIZE_U64]; } LOG_LZ4_streamDecode_t;
/*
* LOG_LZ4_streamDecode_t
* information structure to track an LZ4 stream.
* init this structure content using LOG_LZ4_setStreamDecode or memset() before first use !
*
* In the context of a DLL (liblz4) please prefer usage of construction methods below.
* They are more future proof, in case of a change of LOG_LZ4_streamDecode_t size in the future.
* LOG_LZ4_createStreamDecode will allocate and initialize an LOG_LZ4_streamDecode_t structure
* LOG_LZ4_freeStreamDecode releases its memory.
*/
LOG_LZ4_streamDecode_t* LOG_LZ4_createStreamDecode(void);
int LOG_LZ4_freeStreamDecode (LOG_LZ4_streamDecode_t* LZ4_stream);
/*
* LOG_LZ4_setStreamDecode
* Use this function to instruct where to find the dictionary.
* Setting a size of 0 is allowed (same effect as reset).
* Return : 1 if OK, 0 if error
*/
int LOG_LZ4_setStreamDecode (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
/*
*_continue() :
These decoding functions allow decompression of multiple blocks in "streaming" mode.
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
In the case of a ring buffers, decoding buffer must be either :
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including small ones ( < 64 KB).
- _At least_ 64 KB + 8 bytes + maxBlockSize.
In which case, encoding and decoding buffers do not need to be synchronized,
and encoding ring buffer can have any size, including larger than decoding buffer.
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
and indicate where it is saved using LOG_LZ4_setStreamDecode()
*/
int LOG_LZ4_decompress_safe_continue (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
int LOG_LZ4_decompress_fast_continue (LOG_LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
/*
Advanced decoding functions :
*_usingDict() :
These decoding functions work the same as
a combination of LOG_LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
They are stand-alone. They don't need nor update an LOG_LZ4_streamDecode_t structure.
*/
int LOG_LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
int LOG_LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
/**************************************
* Obsolete Functions
**************************************/
/* Deprecate Warnings */
/* Should these warnings messages be a problem,
it is generally possible to disable them,
with -Wno-deprecated-declarations for gcc
or _CRT_SECURE_NO_WARNINGS in Visual for example.
You can also define LOG_LZ4_DEPRECATE_WARNING_DEFBLOCK. */
#ifndef LOG_LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LOG_LZ4_DEPRECATE_WARNING_DEFBLOCK
# define LOG_LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# if (LOG_LZ4_GCC_VERSION >= 405) || defined(__clang__)
# define LOG_LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif (LOG_LZ4_GCC_VERSION >= 301)
# define LOG_LZ4_DEPRECATED(message) __attribute__((deprecated))
# elif defined(_MSC_VER)
# define LOG_LZ4_DEPRECATED(message) __declspec(deprecated(message))
# else
# pragma message("WARNING: You need to implement LOG_LZ4_DEPRECATED for this compiler")
# define LOG_LZ4_DEPRECATED(message)
# endif
#endif /* LOG_LZ4_DEPRECATE_WARNING_DEFBLOCK */
/* Obsolete compression functions */
/* These functions are planned to start generate warnings by r131 approximately */
int LOG_LZ4_compress (const char* source, char* dest, int sourceSize);
int LOG_LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
int LOG_LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
int LOG_LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
int LOG_LZ4_compress_continue (LOG_LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
int LOG_LZ4_compress_limitedOutput_continue (LOG_LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete decompression functions */
/* These function names are completely deprecated and must no longer be used.
They are only provided here for compatibility with older programs.
- LOG_LZ4_uncompress is the same as LOG_LZ4_decompress_fast
- LOG_LZ4_uncompress_unknownOutputSize is the same as LOG_LZ4_decompress_safe
These function prototypes are now disabled; uncomment them only if you really need them.
It is highly recommended to stop using these prototypes and migrate to maintained ones */
/* int LOG_LZ4_uncompress (const char* source, char* dest, int outputSize); */
/* int LOG_LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
/* Obsolete streaming functions; use new streaming interface whenever possible */
LOG_LZ4_DEPRECATED("use LOG_LZ4_createStream() instead") void* LOG_LZ4_create (char* inputBuffer);
LOG_LZ4_DEPRECATED("use LOG_LZ4_createStream() instead") int LOG_LZ4_sizeofStreamState(void);
LOG_LZ4_DEPRECATED("use LOG_LZ4_resetStream() instead") int LOG_LZ4_resetStreamState(void* state, char* inputBuffer);
LOG_LZ4_DEPRECATED("use LOG_LZ4_saveDict() instead") char* LOG_LZ4_slideInputBuffer (void* state);
/* Obsolete streaming decoding functions */
LOG_LZ4_DEPRECATED("use LOG_LZ4_decompress_safe_usingDict() instead") int LOG_LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LOG_LZ4_DEPRECATED("use LOG_LZ4_decompress_fast_usingDict() instead") int LOG_LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
#if defined (__cplusplus)
}
#endif
#include "log_md5.h"
#include <string.h>
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
void log_mbedtls_md5_init( log_mbedtls_md5_context *ctx )
{
memset( ctx, 0, sizeof( log_mbedtls_md5_context ) );
}
void log_mbedtls_md5_clone( log_mbedtls_md5_context *dst,
const log_mbedtls_md5_context *src )
{
*dst = *src;
}
/*
* MD5 context setup
*/
void log_mbedtls_md5_starts( log_mbedtls_md5_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
#if !defined(MBEDTLS_MD5_PROCESS_ALT)
void log_mbedtls_md5_process( log_mbedtls_md5_context *ctx, const unsigned char data[64] )
{
uint32_t X[16], A, B, C, D;
GET_UINT32_LE( X[ 0], data, 0 );
GET_UINT32_LE( X[ 1], data, 4 );
GET_UINT32_LE( X[ 2], data, 8 );
GET_UINT32_LE( X[ 3], data, 12 );
GET_UINT32_LE( X[ 4], data, 16 );
GET_UINT32_LE( X[ 5], data, 20 );
GET_UINT32_LE( X[ 6], data, 24 );
GET_UINT32_LE( X[ 7], data, 28 );
GET_UINT32_LE( X[ 8], data, 32 );
GET_UINT32_LE( X[ 9], data, 36 );
GET_UINT32_LE( X[10], data, 40 );
GET_UINT32_LE( X[11], data, 44 );
GET_UINT32_LE( X[12], data, 48 );
GET_UINT32_LE( X[13], data, 52 );
GET_UINT32_LE( X[14], data, 56 );
GET_UINT32_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z)))
P( A, B, C, D, 0, 7, 0xD76AA478 );
P( D, A, B, C, 1, 12, 0xE8C7B756 );
P( C, D, A, B, 2, 17, 0x242070DB );
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
P( A, B, C, D, 4, 7, 0xF57C0FAF );
P( D, A, B, C, 5, 12, 0x4787C62A );
P( C, D, A, B, 6, 17, 0xA8304613 );
P( B, C, D, A, 7, 22, 0xFD469501 );
P( A, B, C, D, 8, 7, 0x698098D8 );
P( D, A, B, C, 9, 12, 0x8B44F7AF );
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
P( B, C, D, A, 11, 22, 0x895CD7BE );
P( A, B, C, D, 12, 7, 0x6B901122 );
P( D, A, B, C, 13, 12, 0xFD987193 );
P( C, D, A, B, 14, 17, 0xA679438E );
P( B, C, D, A, 15, 22, 0x49B40821 );
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P( A, B, C, D, 1, 5, 0xF61E2562 );
P( D, A, B, C, 6, 9, 0xC040B340 );
P( C, D, A, B, 11, 14, 0x265E5A51 );
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
P( A, B, C, D, 5, 5, 0xD62F105D );
P( D, A, B, C, 10, 9, 0x02441453 );
P( C, D, A, B, 15, 14, 0xD8A1E681 );
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
P( D, A, B, C, 14, 9, 0xC33707D6 );
P( C, D, A, B, 3, 14, 0xF4D50D87 );
P( B, C, D, A, 8, 20, 0x455A14ED );
P( A, B, C, D, 13, 5, 0xA9E3E905 );
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
P( C, D, A, B, 7, 14, 0x676F02D9 );
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
#undef F
#define F(x,y,z) (x ^ y ^ z)
P( A, B, C, D, 5, 4, 0xFFFA3942 );
P( D, A, B, C, 8, 11, 0x8771F681 );
P( C, D, A, B, 11, 16, 0x6D9D6122 );
P( B, C, D, A, 14, 23, 0xFDE5380C );
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
P( A, B, C, D, 13, 4, 0x289B7EC6 );
P( D, A, B, C, 0, 11, 0xEAA127FA );
P( C, D, A, B, 3, 16, 0xD4EF3085 );
P( B, C, D, A, 6, 23, 0x04881D05 );
P( A, B, C, D, 9, 4, 0xD9D4D039 );
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
P( B, C, D, A, 2, 23, 0xC4AC5665 );
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P( A, B, C, D, 0, 6, 0xF4292244 );
P( D, A, B, C, 7, 10, 0x432AFF97 );
P( C, D, A, B, 14, 15, 0xAB9423A7 );
P( B, C, D, A, 5, 21, 0xFC93A039 );
P( A, B, C, D, 12, 6, 0x655B59C3 );
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
P( C, D, A, B, 10, 15, 0xFFEFF47D );
P( B, C, D, A, 1, 21, 0x85845DD1 );
P( A, B, C, D, 8, 6, 0x6FA87E4F );
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
P( C, D, A, B, 6, 15, 0xA3014314 );
P( B, C, D, A, 13, 21, 0x4E0811A1 );
P( A, B, C, D, 4, 6, 0xF7537E82 );
P( D, A, B, C, 11, 10, 0xBD3AF235 );
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
P( B, C, D, A, 9, 21, 0xEB86D391 );
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
#endif /* !MBEDTLS_MD5_PROCESS_ALT */
/*
* MD5 process buffer
*/
void log_mbedtls_md5_update( log_mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
log_mbedtls_md5_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
log_mbedtls_md5_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
}
static const unsigned char md5_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD5 final digest
*/
void log_mbedtls_md5_finish( log_mbedtls_md5_context *ctx, unsigned char output[16] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_LE( low, msglen, 0 );
PUT_UINT32_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
log_mbedtls_md5_update( ctx, md5_padding, padn );
log_mbedtls_md5_update( ctx, msglen, 8 );
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 );
}
/*
* output = MD5( input buffer )
*/
void log_mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
{
log_mbedtls_md5_context ctx;
log_mbedtls_md5_init( &ctx );
log_mbedtls_md5_starts( &ctx );
log_mbedtls_md5_update( &ctx, input, ilen );
log_mbedtls_md5_finish( &ctx, output );
}
#ifndef LOG_MD5_H_
#define LOG_MD5_H_
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MD5 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
} log_mbedtls_md5_context;
/**
* \brief Initialize MD5 context
*
* \param ctx MD5 context to be initialized
*/
void log_mbedtls_md5_init( log_mbedtls_md5_context *ctx );
/**
* \brief Clone (the state of) an MD5 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void log_mbedtls_md5_clone( log_mbedtls_md5_context *dst,
const log_mbedtls_md5_context *src );
/**
* \brief MD5 context setup
*
* \param ctx context to be initialized
*/
void log_mbedtls_md5_starts( log_mbedtls_md5_context *ctx );
/**
* \brief MD5 process buffer
*
* \param ctx MD5 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void log_mbedtls_md5_update( log_mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief MD5 final digest
*
* \param ctx MD5 context
* \param output MD5 checksum result
*/
void log_mbedtls_md5_finish( log_mbedtls_md5_context *ctx, unsigned char output[16] );
/* Internal use */
void log_mbedtls_md5_process( log_mbedtls_md5_context *ctx, const unsigned char data[64] );
/**
* \brief Output = MD5( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD5 checksum result
*/
void log_mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
#ifdef __cplusplus
}
#endif
#endif /*LOG_MD5_H_*/
//
// Created by davidzhang on 2020/8/23.
//
#include "log_persistent_manager.h"
#include "log_producer_manager.h"
#include "inner_log.h"
#include "log_builder.h"
#include "log_sds.h"
#define MAX_CHECKPOINT_FILE_SIZE (sizeof(log_persistent_checkpoint) * 1024)
#define LOG_PERSISTENT_HEADER_MAGIC (0xf7216a5b76df67f5)
static int32_t is_valid_log_checkpoint(log_persistent_checkpoint * checkpoint)
{
return checkpoint->check_sum == checkpoint->start_log_uuid + checkpoint->now_log_uuid +
checkpoint->start_file_offset + checkpoint->now_file_offset;
}
static int32_t recover_log_checkpoint(log_persistent_manager * manager)
{
FILE * tmpFile = fopen(manager->checkpoint_file_path, "rb");
if (tmpFile == NULL)
{
if (errno == ENOENT)
{
return 0;
}
return -1;
}
fseek(tmpFile, 0, SEEK_END);
long pos = ftell(tmpFile);
if (pos == 0)
{
// empty file
return 0;
}
long fixedPos = pos - pos%sizeof(log_persistent_checkpoint);
long lastPos = fixedPos == 0? 0 : fixedPos - sizeof(log_persistent_checkpoint);
fseek(tmpFile, lastPos, SEEK_SET);
if (1 != fread((void *)&(manager->checkpoint), sizeof(log_persistent_checkpoint), 1, tmpFile))
{
fclose(tmpFile);
return -2;
}
if (!is_valid_log_checkpoint(&(manager->checkpoint)))
{
fclose(tmpFile);
return -3;
}
fclose(tmpFile);
manager->checkpoint_file_size = pos;
return 0;
}
int save_log_checkpoint(log_persistent_manager * manager)
{
log_persistent_checkpoint * checkpoint = &(manager->checkpoint);
checkpoint->check_sum = checkpoint->start_log_uuid + checkpoint->now_log_uuid +
checkpoint->start_file_offset + checkpoint->now_file_offset;
if (manager->checkpoint_file_size >= MAX_CHECKPOINT_FILE_SIZE)
{
if (manager->checkpoint_file_ptr != NULL)
{
fclose(manager->checkpoint_file_ptr);
manager->checkpoint_file_ptr = NULL;
}
char tmpFilePath[256];
strcpy(tmpFilePath, manager->checkpoint_file_path);
strcat(tmpFilePath, ".bak");
aos_info_log("start switch checkpoint index file %s \n", manager->checkpoint_file_path);
FILE * tmpFile = fopen(tmpFilePath, "wb+");
if (tmpFile == NULL)
return -1;
if (1 !=
fwrite((const void *)(&manager->checkpoint), sizeof(log_persistent_checkpoint), 1, tmpFile))
{
fclose(tmpFile);
return -2;
}
if (fclose(tmpFile) != 0)
return -3;
if (rename(tmpFilePath, manager->checkpoint_file_path) != 0 )
return -4;
manager->checkpoint_file_size = sizeof(log_persistent_checkpoint);
return 0;
}
if (manager->checkpoint_file_ptr == NULL)
{
manager->checkpoint_file_ptr = fopen(manager->checkpoint_file_path, "ab+");
if (manager->checkpoint_file_ptr == NULL)
return -5;
}
if (1 !=
fwrite((const void *)(&manager->checkpoint), sizeof(log_persistent_checkpoint), 1, manager->checkpoint_file_ptr))
return -6;
if (fflush(manager->checkpoint_file_ptr) != 0)
return -7;
manager->checkpoint_file_size += sizeof(log_persistent_checkpoint);
return 0;
}
void on_log_persistent_manager_send_done_uuid(const char * config_name,
log_producer_result result,
size_t log_bytes,
size_t compressed_bytes,
const char * req_id,
const char * error_message,
const unsigned char * raw_buffer,
void *persistent_manager,
int64_t startId,
int64_t endId)
{
if (result != LOG_PRODUCER_OK && result != LOG_PRODUCER_DROP_ERROR && result != LOG_PRODUCER_INVALID)
{
return;
}
log_persistent_manager * manager = (log_persistent_manager *)persistent_manager;
if (manager == NULL)
{
return;
}
if (manager->is_invalid)
{
return;
}
if (startId < 0 || endId < 0 || startId > endId || endId - startId > 1024 * 1024)
{
aos_fatal_log("invalid id range %lld %lld", startId, endId);
manager->is_invalid = 1;
return;
}
// multi thread send is not allowed, and this should never happen
if (startId > manager->checkpoint.start_log_uuid)
{
aos_fatal_log("project %s, logstore %s, invalid checkpoint start log uuid %lld %lld",
manager->config->project,
manager->config->logstore,
startId,
manager->checkpoint.start_log_uuid);
manager->is_invalid = 1;
return;
}
CS_ENTER(manager->lock);
// cal log size
uint64_t totalOffset = 0;
for (int64_t id = startId; id <= endId; ++id)
{
totalOffset += manager->in_buffer_log_sizes[id % manager->config->maxPersistentLogCount];
}
manager->checkpoint.start_file_offset += totalOffset;
manager->checkpoint.start_log_uuid = endId + 1;
int rst = save_log_checkpoint(manager);
if (rst != 0)
{
aos_error_log("project %s, logstore %s, save checkpoint failed, reason %d",
manager->config->project,
manager->config->logstore,
rst);
}
log_ring_file_clean(manager->ring_file, manager->checkpoint.start_file_offset - totalOffset, manager->checkpoint.start_file_offset);
CS_LEAVE(manager->lock);
}
static void log_persistent_manager_init(log_persistent_manager * manager, log_producer_config *config)
{
memset(manager, 0, sizeof(log_persistent_manager));
manager->builder = log_group_create();
manager->checkpoint.start_log_uuid = (int64_t)(time(NULL)) * 1000LL * 1000LL * 1000LL;
manager->checkpoint.now_log_uuid = manager->checkpoint.start_log_uuid;
manager->config = config;
manager->lock = CreateCriticalSection();
manager->in_buffer_log_sizes = (uint32_t *)malloc(sizeof(uint32_t) * config->maxPersistentLogCount);
manager->checkpoint_file_path = log_sdscat(log_sdsdup(config->persistentFilePath), ".idx");
memset(manager->in_buffer_log_sizes, 0, sizeof(uint32_t) * config->maxPersistentLogCount);
manager->ring_file = log_ring_file_open(config->persistentFilePath, config->maxPersistentFileCount, config->maxPersistentFileSize, config->forceFlushDisk);
}
static void log_persistent_manager_clear(log_persistent_manager * manager)
{
log_group_destroy(manager->builder);
ReleaseCriticalSection(manager->lock);
if (manager->checkpoint_file_ptr != NULL)
{
fclose(manager->checkpoint_file_ptr);
manager->checkpoint_file_ptr = NULL;
}
free(manager->in_buffer_log_sizes);
log_sdsfree(manager->checkpoint_file_path);
log_ring_file_close(manager->ring_file);
}
log_persistent_manager *
create_log_persistent_manager(log_producer_config *config)
{
if (!log_producer_persistent_config_is_enabled(config))
{
return NULL;
}
log_persistent_manager * manager = (log_persistent_manager *)malloc(sizeof(log_persistent_manager));
log_persistent_manager_init(manager, config);
return manager;
}
void destroy_log_persistent_manager(log_persistent_manager *manager)
{
if (manager == NULL)
{
return;
}
log_persistent_manager_clear(manager);
free(manager);
}
int log_persistent_manager_save_log(log_persistent_manager *manager,
const char *logBuf, size_t logSize)
{
// save binlog
const void * buffer[2];
size_t bufferSize[2];
log_persistent_item_header header;
header.magic_code = LOG_PERSISTENT_HEADER_MAGIC;
header.log_uuid = manager->checkpoint.now_log_uuid;
header.log_size = logSize;
header.preserved = 0;
buffer[0] = &header;
buffer[1] = logBuf;
bufferSize[0] = sizeof(log_persistent_item_header);
bufferSize[1] = logSize;
int rst = log_ring_file_write(manager->ring_file, manager->checkpoint.now_file_offset, 2, buffer, bufferSize);
if (rst != bufferSize[0] + bufferSize[1])
{
aos_error_log("project %s, logstoe %s, write bin log failed, rst %d",
manager->config->project,
manager->config->logstore,
rst);
return LOG_PRODUCER_PERSISTENT_ERROR;
}
// update in memory checkpoint
manager->in_buffer_log_sizes[manager->checkpoint.now_log_uuid % manager->config->maxPersistentLogCount] = rst;
manager->checkpoint.now_file_offset += rst;
++manager->checkpoint.now_log_uuid;
aos_debug_log("project %s, logstore %s, write bin log success, offset %lld, uuid %lld, log size %d",
manager->config->project,
manager->config->logstore,
manager->checkpoint.now_file_offset,
manager->checkpoint.now_log_uuid,
rst);
if (manager->first_checkpoint_saved == 0)
{
save_log_checkpoint(manager);
manager->first_checkpoint_saved = 1;
}
return 0;
}
int log_persistent_manager_is_buffer_enough(log_persistent_manager *manager,
size_t logSize)
{
if (manager->checkpoint.now_file_offset - manager->checkpoint.start_file_offset + logSize + 1024 >
(uint64_t)manager->config->maxPersistentFileCount * manager->config->maxPersistentFileSize &&
manager->checkpoint.now_log_uuid - manager->checkpoint.start_log_uuid < manager->config->maxPersistentLogCount - 1)
{
return 0;
}
return 1;
}
static int log_persistent_manager_recover_inner(log_persistent_manager *manager,
log_producer_manager *producer_manager)
{
int rst = recover_log_checkpoint(manager);
if (rst != 0)
{
return rst;
}
aos_info_log("project %s, logstore %s, recover persistent checkpoint success, checkpoint %lld %lld %lld %lld",
manager->config->project,
manager->config->logstore,
manager->checkpoint.start_file_offset,
manager->checkpoint.now_file_offset,
manager->checkpoint.start_log_uuid,
manager->checkpoint.now_log_uuid);
if (manager->checkpoint.start_file_offset == 0 && manager->checkpoint.now_file_offset == 0)
{
// no need to recover
return 0;
}
// try recover ring file
log_persistent_item_header header;
uint64_t fileOffset = manager->checkpoint.start_file_offset;
int64_t logUUID = manager->checkpoint.start_log_uuid;
char * buffer = NULL;
int max_buffer_size = 0;
while (1)
{
rst = log_ring_file_read(manager->ring_file, fileOffset, &header, sizeof(log_persistent_item_header));
if (rst != sizeof(log_persistent_item_header))
{
if (rst == 0)
{
aos_info_log("project %s, logstore %s, read end of file",
manager->config->project,
manager->config->logstore);
if (buffer != NULL)
{
free(buffer);
buffer = NULL;
}
break;
}
aos_error_log("project %s, logstore %s, read binlog file header failed, offset %lld, result %d",
manager->config->project,
manager->config->logstore,
fileOffset,
rst);
if (buffer != NULL)
{
free(buffer);
buffer = NULL;
}
return -1;
}
if (header.magic_code != LOG_PERSISTENT_HEADER_MAGIC ||
header.log_uuid < logUUID ||
header.log_size <= 0 || header.log_size > 10*1024*1024 )
{
aos_info_log("project %s, logstore %s, read binlog file success, uuid %lld %lld",
manager->config->project,
manager->config->logstore,
header.log_uuid,
logUUID);
break;
}
if (buffer == NULL || max_buffer_size < header.log_size)
{
if (buffer != NULL)
{
free(buffer);
}
buffer = (char *)malloc(header.log_size * 2);
max_buffer_size = header.log_size * 2;
}
rst = log_ring_file_read(manager->ring_file, fileOffset + sizeof(log_persistent_item_header), buffer, header.log_size);
if (rst != header.log_size)
{
// if read fail, just break
aos_warn_log("project %s, logstore %s, read binlog file content failed, offset %lld, result %d",
manager->config->project,
manager->config->logstore,
fileOffset + sizeof(log_persistent_item_header),
rst);
break;
}
if (header.log_uuid - logUUID > 1024*1024)
{
aos_error_log("project %s, logstore %s, log uuid jump, %lld %lld",
manager->config->project,
manager->config->logstore,
header.log_uuid,
logUUID);
if (buffer != NULL)
{
free(buffer);
buffer = NULL;
}
return -3;
}
// set empty log uuid len 0
for (int64_t emptyUUID = logUUID + 1; emptyUUID < header.log_uuid; ++emptyUUID)
{
manager->in_buffer_log_sizes[emptyUUID % manager->config->maxPersistentLogCount] = 0;
}
manager->in_buffer_log_sizes[header.log_uuid % manager->config->maxPersistentLogCount] = header.log_size + sizeof(log_persistent_item_header);
logUUID = header.log_uuid;
fileOffset += header.log_size + sizeof(log_persistent_item_header);
rst = log_producer_manager_add_log_raw(producer_manager, buffer, header.log_size, 0, header.log_uuid);
if (rst != 0)
{
aos_error_log("project %s, logstore %s, add log to producer manager failed, this log will been dropped",
manager->config->project,
manager->config->logstore);
}
}
if (buffer != NULL)
{
free(buffer);
buffer = NULL;
}
if (logUUID < manager->checkpoint.now_log_uuid - 1)
{
// replay fail
aos_fatal_log("project %s, logstore %s, replay bin log failed, now log uuid %lld, expected min log uuid %lld, start uuid %lld, start offset %lld, now offset %lld, replayed offset %lld",
manager->config->project,
manager->config->logstore,
logUUID,
manager->checkpoint.now_log_uuid,
manager->checkpoint.start_log_uuid,
manager->checkpoint.start_file_offset,
manager->checkpoint.now_file_offset,
fileOffset);
return -4;
}
// update new checkpoint when replay bin log success
if (fileOffset > manager->checkpoint.start_file_offset)
{
manager->checkpoint.now_log_uuid = logUUID + 1;
manager->checkpoint.now_file_offset = fileOffset;
}
aos_info_log("project %s, logstore %s, replay bin log success, now checkpoint %lld %lld %lld %lld",
manager->config->project,
manager->config->logstore,
manager->checkpoint.start_log_uuid,
manager->checkpoint.now_log_uuid,
manager->checkpoint.start_file_offset,
manager->checkpoint.now_file_offset);
// save new checkpoint
rst = save_log_checkpoint(manager);
if (rst != 0)
{
aos_error_log("project %s, logstore %s, save checkpoint failed, reason %d",
manager->config->project,
manager->config->logstore,
rst);
}
return rst;
}
static void log_persistent_manager_reset(log_persistent_manager * manager)
{
log_producer_config * config = manager->config;
log_persistent_manager_clear(manager);
log_persistent_manager_init(manager, config);
manager->checkpoint.start_log_uuid = (int64_t)(time(NULL)) * 1000LL * 1000LL * 1000LL + 500LL * 1000LL * 1000LL;
manager->checkpoint.now_log_uuid = manager->checkpoint.start_log_uuid;
manager->is_invalid = 0;
}
int log_persistent_manager_recover(log_persistent_manager *manager,
log_producer_manager *producer_manager)
{
aos_info_log("project %s, logstore %s, start recover persistent manager",
manager->config->project,
manager->config->logstore);
CS_ENTER(manager->lock);
int rst = log_persistent_manager_recover_inner(manager, producer_manager);
if (rst != 0)
{
// if recover failed, reset persistent manager
manager->is_invalid = 1;
log_persistent_manager_reset(manager);
}
else
{
manager->is_invalid = 0;
}
CS_LEAVE(manager->lock);
return rst;
}
//
// Created by davidzhang on 2020/8/23.
//
#include "log_inner_include.h"
#include "log_producer_config.h"
#include "log_ring_file.h"
#include "log_builder.h"
#include "log_producer_manager.h"
#ifndef LOG_C_SDK_LOG_PERSISTENT_MANAGER_H
#define LOG_C_SDK_LOG_PERSISTENT_MANAGER_H
typedef struct _log_persistent_checkpoint {
uint64_t version;
unsigned char signature[16]; // persistent config signature
uint64_t start_file_offset; // logic file start offset in buffer
uint64_t now_file_offset; // logic now file offset
int64_t start_log_uuid; // start log uuid in buffer
int64_t now_log_uuid; // now log uuid
uint64_t check_sum; // start_file_offset + now_file_offset + start_log_uuid + now_log_uuid
unsigned char preserved[32];
}log_persistent_checkpoint;
typedef struct _log_persistent_item_header
{
uint64_t magic_code;
int64_t log_uuid;
int64_t log_size;
uint64_t preserved;
}log_persistent_item_header;
typedef struct _log_persistent_manager{
CRITICALSECTION lock;
log_persistent_checkpoint checkpoint;
uint32_t * in_buffer_log_sizes;
log_producer_config * config;
log_group_builder * builder;
int8_t is_invalid;
int8_t first_checkpoint_saved;
log_ring_file * ring_file;
FILE * checkpoint_file_ptr;
char * checkpoint_file_path;
size_t checkpoint_file_size;
}log_persistent_manager;
log_persistent_manager * create_log_persistent_manager(log_producer_config * config);
void destroy_log_persistent_manager(log_persistent_manager * manager);
void on_log_persistent_manager_send_done_uuid(const char * config_name,
log_producer_result result,
size_t log_bytes,
size_t compressed_bytes,
const char * req_id,
const char * error_message,
const unsigned char * raw_buffer,
void *persistent_manager,
int64_t startId,
int64_t endId);
int log_persistent_manager_save_log(log_persistent_manager * manager, const char * logBuf, size_t logSize);
int log_persistent_manager_is_buffer_enough(log_persistent_manager * manager, size_t logSize);
int save_log_checkpoint(log_persistent_manager * manager);
int log_persistent_manager_recover(log_persistent_manager * manager, log_producer_manager * producer_manager);
#endif //LOG_C_SDK_LOG_PERSISTENT_MANAGER_H
//
// Created by ZhangCheng on 20/11/2017.
//
#include "log_producer_client.h"
#include "log_producer_manager.h"
#include "inner_log.h"
#include "log_api.h"
#include <stdarg.h>
#include <string.h>
#include "log_persistent_manager.h"
static uint32_t s_init_flag = 0;
static log_producer_result s_last_result = 0;
unsigned int LOG_GET_TIME();
typedef struct _producer_client_private {
log_producer_manager * producer_manager;
log_producer_config * producer_config;
log_persistent_manager * persistent_manager;
}producer_client_private ;
struct _log_producer {
log_producer_client * root_client;
};
log_producer_result log_producer_env_init()
{
// if already init, just return s_last_result
if (s_init_flag == 1)
{
return s_last_result;
}
s_init_flag = 1;
if (0 != sls_log_init())
{
s_last_result = LOG_PRODUCER_INVALID;
}
else
{
s_last_result = LOG_PRODUCER_OK;
}
return s_last_result;
}
void log_producer_env_destroy()
{
if (s_init_flag == 0)
{
return;
}
s_init_flag = 0;
sls_log_destroy();
}
log_producer * create_log_producer(log_producer_config * config, on_log_producer_send_done_function send_done_function, void *user_param)
{
if (!log_producer_config_is_valid(config))
{
return NULL;
}
log_producer * producer = (log_producer *)malloc(sizeof(log_producer));
log_producer_client * producer_client = (log_producer_client *)malloc(sizeof(log_producer_client));
producer_client_private * client_private = (producer_client_private *)malloc(sizeof(producer_client_private));
producer_client->private_data = client_private;
client_private->producer_config = config;
client_private->producer_manager = create_log_producer_manager(config);
client_private->producer_manager->send_done_function = send_done_function;
client_private->producer_manager->user_param = user_param;
client_private->persistent_manager = create_log_persistent_manager(config);
if (client_private->persistent_manager != NULL)
{
client_private->producer_manager->uuid_user_param = client_private->persistent_manager;
client_private->producer_manager->uuid_send_done_function = on_log_persistent_manager_send_done_uuid;
int recoverRst = log_persistent_manager_recover(client_private->persistent_manager, client_private->producer_manager);
if (recoverRst != 0)
{
aos_error_log("project %s, logstore %s, recover log persistent manager failed, result %d",
config->project,
config->logstore,
recoverRst);
}
else
{
aos_info_log("project %s, logstore %s, recover log persistent manager success",
config->project,
config->logstore);
}
}
aos_debug_log("create producer client success, config : %s", config->logstore);
producer_client->valid_flag = 1;
producer->root_client = producer_client;
return producer;
}
void destroy_log_producer(log_producer * producer)
{
if (producer == NULL)
{
return;
}
log_producer_client * client = producer->root_client;
client->valid_flag = 0;
producer_client_private * client_private = (producer_client_private *)client->private_data;
destroy_log_producer_manager(client_private->producer_manager);
destroy_log_producer_config(client_private->producer_config);
destroy_log_persistent_manager(client_private->persistent_manager);
free(client_private);
free(client);
free(producer);
}
extern log_producer_client * get_log_producer_client(log_producer * producer, const char * config_name)
{
if (producer == NULL)
{
return NULL;
}
return producer->root_client;
}
void log_producer_client_network_recover(log_producer_client * client)
{
if (client == NULL)
{
return;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
manager->networkRecover = 1;
}
log_producer_result log_producer_client_add_log(log_producer_client * client, int32_t kv_count, ...)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
va_list argp;
va_start(argp, kv_count);
int32_t pairs = kv_count / 2;
char ** keys = (char **)malloc(pairs * sizeof(char *));
char ** values = (char **)malloc(pairs * sizeof(char *));
size_t * key_lens = (size_t *)malloc(pairs * sizeof(size_t));
size_t * val_lens = (size_t *)malloc(pairs * sizeof(size_t));
int32_t i = 0;
for (; i < pairs; ++i)
{
const char * key = va_arg(argp, const char *);
const char * value = va_arg(argp, const char *);
keys[i] = (char *)key;
values[i] = (char *)value;
key_lens[i] = strlen(key);
val_lens[i] = strlen(value);
}
log_producer_result rst = log_producer_client_add_log_with_len(client, pairs, keys, key_lens, values, val_lens, 0);
free(keys);
free(values);
free(key_lens);
free(val_lens);
return rst;
}
log_producer_result log_producer_client_add_log_with_len(log_producer_client * client, int32_t pair_count, char ** keys, size_t * key_lens, char ** values, size_t * val_lens, int flush)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
log_persistent_manager * persistent_manager = ((producer_client_private *)client->private_data)->persistent_manager;
if (persistent_manager != NULL && persistent_manager->is_invalid == 0)
{
CS_ENTER(persistent_manager->lock);
add_log_full(persistent_manager->builder, LOG_GET_TIME(), pair_count, keys, key_lens, values, val_lens);
char * logBuf = persistent_manager->builder->grp->logs.buffer;
size_t logSize = persistent_manager->builder->grp->logs.now_buffer_len;
clear_log_tag(&(persistent_manager->builder->grp->logs));
if (!log_persistent_manager_is_buffer_enough(persistent_manager, logSize) ||
manager->totalBufferSize > manager->producer_config->maxBufferBytes)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
int rst = log_persistent_manager_save_log(persistent_manager, logBuf, logSize);
if (rst != LOG_PRODUCER_OK)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, persistent_manager->checkpoint.now_log_uuid - 1);
CS_LEAVE(persistent_manager->lock);
return rst;
}
return log_producer_manager_add_log(manager, pair_count, keys, key_lens, values, val_lens, flush, -1);
}
log_producer_result log_producer_client_add_raw_log_buffer(log_producer_client * client, size_t log_bytes, size_t compressed_bytes, const unsigned char * raw_buffer)
{
if (client == NULL || !client->valid_flag || raw_buffer == NULL)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
return log_producer_manager_send_raw_buffer(manager, log_bytes, compressed_bytes, raw_buffer);
}
log_producer_result
log_producer_client_add_log_raw(log_producer_client *client, char *logBuf,
size_t logSize, int flush)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
log_persistent_manager * persistent_manager = ((producer_client_private *)client->private_data)->persistent_manager;
if (persistent_manager != NULL && persistent_manager->is_invalid == 0)
{
CS_ENTER(persistent_manager->lock);
if (!log_persistent_manager_is_buffer_enough(persistent_manager, logSize) ||
manager->totalBufferSize > manager->producer_config->maxBufferBytes)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
int rst = log_persistent_manager_save_log(persistent_manager, logBuf, logSize);
if (rst != LOG_PRODUCER_OK)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, persistent_manager->checkpoint.now_log_uuid - 1);
CS_LEAVE(persistent_manager->lock);
return rst;
}
int rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, -1);
return rst;
}
log_producer_result
log_producer_client_add_log_with_array(log_producer_client *client,
uint32_t logTime, size_t logItemCount,
const char *logItemsBuf,
const uint32_t *logItemsSize, int flush)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
log_persistent_manager * persistent_manager = ((producer_client_private *)client->private_data)->persistent_manager;
if (persistent_manager != NULL && persistent_manager->is_invalid == 0)
{
CS_ENTER(persistent_manager->lock);
add_log_full_v2(persistent_manager->builder, logTime, logItemCount, logItemsBuf, logItemsSize);
char * logBuf = persistent_manager->builder->grp->logs.buffer;
size_t logSize = persistent_manager->builder->grp->logs.now_buffer_len;
clear_log_tag(&(persistent_manager->builder->grp->logs));
if (!log_persistent_manager_is_buffer_enough(persistent_manager, logSize) ||
manager->totalBufferSize > manager->producer_config->maxBufferBytes)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
int rst = log_persistent_manager_save_log(persistent_manager, logBuf, logSize);
if (rst != LOG_PRODUCER_OK)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, persistent_manager->checkpoint.now_log_uuid - 1);
CS_LEAVE(persistent_manager->lock);
return rst;
}
int rst = log_producer_manager_add_log_with_array(manager, logTime, logItemCount, logItemsBuf, logItemsSize, flush, -1);
return rst;
}
log_producer_result
log_producer_client_add_log_with_len_int32(log_producer_client *client,
int32_t pair_count, char **keys,
int32_t *key_lens, char **values,
int32_t *value_lens, int flush)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
log_persistent_manager * persistent_manager = ((producer_client_private *)client->private_data)->persistent_manager;
if (persistent_manager != NULL && persistent_manager->is_invalid == 0)
{
CS_ENTER(persistent_manager->lock);
add_log_full_int32(persistent_manager->builder, LOG_GET_TIME(), pair_count, keys, key_lens, values, value_lens);
char * logBuf = persistent_manager->builder->grp->logs.buffer;
size_t logSize = persistent_manager->builder->grp->logs.now_buffer_len;
clear_log_tag(&(persistent_manager->builder->grp->logs));
if (!log_persistent_manager_is_buffer_enough(persistent_manager, logSize) ||
manager->totalBufferSize > manager->producer_config->maxBufferBytes)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
int rst = log_persistent_manager_save_log(persistent_manager, logBuf, logSize);
if (rst != LOG_PRODUCER_OK)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, persistent_manager->checkpoint.now_log_uuid - 1);
CS_LEAVE(persistent_manager->lock);
return rst;
}
return log_producer_manager_add_log_int32(manager, pair_count, keys, key_lens, values, value_lens, flush, -1);
}
log_producer_result
log_producer_client_add_log_with_len_time_int32(log_producer_client *client,
uint32_t time_sec,
int32_t pair_count, char **keys,
int32_t *key_lens, char **values,
int32_t *value_lens, int flush)
{
if (client == NULL || !client->valid_flag)
{
return LOG_PRODUCER_INVALID;
}
log_producer_manager * manager = ((producer_client_private *)client->private_data)->producer_manager;
log_persistent_manager * persistent_manager = ((producer_client_private *)client->private_data)->persistent_manager;
if (persistent_manager != NULL && persistent_manager->is_invalid == 0)
{
CS_ENTER(persistent_manager->lock);
add_log_full_int32(persistent_manager->builder, time_sec, pair_count, keys, key_lens, values, value_lens);
char * logBuf = persistent_manager->builder->grp->logs.buffer;
size_t logSize = persistent_manager->builder->grp->logs.now_buffer_len;
clear_log_tag(&(persistent_manager->builder->grp->logs));
if (!log_persistent_manager_is_buffer_enough(persistent_manager, logSize) ||
manager->totalBufferSize > manager->producer_config->maxBufferBytes)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
int rst = log_persistent_manager_save_log(persistent_manager, logBuf, logSize);
if (rst != LOG_PRODUCER_OK)
{
CS_LEAVE(persistent_manager->lock);
return LOG_PRODUCER_DROP_ERROR;
}
rst = log_producer_manager_add_log_raw(manager, logBuf, logSize, flush, persistent_manager->checkpoint.now_log_uuid - 1);
CS_LEAVE(persistent_manager->lock);
return rst;
}
return log_producer_manager_add_log_int32(manager, pair_count, keys, key_lens, values, value_lens, flush, -1);
}
//
// Created by ZhangCheng on 21/11/2017.
//
#include "log_producer_common.h"
#ifdef WIN32
#include <windows.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
log_producer_result LOG_PRODUCER_OK = 0;
log_producer_result LOG_PRODUCER_INVALID = 1;
log_producer_result LOG_PRODUCER_WRITE_ERROR = 2;
log_producer_result LOG_PRODUCER_DROP_ERROR = 3;
log_producer_result LOG_PRODUCER_SEND_NETWORK_ERROR = 4;
log_producer_result LOG_PRODUCER_SEND_QUOTA_ERROR = 5;
log_producer_result LOG_PRODUCER_SEND_UNAUTHORIZED = 6;
log_producer_result LOG_PRODUCER_SEND_SERVER_ERROR = 7;
log_producer_result LOG_PRODUCER_SEND_DISCARD_ERROR = 8;
log_producer_result LOG_PRODUCER_SEND_TIME_ERROR = 9;
log_producer_result LOG_PRODUCER_SEND_EXIT_BUFFERED = 10;
log_producer_result LOG_PRODUCER_PARAMETERS_INVALID = 11;
log_producer_result LOG_PRODUCER_PERSISTENT_ERROR = 99;
int is_log_producer_result_ok(log_producer_result rst)
{
return rst == LOG_PRODUCER_OK;
}
//
// Created by ZhangCheng on 20/11/2017.
//
#include "log_producer_config.h"
#include "log_sds.h"
#include <string.h>
#include <stdlib.h>
#include "inner_log.h"
static void _set_default_producer_config(log_producer_config * pConfig)
{
pConfig->logBytesPerPackage = 3 * 1024 * 1024;
pConfig->logCountPerPackage = 2048;
pConfig->packageTimeoutInMS = 3000;
pConfig->maxBufferBytes = 64 * 1024 * 1024;
pConfig->flushIntervalInMS = LOG_PRODUCER_FLUSH_INTERVAL_MS;
pConfig->logQueuePopIntervalInMS = LOG_PRODUCER_QUEUE_POP_INTERVAL_MS;
pConfig->connectTimeoutSec = 10;
pConfig->sendTimeoutSec = 15;
pConfig->destroySenderWaitTimeoutSec = 1;
pConfig->destroyFlusherWaitTimeoutSec = 1;
pConfig->compressType = 1;
pConfig->ntpTimeOffset = 0;
pConfig->using_https = 0;
pConfig->maxLogDelayTime = 7*24*3600;
pConfig->dropDelayLog = 1;
pConfig->callbackFromSenderThread = 1;
pConfig->webTracking = 0;
pConfig->mode = 0;
pConfig->user_params = NULL;
}
static void _copy_config_string(const char * value, log_sds * src_value)
{
if (src_value == NULL)
{
return;
}
if (value == NULL)
{
*src_value = NULL;
return;
}
size_t strLen = strlen(value);
if (*src_value == NULL)
{
*src_value = log_sdsnewEmpty(strLen);
}
*src_value = log_sdscpylen(*src_value, value, strLen);
}
log_producer_config * create_log_producer_config()
{
log_producer_config* pConfig = (log_producer_config*)malloc(sizeof(log_producer_config));
memset(pConfig, 0, sizeof(log_producer_config));
_set_default_producer_config(pConfig);
return pConfig;
}
void destroy_log_producer_config(log_producer_config * pConfig)
{
if (pConfig->project != NULL)
{
log_sdsfree(pConfig->project);
}
if (pConfig->logstore != NULL)
{
log_sdsfree(pConfig->logstore);
}
if (pConfig->endpoint != NULL)
{
log_sdsfree(pConfig->endpoint);
}
if (pConfig->accessKey != NULL)
{
log_sdsfree(pConfig->accessKey);
}
if (pConfig->accessKeyId != NULL)
{
log_sdsfree(pConfig->accessKeyId);
}
if (pConfig->topic != NULL)
{
log_sdsfree(pConfig->topic);
}
if (pConfig->source != NULL)
{
log_sdsfree(pConfig->source);
}
if (pConfig->netInterface != NULL)
{
log_sdsfree(pConfig->netInterface);
}
if (pConfig->securityToken != NULL)
{
log_sdsfree(pConfig->securityToken);
}
if (pConfig->securityTokenLock != NULL)
{
ReleaseCriticalSection(pConfig->securityTokenLock);
}
if (pConfig->tagCount > 0 && pConfig->tags != NULL)
{
int i = 0;
for (; i < pConfig->tagCount; ++i)
{
log_sdsfree(pConfig->tags[i].key);
log_sdsfree(pConfig->tags[i].value);
}
free(pConfig->tags);
}
if (pConfig->persistentFilePath != NULL)
{
log_sdsfree(pConfig->persistentFilePath);
}
if (pConfig->mode == 1 && NULL != pConfig->shardKey) {
log_sdsfree(pConfig->shardKey);
}
free(pConfig);
}
#ifdef LOG_PRODUCER_DEBUG
void log_producer_config_print(log_producer_config * pConfig, FILE * file)
{
fprintf(file, "endpoint : %s\n", pConfig->endpoint);
fprintf(file,"project : %s\n", pConfig->project);
fprintf(file,"logstore : %s\n", pConfig->logstore);
fprintf(file,"accessKeyId : %s\n", pConfig->accessKeyId);
fprintf(file,"accessKey : %s\n", pConfig->accessKey);
fprintf(file,"configName : %s\n", pConfig->configName);
fprintf(file,"topic : %s\n", pConfig->topic);
fprintf(file,"logLevel : %d\n", pConfig->logLevel);
fprintf(file,"packageTimeoutInMS : %d\n", pConfig->packageTimeoutInMS);
fprintf(file, "logCountPerPackage : %d\n", pConfig->logCountPerPackage);
fprintf(file, "logBytesPerPackage : %d\n", pConfig->logBytesPerPackage);
fprintf(file, "maxBufferBytes : %d\n", pConfig->maxBufferBytes);
fprintf(file, "tags: \n");
int32_t i = 0;
for (i = 0; i < pConfig->tagCount; ++i)
{
fprintf(file, "tag key : %s, value : %s \n", pConfig->tags[i].key, pConfig->tags[i].value);
}
}
#endif
void log_producer_config_set_packet_timeout(log_producer_config * config, int32_t time_out_ms)
{
if (config == NULL || time_out_ms < 0)
{
return;
}
config->packageTimeoutInMS = time_out_ms;
}
void log_producer_config_set_packet_log_count(log_producer_config * config, int32_t log_count)
{
if (config == NULL || log_count < 0)
{
return;
}
config->logCountPerPackage = log_count;
}
void log_producer_config_set_packet_log_bytes(log_producer_config * config, int32_t log_bytes)
{
if (config == NULL || log_bytes < 0)
{
return;
}
config->logBytesPerPackage = log_bytes;
}
void log_producer_config_set_max_buffer_limit(log_producer_config * config, int64_t max_buffer_bytes)
{
if (config == NULL || max_buffer_bytes < 0)
{
return;
}
config->maxBufferBytes = max_buffer_bytes;
}
void log_producer_config_set_flush_interval(log_producer_config * config, int32_t flush_interval_in_ms)
{
if (NULL == config || flush_interval_in_ms < 500)
{
return;
}
config->flushIntervalInMS = flush_interval_in_ms;
}
void log_producer_config_set_log_queue_interval(log_producer_config * config, int32_t log_queue_in_ms)
{
if (NULL == config || log_queue_in_ms < 500)
{
return;
}
config->logQueuePopIntervalInMS = log_queue_in_ms;
}
void log_producer_config_set_send_thread_count(log_producer_config * config, int32_t thread_count)
{
if (config == NULL || thread_count < 0)
{
return;
}
config->sendThreadCount = thread_count;
}
void log_producer_config_set_net_interface(log_producer_config * config, const char * net_interface)
{
if (config == NULL || net_interface == NULL)
{
return;
}
_copy_config_string(net_interface, &config->netInterface);
}
void log_producer_config_set_connect_timeout_sec(log_producer_config * config, int32_t connect_timeout_sec)
{
if (config == NULL || connect_timeout_sec <= 0)
{
return;
}
config->connectTimeoutSec = connect_timeout_sec;
}
void log_producer_config_set_send_timeout_sec(log_producer_config * config, int32_t send_timeout_sec)
{
if (config == NULL || send_timeout_sec <= 0)
{
return;
}
config->sendTimeoutSec = send_timeout_sec;
}
void log_producer_config_set_destroy_flusher_wait_sec(log_producer_config * config, int32_t destroy_flusher_wait_sec)
{
if (config == NULL || destroy_flusher_wait_sec <= 0)
{
return;
}
config->destroyFlusherWaitTimeoutSec = destroy_flusher_wait_sec;
}
void log_producer_config_set_destroy_sender_wait_sec(log_producer_config * config, int32_t destroy_sender_wait_sec)
{
if (config == NULL || destroy_sender_wait_sec <= 0)
{
return;
}
config->destroySenderWaitTimeoutSec = destroy_sender_wait_sec;
}
void log_producer_config_set_compress_type(log_producer_config * config, int32_t compress_type)
{
if (config == NULL || compress_type < 0 || compress_type > 1)
{
return;
}
config->compressType = compress_type;
}
void log_producer_config_set_ntp_time_offset(log_producer_config * config, int32_t ntp_time_offset)
{
if (config == NULL)
{
return;
}
config->ntpTimeOffset = ntp_time_offset;
}
void log_producer_config_add_tag(log_producer_config * pConfig, const char * key, const char * value)
{
if(key == NULL || value == NULL)
{
return;
}
++pConfig->tagCount;
if (pConfig->tags == NULL || pConfig->tagCount > pConfig->tagAllocSize)
{
if(pConfig->tagAllocSize == 0)
{
pConfig->tagAllocSize = 4;
}
else
{
pConfig->tagAllocSize *= 2;
}
log_producer_config_tag * tagArray = (log_producer_config_tag *)malloc(sizeof(log_producer_config_tag) * pConfig->tagAllocSize);
if (pConfig->tags != NULL)
{
memcpy(tagArray, pConfig->tags, sizeof(log_producer_config_tag) * (pConfig->tagCount - 1));
free(pConfig->tags);
}
pConfig->tags = tagArray;
}
int32_t tagIndex = pConfig->tagCount - 1;
pConfig->tags[tagIndex].key = log_sdsnew(key);
pConfig->tags[tagIndex].value = log_sdsnew(value);
}
void log_producer_config_set_endpoint(log_producer_config * config, const char * endpoint)
{
if (!endpoint) {
_copy_config_string(NULL, &config->endpoint);
return;
}
if (strlen(endpoint) < 8) {
return;
}
if (strncmp(endpoint, "http://", 7) == 0)
{
endpoint += 7;
}
else if (strncmp(endpoint, "https://", 8) == 0)
{
config->using_https = 1;
endpoint += 8;
}
_copy_config_string(endpoint, &config->endpoint);
}
void log_producer_config_set_project(log_producer_config * config, const char * project)
{
_copy_config_string(project, &config->project);
}
void log_producer_config_set_logstore(log_producer_config * config, const char * logstore)
{
_copy_config_string(logstore, &config->logstore);
}
void log_producer_config_set_access_id(log_producer_config * config, const char * access_id)
{
_copy_config_string(access_id, &config->accessKeyId);
}
void log_producer_config_set_access_key(log_producer_config * config, const char * access_key)
{
_copy_config_string(access_key, &config->accessKey);
}
void log_producer_config_reset_security_token(log_producer_config * config, const char * access_id, const char * access_secret, const char * security_token)
{
if (config->securityTokenLock == NULL)
{
config->securityTokenLock = CreateCriticalSection();
}
CS_ENTER(config->securityTokenLock);
_copy_config_string(access_id, &config->accessKeyId);
_copy_config_string(access_secret, &config->accessKey);
_copy_config_string(security_token, &config->securityToken);
CS_LEAVE(config->securityTokenLock);
}
void log_producer_config_get_security(log_producer_config * config, char ** access_id, char ** access_secret, char ** security_token)
{
if (config->securityTokenLock == NULL)
{
_copy_config_string(config->accessKeyId, access_id);
_copy_config_string(config->accessKey, access_secret);
}
else
{
CS_ENTER(config->securityTokenLock);
_copy_config_string(config->accessKeyId, access_id);
_copy_config_string(config->accessKey, access_secret);
_copy_config_string(config->securityToken, security_token);
CS_LEAVE(config->securityTokenLock);
}
}
void log_producer_config_set_topic(log_producer_config * config, const char * topic)
{
_copy_config_string(topic, &config->topic);
}
void log_producer_config_set_source(log_producer_config * config, const char * source)
{
_copy_config_string(source, &config->source);
}
int log_producer_config_is_valid(log_producer_config * config)
{
if (config == NULL)
{
aos_error_log("invalid producer config");
return 0;
}
if (config->endpoint == NULL || config->project == NULL || config->logstore == NULL)
{
aos_error_log("invalid producer config destination params");
// return 0;
}
if (config->accessKey == NULL || config->accessKeyId == NULL)
{
aos_error_log("invalid producer config authority params");
// return 0;
}
if (config->packageTimeoutInMS < 0 || config->maxBufferBytes < 0 || config->logCountPerPackage < 0 || config->logBytesPerPackage < 0)
{
aos_error_log("invalid producer config log merge and buffer params");
return 0;
}
if (config->usePersistent)
{
if (config->persistentFilePath == NULL || config->maxPersistentFileCount <= 0 || config->maxPersistentLogCount <= 0 || config->maxPersistentFileSize <=0 )
{
aos_error_log("invalid producer persistent config params");
return 0;
}
}
return 1;
}
void log_producer_config_set_using_http(log_producer_config * config, int32_t using_https)
{
if (config == NULL || using_https < 0)
{
return;
}
config->using_https = using_https;
}
int log_producer_persistent_config_is_enabled(log_producer_config *config)
{
if (config == NULL)
{
aos_error_log("invalid producer config");
return 0;
}
if (config->usePersistent == 0)
{
return 0;
}
return 1;
}
void log_producer_config_set_persistent(log_producer_config *config,
int32_t persistent)
{
if (config == NULL)
return;
config->usePersistent = persistent;
}
void log_producer_config_set_persistent_file_path(log_producer_config *config,
const char *file_path)
{
if (config == NULL)
return;
_copy_config_string(file_path, &config->persistentFilePath);
}
void
log_producer_config_set_persistent_max_file_count(log_producer_config *config,
int32_t file_count)
{
if (config == NULL)
return;
config->maxPersistentFileCount = file_count;
}
void
log_producer_config_set_persistent_max_file_size(log_producer_config *config,
int32_t file_size)
{
if (config == NULL)
return;
config->maxPersistentFileSize = file_size;
}
void log_producer_config_set_persistent_force_flush(log_producer_config *config,
int32_t force)
{
if (config == NULL)
return;
config->forceFlushDisk = force;
}
void log_producer_config_set_persistent_max_log_count(log_producer_config *config,
int32_t max_log_count)
{
if (config == NULL)
return;
config->maxPersistentLogCount = max_log_count;
}
void log_producer_config_set_max_log_delay_time(log_producer_config *config,
int32_t max_log_delay_time)
{
if (config == NULL)
return;
config->maxLogDelayTime = max_log_delay_time;
}
void log_producer_config_set_drop_delay_log(log_producer_config *config,
int32_t drop_or_rewrite)
{
if (config == NULL)
return;
config->dropDelayLog = drop_or_rewrite;
}
void log_producer_config_set_drop_unauthorized_log(log_producer_config *config,
int32_t drop_or_not)
{
if (config == NULL)
return;
config->dropUnauthorizedLog = drop_or_not;
}
void log_producer_config_set_callback_from_sender_thread(log_producer_config * config,
int32_t callback_from_sender_thread)
{
if (NULL == config) {
return;
}
config->callbackFromSenderThread = callback_from_sender_thread;
}
LOG_EXPORT void log_producer_config_set_use_webtracking(log_producer_config * config, int32_t webtracking)
{
if (NULL == config)
{
return;
}
config->webTracking = webtracking;
}
void log_producer_config_set_mode(log_producer_config *config, int32_t mode) {
if (NULL == config)
{
return;
}
config->mode = mode;
}
void log_producer_config_set_shardkey(log_producer_config *config, const char *shardKey) {
if (NULL == config)
{
return;
}
_copy_config_string(shardKey, &config->shardKey);
}
\ No newline at end of file
//
// Created by ZhangCheng on 20/11/2017.
//
#include "log_producer_manager.h"
#include "inner_log.h"
#include "log_md5.h"
#include "log_sds.h"
#include <sys/time.h>
#ifdef __MACH__
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <mach/clock.h>
#include <mach/mach.h>
#endif
#define MAX_LOGGROUP_QUEUE_SIZE 1024
#define MIN_LOGGROUP_QUEUE_SIZE 32
#define MAX_MANAGER_FLUSH_COUNT 100 // 10MS * 100
#define MAX_SENDER_FLUSH_COUNT 100 // 10ms * 100
#ifdef WIN32
DWORD WINAPI log_producer_send_thread(LPVOID param);
#else
void * log_producer_send_thread(void * param);
#endif
void _generate_pack_id_timestamp(long *timestamp)
{
struct timespec ts;
#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, &ts);
#endif
*(timestamp) = ts.tv_nsec;
}
char * _get_pack_id(const char * configName, const char * ip)
{
long timestamp;
_generate_pack_id_timestamp(&timestamp);
char *prefix = (char *) malloc(100 * sizeof (char));
strcpy(prefix, configName);
sprintf(prefix, "%s%ld", prefix, timestamp);
unsigned char md5Buf[16];
log_mbedtls_md5((const unsigned char *)prefix, strlen(prefix), md5Buf);
int loop = 0;
char * val = (char *)malloc(sizeof(char) * 32);
memset(val, 0, sizeof(char) * 32);
for(; loop < 8; ++loop)
{
unsigned char a = ((md5Buf[loop])>>4) & 0xF, b = (md5Buf[loop]) & 0xF;
val[loop<<1] = a > 9 ? (a - 10 + 'A') : (a + '0');
val[(loop<<1)|1] = b > 9 ? (b - 10 + 'A') : (b + '0');
}
free(prefix);
return val;
}
void _try_flush_loggroup(log_producer_manager * producer_manager)
{
int32_t now_time = time(NULL);
CS_ENTER(producer_manager->lock);
if (producer_manager->builder != NULL && now_time - producer_manager->firstLogTime > producer_manager->producer_config->packageTimeoutInMS / 1000)
{
log_group_builder * builder = producer_manager->builder;
producer_manager->builder = NULL;
CS_LEAVE(producer_manager->lock);
size_t loggroup_size = builder->loggroup_size;
int rst = log_queue_push(producer_manager->loggroup_queue, builder);
aos_debug_log("try push loggroup to flusher, size : %d, status : %d", (int)loggroup_size, rst);
if (rst != 0)
{
aos_error_log("try push loggroup to flusher failed, force drop this log group, error code : %d", rst);
if (producer_manager->send_done_function != NULL)
{
producer_manager->send_done_function(producer_manager->producer_config->logstore, LOG_PRODUCER_DROP_ERROR, loggroup_size, 0,
NULL, "try push loggroup to flusher failed, force drop this log group", NULL, producer_manager->user_param);
}
log_group_destroy(builder);
}
else
{
producer_manager->totalBufferSize += loggroup_size;
COND_SIGNAL(producer_manager->triger_cond);
}
}
else
{
CS_LEAVE(producer_manager->lock);
}
}
#ifdef WIN32
DWORD WINAPI log_producer_flush_thread(LPVOID param)
#else
void * log_producer_flush_thread(void * param)
#endif
{
log_producer_manager * root_producer_manager = (log_producer_manager*)param;
int32_t interval = root_producer_manager->producer_config->flushIntervalInMS;
aos_info_log("[flusher] start run flusher thread, config : %s, flush interval: %d", root_producer_manager->producer_config->logstore, interval);
while (root_producer_manager->shutdown == 0)
{
CS_ENTER(root_producer_manager->lock);
COND_WAIT_TIME(root_producer_manager->triger_cond,
root_producer_manager->lock,
interval);
CS_LEAVE(root_producer_manager->lock);
// try read queue
do
{
// if send queue is full, skip pack and send data
if (root_producer_manager->send_param_queue_write - root_producer_manager->send_param_queue_read >= root_producer_manager->send_param_queue_size)
{
break;
}
void * data = log_queue_trypop(root_producer_manager->loggroup_queue);
if (data != NULL)
{
// process data
log_group_builder * builder = (log_group_builder*)data;
log_producer_manager * producer_manager = (log_producer_manager *)builder->private_value;
CS_ENTER(root_producer_manager->lock);
producer_manager->totalBufferSize -= builder->loggroup_size;
CS_LEAVE(root_producer_manager->lock);
log_producer_config * config = producer_manager->producer_config;
int i = 0;
for (i = 0; i < config->tagCount; ++i)
{
add_tag(builder, config->tags[i].key, strlen(config->tags[i].key), config->tags[i].value, strlen(config->tags[i].value));
}
if (config->topic != NULL)
{
add_topic(builder, config->topic, strlen(config->topic));
}
if (producer_manager->source != NULL)
{
add_source(builder, producer_manager->source, strlen(producer_manager->source));
}
if (producer_manager->pack_prefix != NULL)
{
add_pack_id(builder, producer_manager->pack_prefix, strlen(producer_manager->pack_prefix), producer_manager->pack_index++);
}
lz4_log_buf * lz4_buf = NULL;
// check compress type
if (config->compressType == 1)
{
lz4_buf = serialize_to_proto_buf_with_malloc_lz4(builder);
}
else
{
lz4_buf = serialize_to_proto_buf_with_malloc_no_lz4(builder);
}
if (lz4_buf == NULL)
{
aos_error_log("[flusher] serialize loggroup to proto buf with lz4 failed");
if (producer_manager->send_done_function)
{
producer_manager->send_done_function(producer_manager->producer_config->logstore, LOG_PRODUCER_DROP_ERROR, builder->loggroup_size, 0,
NULL, "serialize loggroup to proto buf with lz4 failed", NULL, producer_manager->user_param);
}
if (producer_manager->uuid_send_done_function != NULL)
{
producer_manager->uuid_send_done_function(producer_manager->producer_config->logstore,
LOG_PRODUCER_INVALID,
builder->loggroup_size,
0,
NULL,
"invalid send param, magic num not found",
NULL,
producer_manager->uuid_user_param,
builder->start_uuid,
builder->end_uuid);
}
}
else
{
CS_ENTER(root_producer_manager->lock);
producer_manager->totalBufferSize += lz4_buf->length;
CS_LEAVE(root_producer_manager->lock);
aos_debug_log("[flusher] push loggroup to sender, config %s, loggroup size %d, lz4 size %d, now buffer size %d",
config->logstore, (int)lz4_buf->raw_length, (int)lz4_buf->length, (int)producer_manager->totalBufferSize);
// if use multi thread, should change producer_manager->send_pool to NULL
//apr_pool_t * pool = config->sendThreadCount == 1 ? producer_manager->send_pool : NULL;
log_producer_send_param * send_param = create_log_producer_send_param(config, producer_manager, lz4_buf, builder);
root_producer_manager->send_param_queue[root_producer_manager->send_param_queue_write++ % root_producer_manager->send_param_queue_size] = send_param;
}
log_group_destroy(builder);
continue;
}
break;
}while(1);
// if no job, check now loggroup
_try_flush_loggroup(root_producer_manager);
// send data
if (root_producer_manager->send_threads != NULL)
{
// if send thread count > 0, we just push send_param to sender queue
while (root_producer_manager->send_param_queue_write > root_producer_manager->send_param_queue_read && !log_queue_isfull(root_producer_manager->sender_data_queue))
{
log_producer_send_param * send_param = root_producer_manager->send_param_queue[root_producer_manager->send_param_queue_read++ % root_producer_manager->send_param_queue_size];
// push always success
log_queue_push(root_producer_manager->sender_data_queue, send_param);
}
}
else if (root_producer_manager->send_param_queue_write > root_producer_manager->send_param_queue_read)
{
// if no sender thread, we send this packet out in flush thread
log_producer_send_param * send_param = root_producer_manager->send_param_queue[root_producer_manager->send_param_queue_read++ % root_producer_manager->send_param_queue_size];
log_producer_send_data(send_param);
}
}
aos_info_log("[flusher] exit flusher thread, config : %s", root_producer_manager->producer_config->logstore);
return 0;
}
log_producer_manager * create_log_producer_manager(log_producer_config * producer_config)
{
aos_debug_log("create log producer manager : %s", producer_config->logstore);
log_producer_manager * producer_manager = (log_producer_manager *)malloc(sizeof(log_producer_manager));
memset(producer_manager, 0, sizeof(log_producer_manager));
producer_manager->producer_config = producer_config;
int32_t base_queue_size = producer_config->maxBufferBytes / (producer_config->logBytesPerPackage + 1) + 10;
if (base_queue_size < MIN_LOGGROUP_QUEUE_SIZE)
{
base_queue_size = MIN_LOGGROUP_QUEUE_SIZE;
}
else if (base_queue_size > MAX_LOGGROUP_QUEUE_SIZE)
{
base_queue_size = MAX_LOGGROUP_QUEUE_SIZE;
}
producer_manager->loggroup_queue = log_queue_create(base_queue_size);
producer_manager->send_param_queue_size = base_queue_size * 2;
producer_manager->send_param_queue = malloc(sizeof(log_producer_send_param*) * producer_manager->send_param_queue_size);
if (producer_config->sendThreadCount > 0)
{
producer_manager->multi_thread_send_count = 0;
producer_manager->send_threads = (THREAD *)malloc(sizeof(THREAD) * producer_config->sendThreadCount);
producer_manager->sender_data_queue = log_queue_create(base_queue_size * 2);
int32_t threadId = 0;
for (; threadId < producer_manager->producer_config->sendThreadCount; ++threadId)
{
THREAD_INIT(producer_manager->send_threads[threadId], log_producer_send_thread, producer_manager);
}
}
producer_manager->triger_cond = CreateCond();
producer_manager->lock = CreateCriticalSection();
THREAD_INIT(producer_manager->flush_thread, log_producer_flush_thread, producer_manager);
if (producer_config->source != NULL)
{
producer_manager->source = log_sdsnew(producer_config->source);
}
else
{
producer_manager->source = log_sdsnew("undefined");
}
if (producer_config->logstore != NULL)
{
producer_manager->pack_prefix = _get_pack_id(producer_config->logstore, producer_manager->source);
}
else
{
producer_manager->pack_prefix = _get_pack_id("default_logstore", producer_manager->source);
}
if (producer_manager->pack_prefix == NULL)
{
producer_manager->pack_prefix = (char *)malloc(32);
srand(time(NULL));
int i = 0;
for (i = 0; i < 16; ++i)
{
producer_manager->pack_prefix[i] = arc4random() % 10 + '0';
}
producer_manager->pack_prefix[i] = '\0';
}
return producer_manager;
}
void _push_last_loggroup(log_producer_manager * manager)
{
CS_ENTER(manager->lock);
log_group_builder * builder = manager->builder;
manager->builder = NULL;
if (builder != NULL)
{
size_t loggroup_size = builder->loggroup_size;
aos_debug_log("try push loggroup to flusher, size : %d, log size %d", (int)builder->loggroup_size, (int)builder->grp->logs.now_buffer_len);
int32_t status = log_queue_push(manager->loggroup_queue, builder);
if (status != 0)
{
aos_error_log("try push loggroup to flusher failed, force drop this log group, error code : %d", status);
log_group_destroy(builder);
}
else
{
manager->totalBufferSize += loggroup_size;
COND_SIGNAL(manager->triger_cond);
}
}
CS_LEAVE(manager->lock);
}
void destroy_log_producer_manager(log_producer_manager * manager)
{
// when destroy instance, flush last loggroup
_push_last_loggroup(manager);
aos_info_log("flush out producer loggroup begin");
int32_t total_wait_count = manager->producer_config->destroyFlusherWaitTimeoutSec > 0 ? manager->producer_config->destroyFlusherWaitTimeoutSec * 100 : MAX_MANAGER_FLUSH_COUNT;
total_wait_count += manager->producer_config->destroySenderWaitTimeoutSec > 0 ? manager->producer_config->destroySenderWaitTimeoutSec * 100 : MAX_SENDER_FLUSH_COUNT;
#ifdef WIN32
Sleep(10);
#else
usleep(10 * 1000);
#endif
int waitCount = 0;
while (log_queue_size(manager->loggroup_queue) > 0 ||
manager->send_param_queue_write - manager->send_param_queue_read > 0 ||
(manager->sender_data_queue != NULL && log_queue_size(manager->sender_data_queue) > 0) )
{
#ifdef WIN32
Sleep(10);
#else
usleep(10 * 1000);
#endif
if (++waitCount == total_wait_count)
{
break;
}
}
if (waitCount == total_wait_count)
{
aos_error_log("try flush out producer loggroup error, force exit, now loggroup %d", (int)(log_queue_size(manager->loggroup_queue)));
}
else
{
aos_info_log("flush out producer loggroup success");
}
manager->shutdown = 1;
// destroy root resources
COND_SIGNAL(manager->triger_cond);
aos_info_log("join flush thread begin");
if (manager->flush_thread) {
THREAD_JOIN(manager->flush_thread);
}
aos_info_log("join flush thread success");
if (manager->send_threads != NULL)
{
aos_info_log("join sender thread pool begin");
int32_t threadId = 0;
for (; threadId < manager->producer_config->sendThreadCount; ++threadId)
{
if (manager->send_threads[threadId]) {
THREAD_JOIN(manager->send_threads[threadId]);
}
}
free(manager->send_threads);
aos_info_log("join sender thread pool success");
}
DeleteCond(manager->triger_cond);
log_queue_destroy(manager->loggroup_queue);
if (manager->sender_data_queue != NULL)
{
aos_info_log("flush out sender queue begin");
while (log_queue_size(manager->sender_data_queue) > 0)
{
void * send_param = log_queue_trypop(manager->sender_data_queue);
if (send_param != NULL)
{
log_producer_send_fun(send_param);
}
}
log_queue_destroy(manager->sender_data_queue);
aos_info_log("flush out sender queue success");
}
ReleaseCriticalSection(manager->lock);
if (manager->pack_prefix != NULL)
{
free(manager->pack_prefix);
}
if (manager->send_param_queue != NULL)
{
free(manager->send_param_queue);
}
log_sdsfree(manager->source);
free(manager);
}
#define LOG_PRODUCER_MANAGER_ADD_LOG_BEGIN if (producer_manager->totalBufferSize > producer_manager->producer_config->maxBufferBytes) \
{ \
return LOG_PRODUCER_DROP_ERROR; \
} \
CS_ENTER(producer_manager->lock); \
if (producer_manager->builder == NULL) \
{ \
if (log_queue_isfull(producer_manager->loggroup_queue)) \
{ \
CS_LEAVE(producer_manager->lock); \
return LOG_PRODUCER_DROP_ERROR; \
} \
int32_t now_time = time(NULL); \
producer_manager->builder = log_group_create(); \
producer_manager->builder->start_uuid = uuid; \
producer_manager->firstLogTime = now_time; \
producer_manager->builder->private_value = producer_manager; \
}
#define LOG_PRODUCER_MANAGER_ADD_LOG_END log_group_builder * builder = producer_manager->builder; \
builder->end_uuid = uuid; \
int32_t nowTime = time(NULL); \
if (flush == 0 && producer_manager->builder->loggroup_size < producer_manager->producer_config->logBytesPerPackage && nowTime - producer_manager->firstLogTime < producer_manager->producer_config->packageTimeoutInMS / 1000 && producer_manager->builder->grp->n_logs < producer_manager->producer_config->logCountPerPackage) \
{ \
CS_LEAVE(producer_manager->lock); \
return LOG_PRODUCER_OK; \
} \
int ret = LOG_PRODUCER_OK; \
producer_manager->builder = NULL; \
size_t loggroup_size = builder->loggroup_size; \
aos_debug_log("try push loggroup to flusher, size : %d, log count %d", (int)builder->loggroup_size, (int)builder->grp->n_logs); \
int status = log_queue_push(producer_manager->loggroup_queue, builder); \
if (status != 0) \
{ \
aos_error_log("try push loggroup to flusher failed, force drop this log group, error code : %d", status); \
ret = LOG_PRODUCER_DROP_ERROR; \
log_group_destroy(builder); \
} \
else \
{ \
producer_manager->totalBufferSize += loggroup_size; \
COND_SIGNAL(producer_manager->triger_cond); \
} \
CS_LEAVE(producer_manager->lock); \
return ret;
log_producer_result log_producer_manager_add_log(log_producer_manager * producer_manager, int32_t pair_count, char ** keys, size_t * key_lens, char ** values, size_t * val_lens, int flush, int64_t uuid)
{
// if (producer_manager->totalBufferSize > producer_manager->producer_config->maxBufferBytes)
// {
// return LOG_PRODUCER_DROP_ERROR;
// }
// CS_ENTER(producer_manager->lock);
// if (producer_manager->builder == NULL)
// {
// // if queue is full, return drop error
// if (log_queue_isfull(producer_manager->loggroup_queue))
// {
// CS_LEAVE(producer_manager->lock);
// return LOG_PRODUCER_DROP_ERROR;
// }
// int32_t now_time = time(NULL);
//
// producer_manager->builder = log_group_create();
// producer_manager->builder->start_uuid = uuid;
// producer_manager->firstLogTime = now_time;
// producer_manager->builder->private_value = producer_manager;
// }
LOG_PRODUCER_MANAGER_ADD_LOG_BEGIN;
add_log_full(producer_manager->builder, (uint32_t)time(NULL), pair_count, keys, key_lens, values, val_lens);
LOG_PRODUCER_MANAGER_ADD_LOG_END;
// log_group_builder * builder = producer_manager->builder;
// builder->end_uuid = uuid;
//
// int32_t nowTime = time(NULL);
// if (flush == 0 && producer_manager->builder->loggroup_size < producer_manager->producer_config->logBytesPerPackage &&
// nowTime - producer_manager->firstLogTime < producer_manager->producer_config->packageTimeoutInMS / 1000 &&
// producer_manager->builder->grp->n_logs < producer_manager->producer_config->logCountPerPackage)
// {
// CS_LEAVE(producer_manager->lock);
// return LOG_PRODUCER_OK;
// }
//
// int ret = LOG_PRODUCER_OK;
// producer_manager->builder = NULL;
// size_t loggroup_size = builder->loggroup_size;
// aos_debug_log("try push loggroup to flusher, size : %d, log count %d", (int)builder->loggroup_size, (int)builder->grp->n_logs);
// int status = log_queue_push(producer_manager->loggroup_queue, builder);
// if (status != 0)
// {
// aos_error_log("try push loggroup to flusher failed, force drop this log group, error code : %d", status);
// ret = LOG_PRODUCER_DROP_ERROR;
// log_group_destroy(builder);
// }
// else
// {
// producer_manager->totalBufferSize += loggroup_size;
// COND_SIGNAL(producer_manager->triger_cond);
// }
//
// CS_LEAVE(producer_manager->lock);
//
// return ret;
}
log_producer_result log_producer_manager_send_raw_buffer(log_producer_manager * producer_manager, size_t log_bytes, size_t compressed_bytes, const unsigned char * raw_buffer)
{
// pack lz4_log_buf
lz4_log_buf* lz4_buf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + compressed_bytes);
lz4_buf->length = compressed_bytes;
lz4_buf->raw_length = log_bytes;
memcpy(lz4_buf->data, raw_buffer, compressed_bytes);
log_producer_send_param * send_param = create_log_producer_send_param(producer_manager->producer_config, producer_manager, lz4_buf, NULL);
CS_ENTER(producer_manager->lock);
producer_manager->totalBufferSize += lz4_buf->length;
CS_LEAVE(producer_manager->lock);
return log_producer_send_data(send_param);
}
log_producer_result
log_producer_manager_add_log_raw(log_producer_manager *producer_manager,
char *logBuf, size_t logSize, int flush,
int64_t uuid)
{
LOG_PRODUCER_MANAGER_ADD_LOG_BEGIN;
int drop = 0;
if (producer_manager->producer_config->maxLogDelayTime > 0)
{
uint32_t nowTimeUint32 = time(NULL);
uint32_t logTime = get_log_time(logBuf, logSize);
// reset to now time
if (logTime < nowTimeUint32 && nowTimeUint32 - logTime > producer_manager->producer_config->maxLogDelayTime)
{
if (producer_manager->producer_config->dropDelayLog == 0)
{
aos_error_log("fix log time because of too old log time, log time : %d, offset : %d", logTime, nowTimeUint32 - logTime);
fix_log_time(logBuf, logSize, nowTimeUint32);
}
else
{
aos_error_log("drop log because of too old log time, log time : %d, offset : %d", logTime, nowTimeUint32 - logTime);
drop = 1;
}
}
}
if (drop == 0)
{
add_log_raw(producer_manager->builder, logBuf, logSize);
}
LOG_PRODUCER_MANAGER_ADD_LOG_END;
}
log_producer_result
log_producer_manager_add_log_with_array(log_producer_manager *producer_manager,
uint32_t logTime, size_t logItemCount,
const char *logItemsBuf,
const uint32_t *logItemsSize, int flush,
int64_t uuid)
{
LOG_PRODUCER_MANAGER_ADD_LOG_BEGIN;
int drop = 0;
if (producer_manager->producer_config->maxLogDelayTime > 0)
{
uint32_t nowTimeUint32 = time(NULL);
// reset to now time
if (logTime < nowTimeUint32 && nowTimeUint32 - logTime >
producer_manager->producer_config->maxLogDelayTime)
{
if (producer_manager->producer_config->dropDelayLog == 0)
{
logTime = nowTimeUint32;
aos_error_log("fix log time because of too old log time, log time : %d, offset : %d", logTime, nowTimeUint32 - logTime);
}
else
{
aos_error_log("drop log because of too old log time, log time : %d, offset : %d", logTime, nowTimeUint32 - logTime);
drop = 1;
}
}
}
if (drop == 0)
{
add_log_full_v2(producer_manager->builder, logTime, logItemCount, logItemsBuf, logItemsSize);
}
LOG_PRODUCER_MANAGER_ADD_LOG_END;
}
log_producer_result
log_producer_manager_add_log_int32(log_producer_manager *producer_manager,
int32_t pair_count, char **keys,
int32_t *key_lens, char **values,
int32_t *val_lens, int flush, int64_t uuid)
{
LOG_PRODUCER_MANAGER_ADD_LOG_BEGIN;
add_log_full_int32(producer_manager->builder, (uint32_t)time(NULL), pair_count, keys, key_lens, values, val_lens);
LOG_PRODUCER_MANAGER_ADD_LOG_END;
}
//
// Created by ZhangCheng on 20/11/2017.
//
#ifndef LOG_C_SDK_LOG_PRODUCER_MANAGER_H
#define LOG_C_SDK_LOG_PRODUCER_MANAGER_H
#include "log_define.h"
LOG_CPP_START
#include "log_producer_config.h"
#include "log_producer_sender.h"
#include "log_builder.h"
#include "log_queue.h"
#include "log_multi_thread.h"
typedef struct _log_producer_manager
{
log_producer_config * producer_config;
volatile uint32_t shutdown;
volatile uint32_t networkRecover;
volatile uint32_t totalBufferSize;
log_queue * loggroup_queue;
log_queue * sender_data_queue;
THREAD * send_threads;
THREAD flush_thread;
CRITICALSECTION lock;
COND triger_cond;
log_group_builder * builder;
int32_t firstLogTime;
char * source;
char * pack_prefix;
volatile uint32_t pack_index;
on_log_producer_send_done_function send_done_function;
void *user_param;
log_producer_send_param ** send_param_queue;
uint64_t send_param_queue_size;
volatile uint64_t send_param_queue_read;
volatile uint64_t send_param_queue_write;
ATOMICINT multi_thread_send_count;
// used for disk saver
on_log_producer_send_done_uuid_function uuid_send_done_function;
void * uuid_user_param;
}log_producer_manager;
extern log_producer_manager * create_log_producer_manager(log_producer_config * producer_config);
extern void destroy_log_producer_manager(log_producer_manager * manager);
extern log_producer_result log_producer_manager_add_log(log_producer_manager * producer_manager,
int32_t pair_count,
char ** keys,
size_t * key_lens,
char ** values,
size_t * val_lens,
int flush,
int64_t uuid);
extern log_producer_result log_producer_manager_add_log_int32(log_producer_manager * producer_manager,
int32_t pair_count,
char ** keys,
int32_t * key_lens,
char ** values,
int32_t * val_lens,
int flush,
int64_t uuid);
extern log_producer_result log_producer_manager_add_log_raw(log_producer_manager * producer_manager,
char * logBuf,
size_t logSize,
int flush,
int64_t uuid);
extern log_producer_result log_producer_manager_add_log_with_array(log_producer_manager * producer_manager,
uint32_t logTime,
size_t logItemCount,
const char * logItemsBuf,
const uint32_t * logItemsSize,
int flush,
int64_t uuid);
extern log_producer_result log_producer_manager_send_raw_buffer(log_producer_manager * producer_manager, size_t log_bytes, size_t compressed_bytes, const unsigned char * raw_buffer);
LOG_CPP_END
#endif //LOG_C_SDK_LOG_PRODUCER_MANAGER_H
//
// Created by ZhangCheng on 20/11/2017.
//
#include "log_producer_sender.h"
#include "log_api.h"
#include "log_producer_manager.h"
#include "inner_log.h"
#include "log_lz4.h"
#include "log_sds.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
unsigned int LOG_GET_TIME();
const char* LOGE_SERVER_BUSY = "ServerBusy";
const char* LOGE_INTERNAL_SERVER_ERROR = "InternalServerError";
const char* LOGE_UNAUTHORIZED = "Unauthorized";
const char* LOGE_WRITE_QUOTA_EXCEED = "WriteQuotaExceed";
const char* LOGE_SHARD_WRITE_QUOTA_EXCEED = "ShardWriteQuotaExceed";
const char* LOGE_TIME_EXPIRED = "RequestTimeExpired";
#define SEND_SLEEP_INTERVAL_MS 100
#define MAX_NETWORK_ERROR_SLEEP_MS 3000
#define BASE_NETWORK_ERROR_SLEEP_MS 300
#define MAX_QUOTA_ERROR_SLEEP_MS 10000
#define BASE_QUOTA_ERROR_SLEEP_MS 500
#define MAX_PARAMETER_ERROR_SLEEP_MS 3000
#define BASE_PARAMETER_ERROR_SLEEP_MS 300
#define INVALID_TIME_TRY_INTERVAL 500
#define DROP_FAIL_DATA_TIME_SECOND 86400
#define SEND_TIME_INVALID_FIX
typedef struct _send_error_info
{
log_producer_send_result last_send_error;
int32_t last_sleep_ms;
int32_t first_error_time;
}send_error_info;
int32_t log_producer_on_send_done(log_producer_send_param * send_param, post_log_result * result, send_error_info * error_info);
#ifdef SEND_TIME_INVALID_FIX
void pb_to_webtracking(lz4_log_buf *lz4_buf, lz4_log_buf **new_lz4_buf)
{
aos_debug_log("[sender] pb_to_webtracking start.");
char * buf = (char *)malloc(lz4_buf->raw_length);
if (LOG_LZ4_decompress_safe((const char* )lz4_buf->data, buf, lz4_buf->length, lz4_buf->raw_length) <= 0)
{
free(buf);
aos_fatal_log("[sender] pb_to_webtracking, LOG_LZ4_decompress_safe error");
return;
}
size_t len = serialize_pb_buffer_to_webtracking(buf, lz4_buf->raw_length, &buf);
int compress_bound = LOG_LZ4_compressBound(len);
char *compress_data = (char *)malloc(compress_bound);
int compressed_size = LOG_LZ4_compress_default((char *)buf, compress_data, len, compress_bound);
if(compressed_size <= 0)
{
aos_fatal_log("[sender] pb_to_webtracking, LOG_LZ4_compress_default error");
free(buf);
free(compress_data);
return;
}
*new_lz4_buf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + compressed_size);
(*new_lz4_buf)->length = compressed_size;
(*new_lz4_buf)->raw_length = len;
memcpy((*new_lz4_buf)->data, compress_data, compressed_size);
free(buf);
free(compress_data);
aos_debug_log("[sender] pb_to_webtracking end.");
}
void _rebuild_time(lz4_log_buf * lz4_buf, lz4_log_buf ** new_lz4_buf)
{
aos_debug_log("[sender] rebuild log.");
char * buf = (char *)malloc(lz4_buf->raw_length);
if (LOG_LZ4_decompress_safe((const char* )lz4_buf->data, buf, lz4_buf->length, lz4_buf->raw_length) <= 0)
{
free(buf);
aos_fatal_log("[sender] LOG_LZ4_decompress_safe error");
return;
}
uint32_t nowTime = LOG_GET_TIME();
fix_log_group_time(buf, lz4_buf->raw_length, nowTime);
int compress_bound = LOG_LZ4_compressBound(lz4_buf->raw_length);
char *compress_data = (char *)malloc(compress_bound);
int compressed_size = LOG_LZ4_compress_default((char *)buf, compress_data, lz4_buf->raw_length, compress_bound);
if(compressed_size <= 0)
{
aos_fatal_log("[sender] LOG_LZ4_compress_default error");
free(buf);
free(compress_data);
return;
}
*new_lz4_buf = (lz4_log_buf*)malloc(sizeof(lz4_log_buf) + compressed_size);
(*new_lz4_buf)->length = compressed_size;
(*new_lz4_buf)->raw_length = lz4_buf->raw_length;
memcpy((*new_lz4_buf)->data, compress_data, compressed_size);
free(buf);
free(compress_data);
return;
}
#endif
#ifdef WIN32
DWORD WINAPI log_producer_send_thread(LPVOID param)
#else
void * log_producer_send_thread(void * param)
#endif
{
log_producer_manager * producer_manager = (log_producer_manager *)param;
if (producer_manager->sender_data_queue == NULL)
{
return 0;
}
int32_t interval = producer_manager->producer_config->logQueuePopIntervalInMS;
while (!producer_manager->shutdown)
{
// change from 30ms to 1000s, reduce wake up when app switch to back
void * send_param = log_queue_pop(producer_manager->sender_data_queue, interval);
if (send_param != NULL)
{
ATOMICINT_INC(&producer_manager->multi_thread_send_count);
log_producer_send_fun(send_param);
ATOMICINT_DEC(&producer_manager->multi_thread_send_count);
}
}
return 0;
}
void * log_producer_send_fun(void * param)
{
aos_info_log("[sender] start send log data.");
log_producer_send_param * send_param = (log_producer_send_param *)param;
if (send_param->magic_num != LOG_PRODUCER_SEND_MAGIC_NUM)
{
aos_fatal_log("[sender] invalid send param, magic num not found, num 0x%x", send_param->magic_num);
log_producer_manager * producer_manager = (log_producer_manager *)send_param->producer_manager;
if (producer_manager && producer_manager->send_done_function != NULL)
{
producer_manager->send_done_function(producer_manager->producer_config->logstore, LOG_PRODUCER_INVALID, send_param->log_buf->raw_length, send_param->log_buf->length,
NULL, "invalid send param, magic num not found", send_param->log_buf->data, producer_manager->user_param);
}
if (producer_manager && producer_manager->uuid_send_done_function != NULL)
{
producer_manager->uuid_send_done_function(producer_manager->producer_config->logstore,
LOG_PRODUCER_INVALID,
send_param->log_buf->raw_length,
send_param->log_buf->length,
NULL,
"invalid send param, magic num not found",
send_param->log_buf->data,
producer_manager->uuid_user_param,
send_param->start_uuid,
send_param->end_uuid);
}
return NULL;
}
log_producer_config * config = send_param->producer_config;
send_error_info error_info;
memset(&error_info, 0, sizeof(error_info));
log_producer_manager * producer_manager = (log_producer_manager *)send_param->producer_manager;
do
{
if (producer_manager->shutdown)
{
aos_info_log("[sender] send fail but shutdown signal received, force exit");
if (producer_manager->send_done_function != NULL)
{
producer_manager->send_done_function(producer_manager->producer_config->logstore, LOG_PRODUCER_SEND_EXIT_BUFFERED, send_param->log_buf->raw_length, send_param->log_buf->length,
NULL, "producer is being destroyed, producer has no time to send this buffer out", send_param->log_buf->data, producer_manager->user_param);
}
break;
}
lz4_log_buf * send_buf = send_param->log_buf;
#ifdef SEND_TIME_INVALID_FIX
uint32_t nowTime = LOG_GET_TIME();
if (nowTime - send_param->builder_time > 600 || send_param->builder_time - nowTime > 600 || error_info.last_send_error == LOG_SEND_TIME_ERROR)
{
_rebuild_time(send_param->log_buf, &send_buf);
send_param->builder_time = nowTime;
}
#endif
log_post_option option;
memset(&option, 0, sizeof(log_post_option));
option.connect_timeout = config->connectTimeoutSec;
option.operation_timeout = config->sendTimeoutSec;
option.interface = config->netInterface;
option.compress_type = config->compressType;
option.using_https = config->using_https;
option.ntp_time_offset = config->ntpTimeOffset;
option.mode = config->mode;
option.shardKey = config->shardKey;
post_log_result * rst;
if (config->webTracking)
{
pb_to_webtracking(send_param->log_buf, &send_buf);
rst = post_logs_from_lz4buf_webtracking(config->endpoint, config->project, config->logstore, send_buf, &option);
}
else
{
log_sds accessKeyId = NULL;
log_sds accessKey = NULL;
log_sds stsToken = NULL;
log_producer_config_get_security(config, &accessKeyId, &accessKey, &stsToken);
rst = post_logs_from_lz4buf_with_config(config, config->endpoint, config->project, config->logstore, accessKeyId, accessKey, stsToken, send_buf, &option);
log_sdsfree(accessKeyId);
log_sdsfree(accessKey);
log_sdsfree(stsToken);
}
aos_debug_log("[sender] send data result: statusCode: %d, errorMessage: %s, requestID :%s",
rst->statusCode, rst->errorMessage, rst->requestID);
int32_t sleepMs = log_producer_on_send_done(send_param, rst, &error_info);
post_log_result_destroy(rst);
// tmp buffer, free
if (send_buf != send_param->log_buf)
{
free(send_buf);
}
if (sleepMs <= 0)
{
break;
}
int i =0;
for (i = 0; i < sleepMs; i += SEND_SLEEP_INTERVAL_MS)
{
#ifdef WIN32
Sleep(SEND_SLEEP_INTERVAL_MS);
#else
usleep(SEND_SLEEP_INTERVAL_MS * 1000);
#endif
if (producer_manager->shutdown || producer_manager->networkRecover)
{
break;
}
}
if (producer_manager->networkRecover)
{
producer_manager->networkRecover = 0;
}
}while(1);
// at last, free all buffer
free_lz4_log_buf(send_param->log_buf);
free(send_param);
return NULL;
}
int32_t log_producer_on_send_done(log_producer_send_param * send_param, post_log_result * result, send_error_info * error_info)
{
log_producer_send_result send_result = AosStatusToResult(result);
log_producer_manager * producer_manager = (log_producer_manager *)send_param->producer_manager;
if (producer_manager->send_done_function != NULL)
{
log_producer_result callback_result = send_result == LOG_SEND_OK ?
LOG_PRODUCER_OK :
(LOG_PRODUCER_SEND_NETWORK_ERROR + send_result - LOG_SEND_NETWORK_ERROR);
producer_manager->send_done_function(producer_manager->producer_config->logstore, callback_result, send_param->log_buf->raw_length, send_param->log_buf->length, result->requestID, result->errorMessage, send_param->log_buf->data, producer_manager->user_param);
}
if (producer_manager->uuid_send_done_function != NULL)
{
log_producer_result callback_result = send_result == LOG_SEND_OK ?
LOG_PRODUCER_OK :
(LOG_PRODUCER_SEND_NETWORK_ERROR + send_result - LOG_SEND_NETWORK_ERROR);
producer_manager->uuid_send_done_function(producer_manager->producer_config->logstore,
callback_result,
send_param->log_buf->raw_length,
send_param->log_buf->length,
result->requestID,
result->errorMessage,
send_param->log_buf->data,
producer_manager->uuid_user_param,
send_param->start_uuid,
send_param->end_uuid);
}
if (send_result == LOG_SEND_UNAUTHORIZED)
{
// if do not drop unauthorized log, change the code to LOG_PRODUCER_SEND_NETWORK_ERROR
if (producer_manager->producer_config->dropUnauthorizedLog == 0)
{
send_result = LOG_PRODUCER_SEND_NETWORK_ERROR;
}
}
switch (send_result)
{
case LOG_SEND_OK:
break;
case LOG_SEND_TIME_ERROR:
// if no this marco, drop data
#ifdef SEND_TIME_INVALID_FIX
error_info->last_send_error = LOG_SEND_TIME_ERROR;
error_info->last_sleep_ms = INVALID_TIME_TRY_INTERVAL;
return error_info->last_sleep_ms;
#else
break;
#endif
case LOG_SEND_QUOTA_EXCEED:
if (error_info->last_send_error != LOG_SEND_QUOTA_EXCEED)
{
error_info->last_send_error = LOG_SEND_QUOTA_EXCEED;
error_info->last_sleep_ms = BASE_QUOTA_ERROR_SLEEP_MS;
error_info->first_error_time = time(NULL);
}
else
{
if (error_info->last_sleep_ms < MAX_QUOTA_ERROR_SLEEP_MS)
{
error_info->last_sleep_ms *= 2;
}
if (time(NULL) - error_info->first_error_time > DROP_FAIL_DATA_TIME_SECOND)
{
break;
}
}
aos_warn_log("[sender] send quota error, project : %s, logstore : %s, buffer len : %d, raw len : %d, code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
result->statusCode,
result->errorMessage);
return error_info->last_sleep_ms;
case LOG_SEND_SERVER_ERROR :
case LOG_SEND_NETWORK_ERROR:
if (error_info->last_send_error != LOG_SEND_NETWORK_ERROR)
{
error_info->last_send_error = LOG_SEND_NETWORK_ERROR;
error_info->last_sleep_ms = BASE_NETWORK_ERROR_SLEEP_MS;
error_info->first_error_time = time(NULL);
}
else
{
if (error_info->last_sleep_ms < MAX_NETWORK_ERROR_SLEEP_MS)
{
error_info->last_sleep_ms *= 2;
}
if (time(NULL) - error_info->first_error_time > DROP_FAIL_DATA_TIME_SECOND)
{
break;
}
}
aos_warn_log("[sender] send network error, project : %s, logstore : %s, buffer len : %d, raw len : %d, code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
result->statusCode,
result->errorMessage);
return error_info->last_sleep_ms;
case LOG_SEND_PARAMETERS_ERROR:
if (error_info->last_send_error != LOG_SEND_PARAMETERS_ERROR)
{
error_info->last_send_error = LOG_SEND_PARAMETERS_ERROR;
error_info->last_sleep_ms = BASE_PARAMETER_ERROR_SLEEP_MS;
error_info->first_error_time = time(NULL);
}
else
{
if (error_info->last_sleep_ms < MAX_PARAMETER_ERROR_SLEEP_MS)
{
error_info->last_sleep_ms *= 2;
}
if (time(NULL) - error_info->first_error_time > DROP_FAIL_DATA_TIME_SECOND)
{
break;
}
}
aos_warn_log("[sender] send parameters error, project : %s, logstore : %s, buffer len : %d, raw len : %d, code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
result->statusCode,
result->errorMessage);
return error_info->last_sleep_ms;
default:
// discard data
break;
}
// always try once when discard error
if (LOG_SEND_OK != send_result && error_info->last_send_error == 0)
{
error_info->last_send_error = LOG_SEND_DISCARD_ERROR;
error_info->last_sleep_ms = BASE_NETWORK_ERROR_SLEEP_MS;
error_info->first_error_time = time(NULL);
aos_warn_log("[sender] send fail, the error is discard data, retry once, project : %s, logstore : %s, buffer len : %d, raw len : %d, total buffer : %d,code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
(int)producer_manager->totalBufferSize,
result->statusCode,
result->errorMessage);
return BASE_NETWORK_ERROR_SLEEP_MS;
}
CS_ENTER(producer_manager->lock);
producer_manager->totalBufferSize -= send_param->log_buf->length;
CS_LEAVE(producer_manager->lock);
if (send_result == LOG_SEND_OK)
{
aos_debug_log("[sender] send success, project : %s, logstore : %s, buffer len : %d, raw len : %d, total buffer : %d,code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
(int)producer_manager->totalBufferSize,
result->statusCode,
result->errorMessage);
}
else
{
aos_warn_log("[sender] send fail, discard data, project : %s, logstore : %s, buffer len : %d, raw len : %d, total buffer : %d,code : %d, error msg : %s",
send_param->producer_config->project,
send_param->producer_config->logstore,
(int)send_param->log_buf->length,
(int)send_param->log_buf->raw_length,
(int)producer_manager->totalBufferSize,
result->statusCode,
result->errorMessage);
if (producer_manager->send_done_function != NULL)
{
producer_manager->send_done_function(producer_manager->producer_config->logstore,
LOG_PRODUCER_DROP_ERROR,
send_param->log_buf->raw_length,
send_param->log_buf->length,
result->requestID,
result->errorMessage,
send_param->log_buf->data,
producer_manager->user_param);
}
if (producer_manager->uuid_send_done_function != NULL)
{
producer_manager->uuid_send_done_function(producer_manager->producer_config->logstore,
LOG_PRODUCER_DROP_ERROR,
send_param->log_buf->raw_length,
send_param->log_buf->length,
result->requestID,
result->errorMessage,
send_param->log_buf->data,
producer_manager->uuid_user_param,
send_param->start_uuid,
send_param->end_uuid);
}
}
return 0;
}
log_producer_result log_producer_send_data(log_producer_send_param * send_param)
{
log_producer_send_fun(send_param);
return LOG_PRODUCER_OK;
}
log_producer_send_result AosStatusToResult(post_log_result * result)
{
if (result->statusCode / 100 == 2)
{
return LOG_SEND_OK;
}
if (result->statusCode <= 0)
{
return LOG_SEND_NETWORK_ERROR;
}
if (result->statusCode == 405)
{
return LOG_SEND_PARAMETERS_ERROR;
}
if (result->statusCode == 403)
{
return LOG_SEND_QUOTA_EXCEED;
}
if (result->statusCode == 401 || result->statusCode == 404)
{
return LOG_SEND_UNAUTHORIZED;
}
if (result->statusCode >= 500 || result->requestID == NULL)
{
return LOG_SEND_SERVER_ERROR;
}
if (result->errorMessage != NULL && strstr(result->errorMessage, LOGE_TIME_EXPIRED) != NULL)
{
return LOG_SEND_TIME_ERROR;
}
return LOG_SEND_DISCARD_ERROR;
}
log_producer_send_param * create_log_producer_send_param(log_producer_config * producer_config,
void * producer_manager,
lz4_log_buf * log_buf,
log_group_builder * builder)
{
log_producer_send_param * param = (log_producer_send_param *)malloc(sizeof(log_producer_send_param));
param->producer_config = producer_config;
param->producer_manager = producer_manager;
param->log_buf = log_buf;
param->magic_num = LOG_PRODUCER_SEND_MAGIC_NUM;
if (builder != NULL)
{
param->builder_time = builder->builder_time;
param->start_uuid = builder->start_uuid;
param->end_uuid = builder->end_uuid;
}
else
{
param->builder_time = time(NULL);
param->start_uuid = -1;
param->end_uuid = -1;
}
return param;
}
//
// Created by ZhangCheng on 20/11/2017.
//
#ifndef LOG_C_SDK_LOG_PRODUCER_SENDER_H
#define LOG_C_SDK_LOG_PRODUCER_SENDER_H
#include "log_define.h"
#include "log_producer_config.h"
#include "log_builder.h"
LOG_CPP_START
#define LOG_PRODUCER_SEND_MAGIC_NUM 0x1B35487A
typedef int32_t log_producer_send_result;
#define LOG_SEND_OK 0
#define LOG_SEND_NETWORK_ERROR 1
#define LOG_SEND_QUOTA_EXCEED 2
#define LOG_SEND_UNAUTHORIZED 3
#define LOG_SEND_SERVER_ERROR 4
#define LOG_SEND_DISCARD_ERROR 5
#define LOG_SEND_TIME_ERROR 6
#define LOG_SEND_PARAMETERS_ERROR 8
extern const char* LOGE_SERVER_BUSY;//= "ServerBusy";
extern const char* LOGE_INTERNAL_SERVER_ERROR;//= "InternalServerError";
extern const char* LOGE_UNAUTHORIZED;//= "Unauthorized";
extern const char* LOGE_WRITE_QUOTA_EXCEED;//="WriteQuotaExceed";
extern const char* LOGE_SHARD_WRITE_QUOTA_EXCEED;//= "ShardWriteQuotaExceed";
extern const char* LOGE_TIME_EXPIRED;//= "RequestTimeExpired";
typedef struct _log_producer_send_param
{
log_producer_config * producer_config;
void * producer_manager;
lz4_log_buf * log_buf;
uint32_t magic_num;
uint32_t builder_time;
int64_t start_uuid;
int64_t end_uuid;
}log_producer_send_param;
extern void * log_producer_send_fun(void * send_param);
extern log_producer_result log_producer_send_data(log_producer_send_param * send_param);
extern log_producer_send_result AosStatusToResult(post_log_result * result);
extern log_producer_send_param * create_log_producer_send_param(log_producer_config * producer_config,
void * producer_manager,
lz4_log_buf * log_buf,
log_group_builder * builder);
LOG_CPP_END
#endif //LOG_C_SDK_LOG_PRODUCER_SENDER_H
//
// Created by ZhangCheng on 29/12/2017.
//
#include "log_queue.h"
#include "log_multi_thread.h"
struct _log_queue{
void ** data;
int64_t head;
int64_t tail;
int32_t size;
CRITICALSECTION mutex;
COND notempty;
};
log_queue * log_queue_create(int32_t size)
{
void * buffer = malloc(sizeof(void *) * size + sizeof(log_queue));
memset(buffer, 0, sizeof(void *) * size + sizeof(log_queue));
log_queue * queue = (log_queue *)buffer;
queue->data = (void **)((char*)buffer + sizeof(log_queue));
queue->size = size;
queue->mutex = CreateCriticalSection();
queue->notempty = CreateCond();
return queue;
}
void log_queue_destroy(log_queue * queue)
{
ReleaseCriticalSection(queue->mutex);
DeleteCond(queue->notempty);
free(queue);
}
int32_t log_queue_size(log_queue * queue)
{
CS_ENTER(queue->mutex);
int32_t len = queue->tail - queue->head;
CS_LEAVE(queue->mutex);
return len;
}
int32_t log_queue_isfull(log_queue * queue)
{
CS_ENTER(queue->mutex);
int32_t rst = (int32_t)((queue->tail - queue->head) == queue->size);
CS_LEAVE(queue->mutex);
return rst;
}
int32_t log_queue_push(log_queue * queue, void * data)
{
CS_ENTER(queue->mutex);
if (queue->tail - queue->head == queue->size)
{
CS_LEAVE(queue->mutex);
return -1;
}
queue->data[queue->tail++ % queue->size] = data;
CS_LEAVE(queue->mutex);
COND_SIGNAL(queue->notempty);
return 0;
}
void * log_queue_pop(log_queue * queue, int32_t waitMs) {
CS_ENTER(queue->mutex);
if (queue->tail == queue->head) {
COND_WAIT_TIME(queue->notempty, queue->mutex, waitMs);
}
void * result = NULL;
if (queue->tail > queue->head)
{
result = queue->data[queue->head++ % queue->size];
}
CS_LEAVE(queue->mutex);
return result;
}
void * log_queue_trypop(log_queue * queue)
{
CS_ENTER(queue->mutex);
void * result = NULL;
if (queue->tail > queue->head)
{
result = queue->data[queue->head++ % queue->size];
}
CS_LEAVE(queue->mutex);
return result;
}
//
// Created by ZhangCheng on 29/12/2017.
//
#ifndef LOG_C_SDK_LOG_QUEUE_H
#define LOG_C_SDK_LOG_QUEUE_H
#include <stdint.h>
typedef struct _log_queue log_queue;
log_queue * log_queue_create(int32_t max_size);
void log_queue_destroy(log_queue * queue);
int32_t log_queue_size(log_queue * queue);
int32_t log_queue_isfull(log_queue * queue);
int32_t log_queue_push(log_queue * queue, void * data);
void * log_queue_pop(log_queue * queue, int32_t waitMs);
void * log_queue_trypop(log_queue * queue);
#endif //LOG_C_SDK_LOG_QUEUE_H
//
// Created by davidzhang on 2020/8/23.
//
#include "log_ring_file.h"
#include "log_sds.h"
#include "inner_log.h"
#include <fcntl.h>
static void get_ring_file_offset(log_ring_file * file,
uint64_t offset,
int32_t * fileIndex,
int32_t * fileOffset)
{
*fileIndex = (offset / file->maxFileSize) % file->maxFileCount;
*fileOffset = offset % file->maxFileSize;
}
static int log_ring_file_open_fd(log_ring_file *file, uint64_t offset, int32_t fileIndex, int32_t fileOffset)
{
if (file->nowFD > 0 && file->nowFileIndex == fileIndex && file->nowOffset % file->maxFileSize == fileOffset)
{
return 0;
}
if (file->nowFD > 0)
{
close(file->nowFD);
file->nowFD = -1;
}
file->fileRemoveFlags[fileIndex] = 0;
char filePath[256] = {0};
snprintf(filePath, 255, "%s_%03d", file->filePath, fileIndex);
int openFlag = O_RDWR|O_CREAT;
if (file->syncWrite)
{
openFlag |= O_SYNC;
}
file->nowFD = open(filePath, openFlag, 0644);
if (file->nowFD < 0)
{
aos_error_log("open file failed %s, error %s", filePath, strerror(errno));
return -1;
}
if (fileOffset != 0)
{
lseek(file->nowFD, fileOffset, SEEK_SET);
}
file->nowFileIndex = fileIndex;
file->nowOffset = offset;
return 0;
}
log_ring_file *
log_ring_file_open(const char *filePath, int maxFileCount, int maxFileSize, int syncWrite)
{
log_ring_file * file = (log_ring_file *)malloc(sizeof(log_ring_file));
memset(file, 0, sizeof(log_ring_file));
file->filePath = log_sdsdup((const log_sds)filePath);
file->nowFD = -1;
file->maxFileCount = maxFileCount;
file->maxFileSize = maxFileSize;
file->syncWrite = syncWrite;
file->fileRemoveFlags = (int *)malloc(sizeof(int) * file->maxFileCount);
memset(file->fileRemoveFlags, 0, sizeof(int) * file->maxFileCount);
file->fileUseFlags = (int *)malloc(sizeof(int) * file->maxFileCount);
memset(file->fileUseFlags, 0, sizeof(int) * file->maxFileCount);
return file;
}
int log_ring_file_write_single(log_ring_file *file, uint64_t offset,
const void *buffer,
size_t buffer_size)
{
// {
// int openFlag = O_RDWR|O_CREAT;
// if (file->syncWrite)
// {
// openFlag |= O_SYNC;
// }
// file->nowFD = open(file->filePath, openFlag, 0644);
// if (file->nowFD < 0)
// {
// aos_error_log("open file failed %s, error %s", file->filePath, strerror(errno));
// return -1;
// }
// if (offset != 0)
// {
// lseek(file->nowFD, offset, SEEK_SET);
// }
// int rst = write(file->nowFD, (char *)buffer, buffer_size);
// close(file->nowFD);
// file->nowFD = 0;
// return rst;
// }
int32_t fileIndex = 0;
int32_t fileOffset = 0;
size_t nowOffset = 0;
while (nowOffset < buffer_size)
{
get_ring_file_offset(file, offset + nowOffset, &fileIndex, &fileOffset);
if (log_ring_file_open_fd(file, offset, fileIndex, fileOffset) != 0)
{
return -1;
}
int writeSize = buffer_size - nowOffset;
if (file->maxFileSize - fileOffset <= writeSize)
{
writeSize = file->maxFileSize - fileOffset;
}
int rst = write(file->nowFD, (char *)buffer + nowOffset, writeSize);
if (rst != writeSize)
{
aos_error_log("write buffer to file failed, file %s, offset %d, size %d, error %s",
file->filePath,
fileIndex + nowOffset,
file->maxFileSize - fileOffset,
strerror(errno));
return -1;
}
nowOffset += rst;
file->nowOffset += rst;
}
return buffer_size;
}
int log_ring_file_write(log_ring_file *file, uint64_t offset, int buffer_count,
const void **buffer, size_t *buffer_size)
{
uint64_t inner_offset = 0;
for (int (i) = 0; (i) < buffer_count; ++(i))
{
if (log_ring_file_write_single(file, offset + inner_offset, buffer[i], buffer_size[i]) != buffer_size[i])
{
return -1;
}
inner_offset += buffer_size[i];
}
return inner_offset;
}
int log_ring_file_read(log_ring_file *file, uint64_t offset, void *buffer,
size_t buffer_size)
{
// {
// int openFlag = O_RDWR|O_CREAT;
// if (file->syncWrite)
// {
// openFlag |= O_SYNC;
// }
// file->nowFD = open(file->filePath, openFlag, 0644);
// if (file->nowFD < 0)
// {
// aos_error_log("open file failed %s, error %s", file->filePath, strerror(errno));
// return -1;
// }
// if (offset != 0)
// {
// lseek(file->nowFD, offset, SEEK_SET);
// }
// int rst = read(file->nowFD, buffer, buffer_size);
// close(file->nowFD);
// file->nowFD = 0;
// return rst;
// }
int32_t fileIndex = 0;
int32_t fileOffset = 0;
size_t nowOffset = 0;
while (nowOffset < buffer_size)
{
get_ring_file_offset(file, offset + nowOffset, &fileIndex, &fileOffset);
if (log_ring_file_open_fd(file, offset, fileIndex, fileOffset) != 0)
{
return -1;
}
int rst = 0;
int readSize = buffer_size - nowOffset;
if (readSize > file->maxFileSize - fileOffset)
{
readSize = file->maxFileSize - fileOffset;
}
if ((rst = read(file->nowFD, buffer + nowOffset, readSize)) != readSize)
{
if (errno == ENOENT)
{
return 0;
}
if (rst > 0)
{
file->nowOffset += rst;
nowOffset += rst;
continue;
}
if (rst == 0)
{
return file->nowOffset - offset;
}
aos_error_log("read buffer from file failed, file %s, offset %d, size %d, error %s",
file->filePath,
fileIndex + nowOffset,
file->maxFileSize - fileOffset,
strerror(errno));
return -1;
}
nowOffset += file->maxFileSize - fileOffset;
file->nowOffset += file->maxFileSize - fileOffset;
}
return buffer_size;
}
int log_ring_file_flush(log_ring_file *file)
{
if (file->nowFD > 0)
{
return fsync(file->nowFD);
}
return -1;
}
void log_ring_file_remove_file(log_ring_file *file, int32_t fileIndex)
{
if (file->fileRemoveFlags[fileIndex] > 0)
{
return;
}
char filePath[256] = {0};
snprintf(filePath, 255, "%s_%03d", file->filePath, fileIndex);
remove(filePath);
aos_info_log("remove file %s", filePath);
file->fileRemoveFlags[fileIndex] = 1;
}
int log_ring_file_clean(log_ring_file *file, uint64_t startOffset,
uint64_t endOffset)
{
if (endOffset > file->nowOffset)
{
aos_error_log("try to clean invalid ring file %s, start %lld, end %lld, now %lld",
file->filePath,
startOffset,
endOffset,
file->nowOffset);
return -1;
}
if ((file->nowOffset - endOffset) / file->maxFileSize >= file->maxFileCount - 1)
{
// no need to clean
return 0;
}
memset(file->fileUseFlags, 0, sizeof(int) * file->maxFileCount);
for (int64_t i = endOffset / file->maxFileSize; i <= file->nowOffset / file->maxFileSize; ++i)
{
file->fileUseFlags[i % file->maxFileCount] = 1;
}
aos_info_log("remove file %s , offset from %lld to %lld, file offset %lld, index from %d to %d",
file->filePath,
startOffset,
endOffset,
file->nowOffset,
endOffset / file->maxFileSize,
file->nowOffset / file->maxFileSize);
for (int i = 0; i < file->maxFileCount; ++i)
{
if (file->fileUseFlags[i] != 0)
continue;
log_ring_file_remove_file(file, i);
}
return 0;
}
int log_ring_file_close(log_ring_file *file)
{
if (file != NULL)
{
log_sdsfree(file->filePath);
if (file->nowFD > 0)
{
close(file->nowFD);
file->nowFD = -1;
}
free(file->fileRemoveFlags);
free(file->fileUseFlags);
free(file);
}
return 0;
}
//
// Created by davidzhang on 2020/8/23.
//
#ifndef LOG_C_SDK_LOG_RING_FILE_H
#define LOG_C_SDK_LOG_RING_FILE_H
#include "log_inner_include.h"
typedef struct _log_ring_file
{
char * filePath;
int maxFileCount;
int maxFileSize;
int syncWrite;
int nowFileIndex;
uint64_t nowOffset;
int nowFD;
int *fileRemoveFlags;
int *fileUseFlags;
}log_ring_file;
log_ring_file * log_ring_file_open(const char * filePath, int maxFileCount, int maxFileSize, int syncWrite);
int log_ring_file_write(log_ring_file * file, uint64_t offset, int buffer_count, const void * buffer[], size_t buffer_size[]);
int log_ring_file_write_single(log_ring_file * file, uint64_t offset, const void * buffer, size_t buffer_size);
int log_ring_file_read(log_ring_file * file, uint64_t offset, void * buffer, size_t buffer_size);
int log_ring_file_flush(log_ring_file * file);
int log_ring_file_clean(log_ring_file * file, uint64_t startOffset, uint64_t endOffset);
int log_ring_file_close(log_ring_file * file);
#endif //LOG_C_SDK_LOG_RING_FILE_H
/* SDSLib, A C dynamic strings library
*
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "log_sds.h"
size_t log_sdslen(const log_sds s) {
struct log_sdshdr *sh = (struct log_sdshdr *) (s - (sizeof(struct log_sdshdr)));
return sh->len;
}
size_t log_sdsavail(const log_sds s) {
struct log_sdshdr *sh = (struct log_sdshdr *) (s - (sizeof(struct log_sdshdr)));
return sh->free;
}
/* Create a new log_sds string with the content specified by the 'init' pointer
* and 'initlen'.
* If NULL is used for 'init' the string is initialized with zero bytes.
*
* The string is always null-termined (all the log_sds strings are, always) so
* even if you create an log_sds string with:
*
* mystring = log_sdsnewlen("abc",3);
*
* You can print the string with printf() as there is an implicit \0 at the
* end of the string. However the string is binary safe and can contain
* \0 characters in the middle, as the length is stored in the log_sds header. */
log_sds log_sdsnewlen(const void *init, size_t initlen) {
struct log_sdshdr *sh;
if (init) {
sh = malloc(sizeof(struct log_sdshdr) + initlen + 1);
} else {
sh = calloc(sizeof(struct log_sdshdr) + initlen + 1, 1);
}
if (sh == NULL) return NULL;
sh->len = initlen;
sh->free = 0;
if (initlen && init)
memcpy(sh->buf, init, initlen);
sh->buf[initlen] = '\0';
return (char *) sh->buf;
}
log_sds log_sdsnewEmpty(size_t preAlloclen) {
struct log_sdshdr *sh;
sh = malloc(sizeof(struct log_sdshdr) + preAlloclen + 1);
if (sh == NULL) return NULL;
sh->len = 0;
sh->free = preAlloclen;
sh->buf[0] = '\0';
return (char *) sh->buf;
}
/* Create an empty (zero length) log_sds string. Even in this case the string
* always has an implicit null term. */
log_sds log_sdsempty(void) {
return log_sdsnewlen("", 0);
}
/* Create a new log_sds string starting from a null terminated C string. */
log_sds log_sdsnew(const char *init) {
size_t initlen = (init == NULL) ? 0 : strlen(init);
return log_sdsnewlen(init, initlen);
}
/* Duplicate an log_sds string. */
log_sds log_sdsdup(const log_sds s) {
if (s == NULL) return NULL;
return log_sdsnewlen(s, log_sdslen(s));
}
/* Free an log_sds string. No operation is performed if 's' is NULL. */
void log_sdsfree(log_sds s) {
if (s == NULL) return;
free(s - sizeof(struct log_sdshdr));
}
/* Set the log_sds string length to the length as obtained with strlen(), so
* considering as content only up to the first null term character.
*
* This function is useful when the log_sds string is hacked manually in some
* way, like in the following example:
*
* s = log_sdsnew("foobar");
* s[2] = '\0';
* log_sdsupdatelen(s);
* printf("%d\n", log_sdslen(s));
*
* The output will be "2", but if we comment out the call to log_sdsupdatelen()
* the output will be "6" as the string was modified but the logical length
* remains 6 bytes. */
void log_sdsupdatelen(log_sds s) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
int reallen = strlen(s);
sh->free += (sh->len - reallen);
sh->len = reallen;
}
/* Modify an log_sds string in-place to make it empty (zero length).
* However all the existing buffer is not discarded but set as free space
* so that next append operations will not require allocations up to the
* number of bytes previously available. */
void log_sdsclear(log_sds s) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
sh->free += sh->len;
sh->len = 0;
sh->buf[0] = '\0';
}
/* Enlarge the free space at the end of the log_sds string so that the caller
* is sure that after calling this function can overwrite up to addlen
* bytes after the end of the string, plus one more byte for nul term.
*
* Note: this does not change the *length* of the log_sds string as returned
* by log_sdslen(), but only the free buffer space we have. */
log_sds log_sdsMakeRoomFor(log_sds s, size_t addlen) {
struct log_sdshdr *sh, *newsh;
size_t free = log_sdsavail(s);
size_t len, newlen;
if (free >= addlen) return s;
len = log_sdslen(s);
sh = (void *) (s - (sizeof(struct log_sdshdr)));
newlen = (len + addlen);
if (newlen < LOG_SDS_MAX_PREALLOC)
newlen *= 2;
else
newlen += LOG_SDS_MAX_PREALLOC;
newsh = realloc(sh, sizeof(struct log_sdshdr) + newlen + 1);
if (newsh == NULL) return NULL;
newsh->free = newlen - len;
return newsh->buf;
}
/* Reallocate the log_sds string so that it has no free space at the end. The
* contained string remains not altered, but next concatenation operations
* will require a reallocation.
*
* After the call, the passed log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
log_sds log_sdsRemoveFreeSpace(log_sds s) {
struct log_sdshdr *sh;
sh = (void *) (s - (sizeof(struct log_sdshdr)));
sh = realloc(sh, sizeof(struct log_sdshdr) + sh->len + 1);
sh->free = 0;
return sh->buf;
}
/* Return the total size of the allocation of the specifed log_sds string,
* including:
* 1) The log_sds header before the pointer.
* 2) The string.
* 3) The free buffer at the end if any.
* 4) The implicit null term.
*/
size_t log_sdsAllocSize(log_sds s) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
return sizeof(*sh) + sh->len + sh->free + 1;
}
/* Increment the log_sds length and decrements the left free space at the
* end of the string according to 'incr'. Also set the null term
* in the new end of the string.
*
* This function is used in order to fix the string length after the
* user calls log_sdsMakeRoomFor(), writes something after the end of
* the current string, and finally needs to set the new length.
*
* Note: it is possible to use a negative increment in order to
* right-trim the string.
*
* Usage example:
*
* Using log_sdsIncrLen() and log_sdsMakeRoomFor() it is possible to mount the
* following schema, to cat bytes coming from the kernel to the end of an
* log_sds string without copying into an intermediate buffer:
*
* oldlen = log_sdslen(s);
* s = log_sdsMakeRoomFor(s, BUFFER_SIZE);
* nread = read(fd, s+oldlen, BUFFER_SIZE);
* ... check for nread <= 0 and handle it ...
* log_sdsIncrLen(s, nread);
*/
void log_sdsIncrLen(log_sds s, int incr) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
if (incr >= 0)
assert(sh->free >= (unsigned int) incr);
else
assert(sh->len >= (unsigned int) (-incr));
sh->len += incr;
sh->free -= incr;
s[sh->len] = '\0';
}
/* Grow the log_sds to have the specified length. Bytes that were not part of
* the original length of the log_sds will be set to zero.
*
* if the specified length is smaller than the current length, no operation
* is performed. */
log_sds log_sdsgrowzero(log_sds s, size_t len) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
size_t totlen, curlen = sh->len;
if (len <= curlen) return s;
s = log_sdsMakeRoomFor(s, len - curlen);
if (s == NULL) return NULL;
/* Make sure added region doesn't contain garbage */
sh = (void *) (s - (sizeof(struct log_sdshdr)));
memset(s + curlen, 0, (len - curlen + 1)); /* also set trailing \0 byte */
totlen = sh->len + sh->free;
sh->len = len;
sh->free = totlen - sh->len;
return s;
}
/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the
* end of the specified log_sds string 's'.
*
* After the call, the passed log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
log_sds log_sdscatlen(log_sds s, const void *t, size_t len) {
struct log_sdshdr *sh;
size_t curlen = log_sdslen(s);
s = log_sdsMakeRoomFor(s, len);
if (s == NULL) return NULL;
sh = (void *) (s - (sizeof(struct log_sdshdr)));
memcpy(s + curlen, t, len);
sh->len = curlen + len;
sh->free = sh->free - len;
s[curlen + len] = '\0';
return s;
}
log_sds log_sdscatchar(log_sds s, char c) {
struct log_sdshdr *sh;
size_t curlen = log_sdslen(s);
s = log_sdsMakeRoomFor(s, 1);
if (s == NULL) return NULL;
sh = (void *) (s - (sizeof(struct log_sdshdr)));
s[curlen] = c;
s[curlen + 1] = '\0';
++sh->len;
--sh->free;
return s;
}
/* Append the specified null termianted C string to the log_sds string 's'.
*
* After the call, the passed log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
log_sds log_sdscat(log_sds s, const char *t) {
if (s == NULL || t == NULL) {
return s;
}
return log_sdscatlen(s, t, strlen(t));
}
/* Append the specified log_sds 't' to the existing log_sds 's'.
*
* After the call, the modified log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
log_sds log_sdscatsds(log_sds s, const log_sds t) {
return log_sdscatlen(s, t, log_sdslen(t));
}
/* Destructively modify the log_sds string 's' to hold the specified binary
* safe string pointed by 't' of length 'len' bytes. */
log_sds log_sdscpylen(log_sds s, const char *t, size_t len) {
struct log_sdshdr *sh = (void *) (s - (sizeof(struct log_sdshdr)));
size_t totlen = sh->free + sh->len;
if (totlen < len) {
s = log_sdsMakeRoomFor(s, len - sh->len);
if (s == NULL) return NULL;
sh = (void *) (s - (sizeof(struct log_sdshdr)));
totlen = sh->free + sh->len;
}
memcpy(s, t, len);
s[len] = '\0';
sh->len = len;
sh->free = totlen - len;
return s;
}
/* Like log_sdscpylen() but 't' must be a null-termined string so that the length
* of the string is obtained with strlen(). */
log_sds log_sdscpy(log_sds s, const char *t) {
return log_sdscpylen(s, t, strlen(t));
}
/* Like log_sdscatprintf() but gets va_list instead of being variadic. */
log_sds log_sdscatvprintf(log_sds s, const char *fmt, va_list ap) {
va_list cpy;
char staticbuf[1024], *buf = staticbuf, *t;
size_t buflen = strlen(fmt) * 2;
/* We try to start using a static buffer for speed.
* If not possible we revert to heap allocation. */
if (buflen > sizeof(staticbuf)) {
buf = malloc(buflen);
if (buf == NULL) return NULL;
} else {
buflen = sizeof(staticbuf);
}
/* Try with buffers two times bigger every time we fail to
* fit the string in the current buffer size. */
while (1) {
buf[buflen - 2] = '\0';
va_copy(cpy, ap);
vsnprintf(buf, buflen, fmt, cpy);
va_end(cpy);
if (buf[buflen - 2] != '\0') {
if (buf != staticbuf) free(buf);
buflen *= 2;
buf = malloc(buflen);
if (buf == NULL) return NULL;
continue;
}
break;
}
/* Finally concat the obtained string to the SDS string and return it. */
t = log_sdscat(s, buf);
if (buf != staticbuf) free(buf);
return t;
}
/* Append to the log_sds string 's' a string obtained using printf-alike format
* specifier.
*
* After the call, the modified log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call.
*
* Example:
*
* s = log_sdsnew("Sum is: ");
* s = log_sdscatprintf(s,"%d+%d = %d",a,b,a+b).
*
* Often you need to create a string from scratch with the printf-alike
* format. When this is the need, just use log_sdsempty() as the target string:
*
* s = log_sdscatprintf(log_sdsempty(), "... your format ...", args);
*/
log_sds log_sdscatprintf(log_sds s, const char *fmt, ...) {
va_list ap;
char *t;
va_start(ap, fmt);
t = log_sdscatvprintf(s, fmt, ap);
va_end(ap);
return t;
}
/* Append to the log_sds string "s" an escaped string representation where
* all the non-printable characters (tested with isprint()) are turned into
* escapes in the form "\n\r\a...." or "\x<hex-number>".
*
* After the call, the modified log_sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
log_sds log_sdscatrepr(log_sds s, const char *p, size_t len) {
s = log_sdscatlen(s,"\"",1);
while(len--) {
switch(*p) {
case '\\':
case '"':
s = log_sdscatprintf(s,"\\%c",*p);
break;
case '\n': s = log_sdscatlen(s,"\\n",2); break;
case '\r': s = log_sdscatlen(s,"\\r",2); break;
case '\t': s = log_sdscatlen(s,"\\t",2); break;
case '\a': s = log_sdscatlen(s,"\\a",2); break;
case '\b': s = log_sdscatlen(s,"\\b",2); break;
default:
if (isprint(*p))
s = log_sdscatprintf(s,"%c",*p);
else
s = log_sdscatprintf(s,"\\\\x%02x",(unsigned char)*p);
break;
}
p++;
}
return log_sdscatlen(s,"\"",1);
}
/* SDSLib, A C dynamic strings library
*
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LOG_SDS_H
#define __LOG_SDS_H
#define LOG_SDS_MAX_PREALLOC (1024*1024)
#include <sys/types.h>
#include <stdarg.h>
#ifdef WIN32
#define inline __inline
#endif
typedef char *log_sds;
struct log_sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
size_t log_sdslen(const log_sds s);
size_t log_sdsavail(const log_sds s);
log_sds log_sdsnewlen(const void *init, size_t initlen);
log_sds log_sdsnewEmpty(size_t preAlloclen);
log_sds log_sdsnew(const char *init);
log_sds log_sdsempty(void);
size_t log_sdslen(const log_sds s);
log_sds log_sdsdup(const log_sds s);
void log_sdsfree(log_sds s);
size_t log_sdsavail(const log_sds s);
log_sds log_sdsgrowzero(log_sds s, size_t len);
log_sds log_sdscatlen(log_sds s, const void *t, size_t len);
log_sds log_sdscat(log_sds s, const char *t);
log_sds log_sdscatchar(log_sds s, char c);
log_sds log_sdscatsds(log_sds s, const log_sds t);
log_sds log_sdscpylen(log_sds s, const char *t, size_t len);
log_sds log_sdscpy(log_sds s, const char *t);
log_sds log_sdscatvprintf(log_sds s, const char *fmt, va_list ap);
log_sds log_sdscatrepr(log_sds s, const char *p, size_t len);
#ifdef __GNUC__
log_sds log_sdscatprintf(log_sds s, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
log_sds log_sdscatprintf(log_sds s, const char *fmt, ...);
#endif
#endif
#include <string.h> /* memcpy & co */
#include <stdint.h>
#include "log_sha1.h"
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN
#endif
/********************************************************************************************************/
/**
* \brief initialises given SHA-1 context
*
*/
void log_sha1_init(log_sha1_ctx_t *state){
state->h[0] = 0x67452301;
state->h[1] = 0xefcdab89;
state->h[2] = 0x98badcfe;
state->h[3] = 0x10325476;
state->h[4] = 0xc3d2e1f0;
state->length = 0;
}
/********************************************************************************************************/
/* some helping functions */
uint32_t log_rotl32(uint32_t n, uint8_t bits){
return ((n<<bits) | (n>>(32-bits)));
}
uint32_t log_change_endian32(uint32_t x){
return (((x)<<24) | ((x)>>24) | (((x)& 0x0000ff00)<<8) | (((x)& 0x00ff0000)>>8));
}
/* three SHA-1 inner functions */
uint32_t log_ch(uint32_t x, uint32_t y, uint32_t z){
return ((x&y)^((~x)&z));
}
uint32_t log_maj(uint32_t x, uint32_t y, uint32_t z){
return ((x&y)^(x&z)^(y&z));
}
uint32_t log_parity(uint32_t x, uint32_t y, uint32_t z){
return ((x^y)^z);
}
/********************************************************************************************************/
/**
* \brief "add" a block to the hash
* This is the core function of the hash algorithm. To understand how it's working
* and what thoese variables do, take a look at FIPS-182. This is an "alternativ" implementation
*/
#define MASK 0x0000000f
typedef uint32_t (*pf_t)(uint32_t x, uint32_t y, uint32_t z);
void log_sha1_nextBlock (log_sha1_ctx_t *state, const void *block){
uint32_t a[5];
uint32_t w[16];
uint32_t temp;
uint8_t t,s,fi, fib;
pf_t f[] = {log_ch,log_parity,log_maj,log_parity};
uint32_t k[4]={ 0x5a827999,
0x6ed9eba1,
0x8f1bbcdc,
0xca62c1d6};
/* load the w array (changing the endian and so) */
for(t=0; t<16; ++t){
w[t] = log_change_endian32(((uint32_t*)block)[t]);
}
/* load the state */
memcpy(a, state->h, 5*sizeof(uint32_t));
/* the fun stuff */
for(fi=0,fib=0,t=0; t<=79; ++t){
s = t & MASK;
if(t>=16){
w[s] = log_rotl32( w[(s+13)&MASK] ^ w[(s+8)&MASK] ^
w[(s+ 2)&MASK] ^ w[s] ,1);
}
uint32_t dtemp;
temp = log_rotl32(a[0],5) + (dtemp=f[fi](a[1],a[2],a[3])) + a[4] + k[fi] + w[s];
memmove(&(a[1]), &(a[0]), 4*sizeof(uint32_t)); /* e=d; d=c; c=b; b=a; */
a[0] = temp;
a[2] = log_rotl32(a[2],30); /* we might also do rotr32(c,2) */
fib++;
if(fib==20){
fib=0;
fi = (fi+1)%4;
}
}
/* update the state */
for(t=0; t<5; ++t){
state->h[t] += a[t];
}
state->length += 512;
}
/********************************************************************************************************/
void log_sha1_lastBlock(log_sha1_ctx_t *state, const void *block, uint16_t length){
uint8_t lb[LOG_SHA1_BLOCK_BYTES]; /* local block */
while(length>=LOG_SHA1_BLOCK_BITS){
log_sha1_nextBlock(state, block);
length -= LOG_SHA1_BLOCK_BITS;
block = (uint8_t*)block + LOG_SHA1_BLOCK_BYTES;
}
state->length += length;
memset(lb, 0, LOG_SHA1_BLOCK_BYTES);
memcpy (lb, block, (length+7)>>3);
/* set the final one bit */
lb[length>>3] |= 0x80>>(length & 0x07);
if (length>512-64-1){ /* not enouth space for 64bit length value */
log_sha1_nextBlock(state, lb);
state->length -= 512;
memset(lb, 0, LOG_SHA1_BLOCK_BYTES);
}
/* store the 64bit length value */
#if defined LITTLE_ENDIAN
/* this is now rolled up */
uint8_t i;
for (i=0; i<8; ++i){
lb[56+i] = ((uint8_t*)&(state->length))[7-i];
}
#elif defined BIG_ENDIAN
*((uint64_t)&(lb[56])) = state->length;
#endif
log_sha1_nextBlock(state, lb);
}
/********************************************************************************************************/
void log_sha1_ctx2hash (void *dest, log_sha1_ctx_t *state){
#if defined LITTLE_ENDIAN
uint8_t i;
for(i=0; i<5; ++i){
((uint32_t*)dest)[i] = log_change_endian32(state->h[i]);
}
#elif BIG_ENDIAN
if (dest != state->h)
memcpy(dest, state->h, LOG_SHA1_HASH_BITS/8);
#else
# error unsupported endian type!
#endif
}
/********************************************************************************************************/
/**
*
*
*/
void log_sha1 (void *dest, const void *msg, uint32_t length){
log_sha1_ctx_t s;
log_sha1_init(&s);
while(length & (~0x0001ff)){ /* length>=512 */
log_sha1_nextBlock(&s, msg);
msg = (uint8_t*)msg + LOG_SHA1_BLOCK_BITS/8; /* increment pointer to next block */
length -= LOG_SHA1_BLOCK_BITS;
}
log_sha1_lastBlock(&s, msg, length);
log_sha1_ctx2hash(dest, &s);
}
#ifndef LOG_SHA1_H_
#define LOG_SHA1_H_
#include <stdint.h>
/** \def LOG_SHA1_HASH_BITS
* definees the size of a SHA-1 hash in bits
*/
/** \def LOG_SHA1_HASH_BYTES
* definees the size of a SHA-1 hash in bytes
*/
/** \def LOG_SHA1_BLOCK_BITS
* definees the size of a SHA-1 input block in bits
*/
/** \def LOG_SHA1_BLOCK_BYTES
* definees the size of a SHA-1 input block in bytes
*/
#define LOG_SHA1_HASH_BITS 160
#define LOG_SHA1_HASH_BYTES (LOG_SHA1_HASH_BITS/8)
#define LOG_SHA1_BLOCK_BITS 512
#define LOG_SHA1_BLOCK_BYTES (LOG_SHA1_BLOCK_BITS/8)
/** \typedef log_sha1_ctx_t
* \brief SHA-1 context type
*
* A vatiable of this type may hold the state of a SHA-1 hashing process
*/
typedef struct {
uint32_t h[5];
uint64_t length;
} log_sha1_ctx_t;
/** \typedef sha1_hash_t
* \brief hash value type
* A variable of this type may hold a SHA-1 hash value
*/
/*
typedef uint8_t sha1_hash_t[LOG_SHA1_HASH_BITS/8];
*/
/** \fn log_sha1_init(log_sha1_ctx_t *state)
* \brief initializes a SHA-1 context
* This function sets a ::log_sha1_ctx_t variable to the initialization vector
* for SHA-1 hashing.
* \param state pointer to the SHA-1 context variable
*/
void log_sha1_init(log_sha1_ctx_t *state);
/** \fn log_sha1_nextBlock(log_sha1_ctx_t *state, const void *block)
* \brief process one input block
* This function processes one input block and updates the hash context
* accordingly
* \param state pointer to the state variable to update
* \param block pointer to the message block to process
*/
void log_sha1_nextBlock (log_sha1_ctx_t *state, const void *block);
/** \fn log_sha1_lastBlock(log_sha1_ctx_t *state, const void *block, uint16_t length_b)
* \brief processes the given block and finalizes the context
* This function processes the last block in a SHA-1 hashing process.
* The block should have a maximum length of a single input block.
* \param state pointer to the state variable to update and finalize
* \param block pointer to themessage block to process
* \param length_b length of the message block in bits
*/
void log_sha1_lastBlock (log_sha1_ctx_t *state, const void *block, uint16_t length_b);
/** \fn log_sha1_ctx2hash(sha1_hash_t *dest, log_sha1_ctx_t *state)
* \brief convert a state variable into an actual hash value
* Writes the hash value corresponding to the state to the memory pointed by dest.
* \param dest pointer to the hash value destination
* \param state pointer to the hash context
*/
void log_sha1_ctx2hash (void *dest, log_sha1_ctx_t *state);
/** \fn log_sha1(sha1_hash_t *dest, const void *msg, uint32_t length_b)
* \brief hashing a message which in located entirely in RAM
* This function automatically hashes a message which is entirely in RAM with
* the SHA-1 hashing algorithm.
* \param dest pointer to the hash value destination
* \param msg pointer to the message which should be hashed
* \param length_b length of the message in bits
*/
void log_sha1(void *dest, const void *msg, uint32_t length_b);
#endif /*LOG_SHA1_H_*/
#ifdef WIN32
#include <windows.h>
#else
#include <arpa/inet.h>
#endif
#include <string.h>
#include "log_util.h"
#include "log_md5.h"
#include "log_hmac-sha.h"
static const char *g_hex_hash = "0123456789ABCDEF";
void md5_to_string(const char * buffer, int bufLen, char * md5)
{
unsigned char md5Buf[16];
log_mbedtls_md5((const unsigned char *)buffer, bufLen, md5Buf);
int i = 0;
for(; i < 32; i+=2)
{
md5[i] = g_hex_hash[md5Buf[i >> 1] >> 4];
md5[i+1] = g_hex_hash[md5Buf[i >> 1] & 0xF];
}
}
int aos_base64_encode(const unsigned char *in, int inLen, char *out)
{
static const char *ENC =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *original_out = out;
while (inLen) {
// first 6 bits of char 1
*out++ = ENC[*in >> 2];
if (!--inLen) {
// last 2 bits of char 1, 4 bits of 0
*out++ = ENC[(*in & 0x3) << 4];
*out++ = '=';
*out++ = '=';
break;
}
// last 2 bits of char 1, first 4 bits of char 2
*out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)];
in++;
if (!--inLen) {
// last 4 bits of char 2, 2 bits of 0
*out++ = ENC[(*in & 0xF) << 2];
*out++ = '=';
break;
}
// last 4 bits of char 2, first 2 bits of char 3
*out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)];
in++;
// last 6 bits of char 3
*out++ = ENC[*in & 0x3F];
in++, inLen--;
}
return (int)(out - original_out);
}
int signature_to_base64(const char * sig, int sigLen, const char * key, int keyLen, char * base64)
{
unsigned char sha1Buf[20];
log_hmac_sha1(sha1Buf, key, keyLen << 3, sig, sigLen << 3);
return aos_base64_encode((const unsigned char *)sha1Buf, 20, base64);
}
#ifndef LIBLOG_UTIL_H
#define LIBLOG_UTIL_H
#include "log_define.h"
LOG_CPP_START
void md5_to_string(const char * buffer, int bufLen, char * md5);
int signature_to_base64(const char * sig, int sigLen, const char * key, int keyLen, char * base64);
LOG_CPP_END
#endif
# Uncomment the next line to define a global platform for your project # Uncomment the next line to define a global platform for your project
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/aliyun-sls/Specs.git' source 'https://github.com/aliyun-sls/Specs.git'
platform :ios, '13.0'
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, '15.1'
prepare_react_native_project!
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'galaxy' do target 'galaxy' do
use_frameworks! use_frameworks!
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# :hermes_enabled => true,
# :fabric_enabled => true, # 尝试启用 Fabric
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/../.."
)
#声网SDK播放器等(先弄完整的,后续剪裁) #声网SDK播放器等(先弄完整的,后续剪裁)
pod 'AgoraRtcEngine_iOS', '4.4.0' #, :subspecs => ['RtcBasic'] pod 'AgoraRtcEngine_iOS', '4.4.0' #, :subspecs => ['RtcBasic']
...@@ -111,19 +134,43 @@ target 'galaxy' do ...@@ -111,19 +134,43 @@ target 'galaxy' do
pod 'TYSnapshotScroll', '0.4.0' pod 'TYSnapshotScroll', '0.4.0'
#七鱼SDK #七鱼SDK
pod 'QY_iOS_SDK', '9.9.2' pod 'QY_iOS_SDK', '9.9.2'
#阿里云日志 #阿里云日志(换成本地仓库)
pod 'AliyunLogProducer', '4.3.3' # pod 'AliyunLogProducer', '4.3.3'
pod 'AliyunLogProducer', :path => 'AliyunLogProducer/'
#加密 #加密
pod 'xxtea', '1.0.2' pod 'xxtea', '1.0.2'
end end
pre_install do |installer|
installer.pod_targets.each do |pod|
if pod.name.eql?('RNReanimated')
def pod.build_type;
Pod::BuildType.static_library
end
end
end
end
post_install do |installer| post_install do |installer|
config = use_native_modules!
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
target.build_configurations.each do |config| target.build_configurations.each do |config|
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 13.0 if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 13.0
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end end
end end
if target.name.eql?('RNReanimated')
def target.build_type
Pod::BuildType.static_library
end
end
end end
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
end end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>3B52.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
...@@ -1090,6 +1090,8 @@ ...@@ -1090,6 +1090,8 @@
0468D42E2B5654A500CFB916 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42D2B5654A500CFB916 /* CoreTelephony.framework */; }; 0468D42E2B5654A500CFB916 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42D2B5654A500CFB916 /* CoreTelephony.framework */; };
0468D4302B5654B500CFB916 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */; }; 0468D4302B5654B500CFB916 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */; };
0468D4312B5654C100CFB916 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42C2B56549200CFB916 /* libresolv.tbd */; }; 0468D4312B5654C100CFB916 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0468D42C2B56549200CFB916 /* libresolv.tbd */; };
047A967D2D150DA10033BB4E /* YHTestRNViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047A967C2D150DA10033BB4E /* YHTestRNViewController.swift */; };
047A96812D151B3C0033BB4E /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 047A96802D151B3C0033BB4E /* main.jsbundle */; };
04AE200F2D12CFAF00891D24 /* YHGCMineSchemeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FF82D12CFAF00891D24 /* YHGCMineSchemeViewController.swift */; }; 04AE200F2D12CFAF00891D24 /* YHGCMineSchemeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FF82D12CFAF00891D24 /* YHGCMineSchemeViewController.swift */; };
04AE20102D12CFAF00891D24 /* YHGCApplicationTypeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FFD2D12CFAF00891D24 /* YHGCApplicationTypeController.swift */; }; 04AE20102D12CFAF00891D24 /* YHGCApplicationTypeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FFD2D12CFAF00891D24 /* YHGCApplicationTypeController.swift */; };
04AE20112D12CFAF00891D24 /* YHGCApplicationTypeResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FFE2D12CFAF00891D24 /* YHGCApplicationTypeResultController.swift */; }; 04AE20112D12CFAF00891D24 /* YHGCApplicationTypeResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE1FFE2D12CFAF00891D24 /* YHGCApplicationTypeResultController.swift */; };
...@@ -1117,7 +1119,8 @@ ...@@ -1117,7 +1119,8 @@
04AE203F2D13C36500891D24 /* YHGCQualificationDetailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE203E2D13C36500891D24 /* YHGCQualificationDetailVC.swift */; }; 04AE203F2D13C36500891D24 /* YHGCQualificationDetailVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04AE203E2D13C36500891D24 /* YHGCQualificationDetailVC.swift */; };
04EA376D2BEA06EF00DBAF64 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EA376C2BEA06EF00DBAF64 /* WebKit.framework */; }; 04EA376D2BEA06EF00DBAF64 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EA376C2BEA06EF00DBAF64 /* WebKit.framework */; };
04EA376F2BEA071600DBAF64 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EA376E2BEA070500DBAF64 /* libc++.tbd */; }; 04EA376F2BEA071600DBAF64 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EA376E2BEA070500DBAF64 /* libc++.tbd */; };
6203A87EDC96313BBE789D9C /* Pods_galaxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 987C69D43AE8D85DC1930DCF /* Pods_galaxy.framework */; }; 134448BA91456A66F447B18B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 9A9C4777B08F67B4E2AA5F9F /* PrivacyInfo.xcprivacy */; };
70A81099B6D30A26A777E870 /* Pods_galaxy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ED011249B4E2CA3CA2B67FC /* Pods_galaxy.framework */; };
A5573EE92B317C0100D98EC0 /* galaxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EE82B317C0100D98EC0 /* galaxyTests.swift */; }; A5573EE92B317C0100D98EC0 /* galaxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EE82B317C0100D98EC0 /* galaxyTests.swift */; };
A5573EF32B317C0100D98EC0 /* galaxyUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EF22B317C0100D98EC0 /* galaxyUITests.swift */; }; A5573EF32B317C0100D98EC0 /* galaxyUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EF22B317C0100D98EC0 /* galaxyUITests.swift */; };
A5573EF52B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EF42B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift */; }; A5573EF52B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5573EF42B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift */; };
...@@ -2245,6 +2248,8 @@ ...@@ -2245,6 +2248,8 @@
0468D42C2B56549200CFB916 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; 0468D42C2B56549200CFB916 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
0468D42D2B5654A500CFB916 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; 0468D42D2B5654A500CFB916 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
047A967C2D150DA10033BB4E /* YHTestRNViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHTestRNViewController.swift; sourceTree = "<group>"; };
047A96802D151B3C0033BB4E /* main.jsbundle */ = {isa = PBXFileReference; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
04AE1FF82D12CFAF00891D24 /* YHGCMineSchemeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCMineSchemeViewController.swift; sourceTree = "<group>"; }; 04AE1FF82D12CFAF00891D24 /* YHGCMineSchemeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCMineSchemeViewController.swift; sourceTree = "<group>"; };
04AE1FFA2D12CFAF00891D24 /* YHGCSchemeTableHeadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCSchemeTableHeadView.swift; sourceTree = "<group>"; }; 04AE1FFA2D12CFAF00891D24 /* YHGCSchemeTableHeadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCSchemeTableHeadView.swift; sourceTree = "<group>"; };
04AE1FFD2D12CFAF00891D24 /* YHGCApplicationTypeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCApplicationTypeController.swift; sourceTree = "<group>"; }; 04AE1FFD2D12CFAF00891D24 /* YHGCApplicationTypeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YHGCApplicationTypeController.swift; sourceTree = "<group>"; };
...@@ -2271,17 +2276,18 @@ ...@@ -2271,17 +2276,18 @@
04EA376C2BEA06EF00DBAF64 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 04EA376C2BEA06EF00DBAF64 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
04EA376E2BEA070500DBAF64 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 04EA376E2BEA070500DBAF64 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
04FA8B2D2C084C7E00ABE43F /* ATAuthSDK.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = ATAuthSDK.bundle; path = "galaxy/Classes/Modules/AutoLogin(一键登录)/framework/ATAuthSDK_D.framework/ATAuthSDK.bundle"; sourceTree = "<group>"; }; 04FA8B2D2C084C7E00ABE43F /* ATAuthSDK.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = ATAuthSDK.bundle; path = "galaxy/Classes/Modules/AutoLogin(一键登录)/framework/ATAuthSDK_D.framework/ATAuthSDK.bundle"; sourceTree = "<group>"; };
19B28612265782F9DC1BE0B0 /* Pods-galaxy.testenv.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.testenv.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.testenv.xcconfig"; sourceTree = "<group>"; }; 0B72C229AEE1BEB0959F0A26 /* Pods-galaxy.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.release.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.release.xcconfig"; sourceTree = "<group>"; };
58C2405158A4A6632D0E7460 /* Pods-galaxy.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.debug.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.debug.xcconfig"; sourceTree = "<group>"; }; 1ED011249B4E2CA3CA2B67FC /* Pods_galaxy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_galaxy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
987C69D43AE8D85DC1930DCF /* Pods_galaxy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_galaxy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6730861F2D1C34DDDD195940 /* Pods-galaxy.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.debug.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.debug.xcconfig"; sourceTree = "<group>"; };
977D00DB1E2D046DDBE24B4B /* Pods-galaxy.testenv.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.testenv.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.testenv.xcconfig"; sourceTree = "<group>"; };
9A9C4777B08F67B4E2AA5F9F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = ../PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
A5573ECE2B317BFF00D98EC0 /* galaxy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = galaxy.app; sourceTree = BUILT_PRODUCTS_DIR; }; A5573ECE2B317BFF00D98EC0 /* galaxy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = galaxy.app; sourceTree = BUILT_PRODUCTS_DIR; };
A5573EE42B317C0100D98EC0 /* galaxyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = galaxyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A5573EE42B317C0100D98EC0 /* galaxyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = galaxyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A5573EE82B317C0100D98EC0 /* galaxyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyTests.swift; sourceTree = "<group>"; }; A5573EE82B317C0100D98EC0 /* galaxyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyTests.swift; sourceTree = "<group>"; };
A5573EEE2B317C0100D98EC0 /* galaxyUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = galaxyUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A5573EEE2B317C0100D98EC0 /* galaxyUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = galaxyUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A5573EF22B317C0100D98EC0 /* galaxyUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyUITests.swift; sourceTree = "<group>"; }; A5573EF22B317C0100D98EC0 /* galaxyUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyUITests.swift; sourceTree = "<group>"; };
A5573EF42B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyUITestsLaunchTests.swift; sourceTree = "<group>"; }; A5573EF42B317C0100D98EC0 /* galaxyUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = galaxyUITestsLaunchTests.swift; sourceTree = "<group>"; };
B6BB01E4C5DB87B66F0ECE84 /* Pods-galaxy.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.release.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.release.xcconfig"; sourceTree = "<group>"; }; E3B32258B6D8636984F97AD4 /* Pods-galaxy.uatrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.uatrelease.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.uatrelease.xcconfig"; sourceTree = "<group>"; };
DF4796A13E2592E1653226DE /* Pods-galaxy.uatrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-galaxy.uatrelease.xcconfig"; path = "Target Support Files/Pods-galaxy/Pods-galaxy.uatrelease.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
...@@ -2289,13 +2295,13 @@ ...@@ -2289,13 +2295,13 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
6203A87EDC96313BBE789D9C /* Pods_galaxy.framework in Frameworks */,
04EA376F2BEA071600DBAF64 /* libc++.tbd in Frameworks */, 04EA376F2BEA071600DBAF64 /* libc++.tbd in Frameworks */,
0468D42E2B5654A500CFB916 /* CoreTelephony.framework in Frameworks */, 0468D42E2B5654A500CFB916 /* CoreTelephony.framework in Frameworks */,
04EA376D2BEA06EF00DBAF64 /* WebKit.framework in Frameworks */, 04EA376D2BEA06EF00DBAF64 /* WebKit.framework in Frameworks */,
045C13B72D12CA5F00BD2DC0 /* ATAuthSDK_D.framework in Frameworks */, 045C13B72D12CA5F00BD2DC0 /* ATAuthSDK_D.framework in Frameworks */,
0468D4312B5654C100CFB916 /* libresolv.tbd in Frameworks */, 0468D4312B5654C100CFB916 /* libresolv.tbd in Frameworks */,
0468D4302B5654B500CFB916 /* SystemConfiguration.framework in Frameworks */, 0468D4302B5654B500CFB916 /* SystemConfiguration.framework in Frameworks */,
70A81099B6D30A26A777E870 /* Pods_galaxy.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -5361,6 +5367,7 @@ ...@@ -5361,6 +5367,7 @@
045C0EE12D12CA5E00BD2DC0 /* C */ = { 045C0EE12D12CA5E00BD2DC0 /* C */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
047A967C2D150DA10033BB4E /* YHTestRNViewController.swift */,
045C0ED62D12CA5E00BD2DC0 /* YHAboutGalaxyViewController.swift */, 045C0ED62D12CA5E00BD2DC0 /* YHAboutGalaxyViewController.swift */,
045C0ED72D12CA5E00BD2DC0 /* YHAboutUsViewController.swift */, 045C0ED72D12CA5E00BD2DC0 /* YHAboutUsViewController.swift */,
045C0ED82D12CA5E00BD2DC0 /* YHDeviceInfoViewController.swift */, 045C0ED82D12CA5E00BD2DC0 /* YHDeviceInfoViewController.swift */,
...@@ -5820,6 +5827,7 @@ ...@@ -5820,6 +5827,7 @@
045C0F772D12CA5E00BD2DC0 /* Res */ = { 045C0F772D12CA5E00BD2DC0 /* Res */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
047A96802D151B3C0033BB4E /* main.jsbundle */,
045C0F4C2D12CA5E00BD2DC0 /* Font */, 045C0F4C2D12CA5E00BD2DC0 /* Font */,
045C0F502D12CA5E00BD2DC0 /* gif */, 045C0F502D12CA5E00BD2DC0 /* gif */,
045C0F6E2D12CA5E00BD2DC0 /* jsons */, 045C0F6E2D12CA5E00BD2DC0 /* jsons */,
...@@ -5845,6 +5853,7 @@ ...@@ -5845,6 +5853,7 @@
045C0F7B2D12CA5E00BD2DC0 /* galaxyDebug.entitlements */, 045C0F7B2D12CA5E00BD2DC0 /* galaxyDebug.entitlements */,
045C0F7C2D12CA5E00BD2DC0 /* galaxyTestEnv.entitlements */, 045C0F7C2D12CA5E00BD2DC0 /* galaxyTestEnv.entitlements */,
045C0F7D2D12CA5E00BD2DC0 /* README.md */, 045C0F7D2D12CA5E00BD2DC0 /* README.md */,
9A9C4777B08F67B4E2AA5F9F /* PrivacyInfo.xcprivacy */,
); );
path = galaxy; path = galaxy;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -6059,10 +6068,10 @@ ...@@ -6059,10 +6068,10 @@
4758815B24BAF3CAA24EC6A8 /* Pods */ = { 4758815B24BAF3CAA24EC6A8 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
58C2405158A4A6632D0E7460 /* Pods-galaxy.debug.xcconfig */, 6730861F2D1C34DDDD195940 /* Pods-galaxy.debug.xcconfig */,
B6BB01E4C5DB87B66F0ECE84 /* Pods-galaxy.release.xcconfig */, 0B72C229AEE1BEB0959F0A26 /* Pods-galaxy.release.xcconfig */,
19B28612265782F9DC1BE0B0 /* Pods-galaxy.testenv.xcconfig */, E3B32258B6D8636984F97AD4 /* Pods-galaxy.uatrelease.xcconfig */,
DF4796A13E2592E1653226DE /* Pods-galaxy.uatrelease.xcconfig */, 977D00DB1E2D046DDBE24B4B /* Pods-galaxy.testenv.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -6075,7 +6084,7 @@ ...@@ -6075,7 +6084,7 @@
0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */, 0468D42F2B5654B500CFB916 /* SystemConfiguration.framework */,
0468D42D2B5654A500CFB916 /* CoreTelephony.framework */, 0468D42D2B5654A500CFB916 /* CoreTelephony.framework */,
0468D42C2B56549200CFB916 /* libresolv.tbd */, 0468D42C2B56549200CFB916 /* libresolv.tbd */,
987C69D43AE8D85DC1930DCF /* Pods_galaxy.framework */, 1ED011249B4E2CA3CA2B67FC /* Pods_galaxy.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -6128,13 +6137,13 @@ ...@@ -6128,13 +6137,13 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = A5573EF82B317C0100D98EC0 /* Build configuration list for PBXNativeTarget "galaxy" */; buildConfigurationList = A5573EF82B317C0100D98EC0 /* Build configuration list for PBXNativeTarget "galaxy" */;
buildPhases = ( buildPhases = (
7D00420CA535917A84A0A43E /* [CP] Check Pods Manifest.lock */, CEBE5659282DCD0474CE9E93 /* [CP] Check Pods Manifest.lock */,
A5573ECA2B317BFF00D98EC0 /* Sources */, A5573ECA2B317BFF00D98EC0 /* Sources */,
A5573ECB2B317BFF00D98EC0 /* Frameworks */, A5573ECB2B317BFF00D98EC0 /* Frameworks */,
A5573ECC2B317BFF00D98EC0 /* Resources */, A5573ECC2B317BFF00D98EC0 /* Resources */,
0CFB07298194FEC905CE2694 /* [CP] Embed Pods Frameworks */,
04808C092B4686C10056D53C /* Embed Frameworks */, 04808C092B4686C10056D53C /* Embed Frameworks */,
47BB31035D3DBEB9235AC809 /* [CP] Copy Pods Resources */, C1342D35A3592DE7B5EF54BC /* [CP] Embed Pods Frameworks */,
A0B9C54FB2F64F568EF0BC88 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
...@@ -6256,6 +6265,7 @@ ...@@ -6256,6 +6265,7 @@
045C0F942D12CA5F00BD2DC0 /* galaxy_refresher.gif in Resources */, 045C0F942D12CA5F00BD2DC0 /* galaxy_refresher.gif in Resources */,
045C0F952D12CA5F00BD2DC0 /* area.plist in Resources */, 045C0F952D12CA5F00BD2DC0 /* area.plist in Resources */,
045C0F962D12CA5F00BD2DC0 /* Assets.xcassets in Resources */, 045C0F962D12CA5F00BD2DC0 /* Assets.xcassets in Resources */,
047A96812D151B3C0033BB4E /* main.jsbundle in Resources */,
045C0F972D12CA5F00BD2DC0 /* YHQuestionList.plist in Resources */, 045C0F972D12CA5F00BD2DC0 /* YHQuestionList.plist in Resources */,
045C0F982D12CA5F00BD2DC0 /* AlibabaPuHuiTi-Bold.ttf in Resources */, 045C0F982D12CA5F00BD2DC0 /* AlibabaPuHuiTi-Bold.ttf in Resources */,
045C0F992D12CA5F00BD2DC0 /* AlimamaShuHeiTi-Bold.ttf in Resources */, 045C0F992D12CA5F00BD2DC0 /* AlimamaShuHeiTi-Bold.ttf in Resources */,
...@@ -6269,6 +6279,7 @@ ...@@ -6269,6 +6279,7 @@
045C0FA12D12CA5F00BD2DC0 /* people_rotate.json in Resources */, 045C0FA12D12CA5F00BD2DC0 /* people_rotate.json in Resources */,
045C0FA22D12CA5F00BD2DC0 /* community.json in Resources */, 045C0FA22D12CA5F00BD2DC0 /* community.json in Resources */,
045C0FA32D12CA5F00BD2DC0 /* officalsuccess.gif in Resources */, 045C0FA32D12CA5F00BD2DC0 /* officalsuccess.gif in Resources */,
134448BA91456A66F447B18B /* PrivacyInfo.xcprivacy in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -6289,41 +6300,41 @@ ...@@ -6289,41 +6300,41 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
0CFB07298194FEC905CE2694 /* [CP] Embed Pods Frameworks */ = { A0B9C54FB2F64F568EF0BC88 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Copy Pods Resources";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources-${CONFIGURATION}-output-files.xcfilelist",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
47BB31035D3DBEB9235AC809 /* [CP] Copy Pods Resources */ = { C1342D35A3592DE7B5EF54BC /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Embed Pods Frameworks";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks-${CONFIGURATION}-output-files.xcfilelist",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-resources.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-galaxy/Pods-galaxy-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
7D00420CA535917A84A0A43E /* [CP] Check Pods Manifest.lock */ = { CEBE5659282DCD0474CE9E93 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
...@@ -6611,6 +6622,7 @@ ...@@ -6611,6 +6622,7 @@
045C10972D12CA5F00BD2DC0 /* YHMaterialListCell.swift in Sources */, 045C10972D12CA5F00BD2DC0 /* YHMaterialListCell.swift in Sources */,
045C10982D12CA5F00BD2DC0 /* YHTravelDocsPreparationListModel.swift in Sources */, 045C10982D12CA5F00BD2DC0 /* YHTravelDocsPreparationListModel.swift in Sources */,
045C10992D12CA5F00BD2DC0 /* YHCertificateAppointOptionCell.swift in Sources */, 045C10992D12CA5F00BD2DC0 /* YHCertificateAppointOptionCell.swift in Sources */,
047A967D2D150DA10033BB4E /* YHTestRNViewController.swift in Sources */,
045C109A2D12CA5F00BD2DC0 /* YhCacheTool.swift in Sources */, 045C109A2D12CA5F00BD2DC0 /* YhCacheTool.swift in Sources */,
045C109B2D12CA5F00BD2DC0 /* YHHomeInfoDetailViewController.swift in Sources */, 045C109B2D12CA5F00BD2DC0 /* YHHomeInfoDetailViewController.swift in Sources */,
045C109C2D12CA5F00BD2DC0 /* YHAdopterChinaViewController.swift in Sources */, 045C109C2D12CA5F00BD2DC0 /* YHAdopterChinaViewController.swift in Sources */,
...@@ -7461,7 +7473,7 @@ ...@@ -7461,7 +7473,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_OBJC_WEAK = YES;
...@@ -7500,19 +7512,36 @@ ...@@ -7500,19 +7512,36 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx",
"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
USE_HERMES = true;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = TestEnv; name = TestEnv;
}; };
A53B61142BB19B840010B573 /* TestEnv */ = { A53B61142BB19B840010B573 /* TestEnv */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 19B28612265782F9DC1BE0B0 /* Pods-galaxy.testenv.xcconfig */; baseConfigurationReference = 977D00DB1E2D046DDBE24B4B /* Pods-galaxy.testenv.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
...@@ -7541,7 +7570,7 @@ ...@@ -7541,7 +7570,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard"; INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UIUserInterfaceStyle = Light; INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
...@@ -7605,7 +7634,7 @@ ...@@ -7605,7 +7634,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_OBJC_WEAK = YES;
...@@ -7644,19 +7673,36 @@ ...@@ -7644,19 +7673,36 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx",
"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
USE_HERMES = true;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = UatRelease; name = UatRelease;
}; };
A54B7CC92C3645ED00BBA593 /* UatRelease */ = { A54B7CC92C3645ED00BBA593 /* UatRelease */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = DF4796A13E2592E1653226DE /* Pods-galaxy.uatrelease.xcconfig */; baseConfigurationReference = E3B32258B6D8636984F97AD4 /* Pods-galaxy.uatrelease.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
...@@ -7685,7 +7731,7 @@ ...@@ -7685,7 +7731,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard"; INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UIUserInterfaceStyle = Light; INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
...@@ -7749,7 +7795,7 @@ ...@@ -7749,7 +7795,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_OBJC_WEAK = YES;
...@@ -7794,14 +7840,31 @@ ...@@ -7794,14 +7840,31 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx",
"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
USE_HERMES = true;
}; };
name = Debug; name = Debug;
}; };
...@@ -7812,7 +7875,7 @@ ...@@ -7812,7 +7875,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_OBJC_WEAK = YES;
...@@ -7851,19 +7914,36 @@ ...@@ -7851,19 +7914,36 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx",
"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers",
"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios",
);
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
USE_HERMES = true;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;
}; };
A5573EF92B317C0100D98EC0 /* Debug */ = { A5573EF92B317C0100D98EC0 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 58C2405158A4A6632D0E7460 /* Pods-galaxy.debug.xcconfig */; baseConfigurationReference = 6730861F2D1C34DDDD195940 /* Pods-galaxy.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
...@@ -7892,7 +7972,7 @@ ...@@ -7892,7 +7972,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard"; INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UIUserInterfaceStyle = Light; INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
...@@ -7910,7 +7990,7 @@ ...@@ -7910,7 +7990,7 @@
}; };
A5573EFA2B317C0100D98EC0 /* Release */ = { A5573EFA2B317C0100D98EC0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = B6BB01E4C5DB87B66F0ECE84 /* Pods-galaxy.release.xcconfig */; baseConfigurationReference = 0B72C229AEE1BEB0959F0A26 /* Pods-galaxy.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
...@@ -7939,7 +8019,7 @@ ...@@ -7939,7 +8019,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard"; INFOPLIST_KEY_UILaunchStoryboardName = "Launch Screen.storyboard";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UIUserInterfaceStyle = Light; INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
......
...@@ -18,13 +18,15 @@ import AGConnectCore ...@@ -18,13 +18,15 @@ import AGConnectCore
import AGConnectCredential import AGConnectCredential
import AGConnectAppLinking import AGConnectAppLinking
import HyphenateChat import HyphenateChat
import React_RCTAppDelegate
@main @main
class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate { class AppDelegate: RCTAppDelegate, WXApiDelegate {
var window: UIWindow? // var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.automaticallyLoadReactNativeWindow = false
Thread.sleep(forTimeInterval: 0.5) // 应产品同学Nick要求 启动页时间展示长点 self.moduleName = "galaxy"
//Thread.sleep(forTimeInterval: 0.5) // 应产品同学Nick要求 启动页时间展示长点
setupAudionConfig() setupAudionConfig()
...@@ -87,10 +89,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate { ...@@ -87,10 +89,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
//设置主窗口 //设置主窗口
setupRootVC() setupRootVC()
return true let result = super.application(application, didFinishLaunchingWithOptions: launchOptions)
return result
} }
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if let host = url.host, host.contains("platformId=wechat") { if let host = url.host, host.contains("platformId=wechat") {
return WXApi.handleOpen(url, delegate: self) return WXApi.handleOpen(url, delegate: self)
...@@ -105,11 +108,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate { ...@@ -105,11 +108,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
GKConfigure.setupDefault() GKConfigure.setupDefault()
} }
func application(_ application: UIApplication, handleOpen url: URL) -> Bool { override func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
return WXApi.handleOpen(url, delegate: self) return WXApi.handleOpen(url, delegate: self)
} }
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { override func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return WXApi.handleOpen(url, delegate: self) return WXApi.handleOpen(url, delegate: self)
} }
...@@ -119,7 +122,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate { ...@@ -119,7 +122,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
// return isAppLinking // return isAppLinking
// } // }
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
let isAppLinking = AGCAppLinking.instance().continueUserActivity(userActivity) let isAppLinking = AGCAppLinking.instance().continueUserActivity(userActivity)
return isAppLinking == false ? WXApi.handleOpenUniversalLink(userActivity, delegate: self) : true return isAppLinking == false ? WXApi.handleOpenUniversalLink(userActivity, delegate: self) : true
} }
...@@ -201,8 +204,8 @@ extension AppDelegate { ...@@ -201,8 +204,8 @@ extension AppDelegate {
} else { } else {
let nav = YHNavigationController(rootVC:YHStartPageViewController()) let nav = YHNavigationController(rootVC:YHStartPageViewController())
window = UIWindow(frame: UIScreen.main.bounds) window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = nav window.rootViewController = nav
window?.makeKeyAndVisible() window.makeKeyAndVisible()
} }
} }
...@@ -211,8 +214,8 @@ extension AppDelegate { ...@@ -211,8 +214,8 @@ extension AppDelegate {
func setupRootVCWithTabBar() { func setupRootVCWithTabBar() {
window = UIWindow(frame: UIScreen.main.bounds) window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = configTabBarController() window.rootViewController = configTabBarController()
window?.makeKeyAndVisible() window.makeKeyAndVisible()
if YHLoginManager.shared.needJumpToMsgTabFlag { if YHLoginManager.shared.needJumpToMsgTabFlag {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: { DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
...@@ -248,4 +251,17 @@ extension AppDelegate { ...@@ -248,4 +251,17 @@ extension AppDelegate {
print("error: \(error.localizedDescription)") print("error: \(error.localizedDescription)")
} }
} }
override func sourceURL(for bridge: RCTBridge) -> URL? {
self.bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
let setting = RCTBundleURLProvider.sharedSettings()
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
} }
...@@ -44,7 +44,7 @@ extension AppDelegate: JPUSHRegisterDelegate { ...@@ -44,7 +44,7 @@ extension AppDelegate: JPUSHRegisterDelegate {
} }
//系统获取Token //系统获取Token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenStr = deviceToken.map{String(format:"%02.2hhx", arguments: [$0]) }.joined() let deviceTokenStr = deviceToken.map{String(format:"%02.2hhx", arguments: [$0]) }.joined()
print("deviceToken:\(deviceTokenStr)") print("deviceToken:\(deviceTokenStr)")
JPUSHService.registerDeviceToken(deviceToken) JPUSHService.registerDeviceToken(deviceToken)
...@@ -52,7 +52,7 @@ extension AppDelegate: JPUSHRegisterDelegate { ...@@ -52,7 +52,7 @@ extension AppDelegate: JPUSHRegisterDelegate {
YHButlerServiceManager.shared.updateApnsToken(token: deviceToken) YHButlerServiceManager.shared.updateApnsToken(token: deviceToken)
} }
//获取token 失败 //获取token 失败
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { //可选 override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { //可选
print("did Fail To Register For Remote Notifications With Error: \(error)") print("did Fail To Register For Remote Notifications With Error: \(error)")
#if DEBUG #if DEBUG
...@@ -65,7 +65,7 @@ extension AppDelegate: JPUSHRegisterDelegate { ...@@ -65,7 +65,7 @@ extension AppDelegate: JPUSHRegisterDelegate {
} }
//点推送进来执行这个方法 //点推送进来执行这个方法
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
JPUSHService.handleRemoteNotification(userInfo) JPUSHService.handleRemoteNotification(userInfo)
completionHandler(UIBackgroundFetchResult.newData) completionHandler(UIBackgroundFetchResult.newData)
...@@ -78,7 +78,7 @@ extension AppDelegate: JPUSHRegisterDelegate { ...@@ -78,7 +78,7 @@ extension AppDelegate: JPUSHRegisterDelegate {
} }
//后台进前台 //后台进前台
func applicationWillEnterForeground(_ application: UIApplication) { override func applicationWillEnterForeground(_ application: UIApplication) {
DispatchQueue.main.async { DispatchQueue.main.async {
// 请求消息页面通知权限通知 // 请求消息页面通知权限通知
NotificationCenter.default.post(name: YhConstant.YhNotification.didReqeustNotifyPermissionNotification, object: nil) NotificationCenter.default.post(name: YhConstant.YhNotification.didReqeustNotifyPermissionNotification, object: nil)
......
...@@ -74,7 +74,7 @@ class YHAliYunLogManager { ...@@ -74,7 +74,7 @@ class YHAliYunLogManager {
return manager return manager
} }
func addLog(_ log: Log?) { func addLog(_ log: AliyunLog?) {
guard let log = log else { guard let log = log else {
print("Log is nil, not adding.") print("Log is nil, not adding.")
return return
...@@ -84,13 +84,13 @@ class YHAliYunLogManager { ...@@ -84,13 +84,13 @@ class YHAliYunLogManager {
} }
func addLog() { func addLog() {
let log = Log() let log = AliyunLog()
log.putContent("银河移动开发组效忠宣言", value: "坚决拥护龙的领导,团结在龙的周围,凡是龙的决策,我们都坚决维护,凡是龙的指示,我们都始终不渝地遵循") log.putContent("银河移动开发组效忠宣言", value: "坚决拥护龙的领导,团结在龙的周围,凡是龙的决策,我们都坚决维护,凡是龙的指示,我们都始终不渝地遵循")
client?.add(log) client?.add(log)
} }
func addModuleName(_ moduleName: YHModuleNameValue, remark: String) { func addModuleName(_ moduleName: YHModuleNameValue, remark: String) {
let log = Log() let log = AliyunLog()
addCommonInfoLog(log) addCommonInfoLog(log)
log.putContent(YHAliYunLogKey.moduleName.rawValue, value: moduleName.rawValue) log.putContent(YHAliYunLogKey.moduleName.rawValue, value: moduleName.rawValue)
log.putContent(YHAliYunLogKey.remark.rawValue, value: remark) log.putContent(YHAliYunLogKey.remark.rawValue, value: remark)
...@@ -98,14 +98,14 @@ class YHAliYunLogManager { ...@@ -98,14 +98,14 @@ class YHAliYunLogManager {
} }
func addModuleName(_ moduleName: YHModuleNameValue, remark: [AnyHashable:Any]) { func addModuleName(_ moduleName: YHModuleNameValue, remark: [AnyHashable:Any]) {
let log = Log() let log = AliyunLog()
addCommonInfoLog(log) addCommonInfoLog(log)
log.putContent(YHAliYunLogKey.moduleName.rawValue, value: moduleName.rawValue) log.putContent(YHAliYunLogKey.moduleName.rawValue, value: moduleName.rawValue)
log.putContent(YHAliYunLogKey.remark.rawValue, dictValue: remark) log.putContent(YHAliYunLogKey.remark.rawValue, dictValue: remark)
client?.add(log) client?.add(log)
} }
private func addCommonInfoLog(_ log: Log) { private func addCommonInfoLog(_ log: AliyunLog) {
// 当前登录用户的手机号码 // 当前登录用户的手机号码
if YHLoginManager.shared.isLogin(), let mobile = YHLoginManager.shared.userModel?.mobile, !mobile.isEmpty { if YHLoginManager.shared.isLogin(), let mobile = YHLoginManager.shared.userModel?.mobile, !mobile.isEmpty {
......
...@@ -36,7 +36,7 @@ enum YHPersonalModuleItemType: Int { ...@@ -36,7 +36,7 @@ enum YHPersonalModuleItemType: Int {
case myOrder //我的订单 双十一订单入口 case myOrder //我的订单 双十一订单入口
case mycart //我的订单 双十一订单入口 case mycart //我的订单 双十一订单入口
case serviceStep case serviceStep
//case liveEntryTest //直播入口 case rnTest //rn测试入口
} }
class PersonalModuleItem { class PersonalModuleItem {
...@@ -333,8 +333,8 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget { ...@@ -333,8 +333,8 @@ class YHMyViewController: YHBaseViewController, ConstraintRelatableTarget {
} }
// let item = PersonalModuleItem(icon: "mine_item_about_us", title: "直播测试入口".local, type: .liveEntryTest) let item = PersonalModuleItem(icon: "mine_item_about_us", title: "RN测试入口".local, type: .rnTest)
// items.append(item) items.append(item)
...@@ -465,6 +465,9 @@ extension YHMyViewController : UITableViewDelegate, UITableViewDataSource { ...@@ -465,6 +465,9 @@ extension YHMyViewController : UITableViewDelegate, UITableViewDataSource {
} }
case .serviceStep: case .serviceStep:
UIViewController.current?.tabBarController?.selectedIndex = 1 UIViewController.current?.tabBarController?.selectedIndex = 1
case .rnTest:
let vc = YHTestRNViewController()
self.navigationController?.pushViewController(vc)
default: default:
printLog("不需要响应") printLog("不需要响应")
} }
......
//
// YHTestRNViewController.swift
// galaxy
//
// Created by alexzzw on 2024/12/16.
// Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//
import React_RCTAppDelegate
import UIKit
class YHTestRNViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let factory = (RCTSharedApplication()?.delegate as? RCTAppDelegate)?.rootViewFactory
self.view = factory?.view(withModuleName: "galaxy")
}
}
...@@ -13,7 +13,7 @@ extension UIViewController { ...@@ -13,7 +13,7 @@ extension UIViewController {
// 获取当前正呈现的UIViewController // 获取当前正呈现的UIViewController
static var current:UIViewController? { static var current:UIViewController? {
let delegate = UIApplication.shared.delegate as? AppDelegate let delegate = UIApplication.shared.delegate as? AppDelegate
var current = delegate?.window?.rootViewController var current = delegate?.window.rootViewController
while (current?.presentedViewController != nil) { while (current?.presentedViewController != nil) {
current = current?.presentedViewController current = current?.presentedViewController
...@@ -32,7 +32,7 @@ extension UIViewController { ...@@ -32,7 +32,7 @@ extension UIViewController {
//获取UINavigationController的topViewController //获取UINavigationController的topViewController
static var navTopViewController: UIViewController? { static var navTopViewController: UIViewController? {
let delegate = UIApplication.shared.delegate as? AppDelegate let delegate = UIApplication.shared.delegate as? AppDelegate
var current = delegate?.window?.rootViewController var current = delegate?.window.rootViewController
if let tabbar = current as? UITabBarController , tabbar.selectedViewController != nil { if let tabbar = current as? UITabBarController , tabbar.selectedViewController != nil {
current = tabbar.selectedViewController current = tabbar.selectedViewController
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>agc_applinking_not_read_pasteboard</key> <key>agc_applinking_not_read_pasteboard</key>
<false/> <false/>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment