From f8f80a07afd45d60c2975bfd7e4b859fb8c10a96 Mon Sep 17 00:00:00 2001 From: Lassi Marttala Date: Wed, 16 May 2012 10:10:12 +0200 Subject: [GDLT-67] dlt-system v2.0, check full commit message for rebase details [GDLT-67] Prepare build system. [GDLT-67] Config parsing, structure for thread handling [GDLT-67] Finalize configuration reading. [GDLT-67] Reimplementation of syslog, logfile, logprocess, shell. [GDLT-67] First complete version of the new dlt-system. [GDLT-67] Fixed header comments. authors, file names. [GDLT-67] Final touches. [GDLT-67] Fixed a problem with thread creation in optimized release binary. [GDLT-67] New configuration file. [GDLT-67] Added dlt debug output Signed-off-by: Christian Muck --- src/system/dlt-system-filetransfer.c | 317 +++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 src/system/dlt-system-filetransfer.c (limited to 'src/system/dlt-system-filetransfer.c') diff --git a/src/system/dlt-system-filetransfer.c b/src/system/dlt-system-filetransfer.c new file mode 100644 index 0000000..b05fc39 --- /dev/null +++ b/src/system/dlt-system-filetransfer.c @@ -0,0 +1,317 @@ +/** + * @licence app begin@ + * Copyright (C) 2012 BMW AG + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * Contributions are licensed to the GENIVI Alliance under one or more + * Contribution License Agreements. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Lassi Marttala BMW 2012 + * + * \file dlt-system-filetransfer.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt-system-filetransfer.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Lassi Marttala ** +** Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** +** ** +** PURPOSE : ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlt-system.h" +#include "dlt.h" +#include "dlt_filetransfer.h" + +#define INOTIFY_SZ (sizeof(struct inotify_event)) +#define INOTIFY_LEN (INOTIFY_SZ + 256) +#define Z_CHUNK_SZ 1024*128 + +extern DltSystemThreads threads; +// From dlt_filetransfer +extern unsigned long getFileSerialNumber(const char* file); + +DLT_IMPORT_CONTEXT(dltsystem); +DLT_DECLARE_CONTEXT(filetransferContext) + +typedef struct { + int handle; + int fd[DLT_SYSTEM_LOG_DIRS_MAX]; +} s_ft_inotify; + +s_ft_inotify ino; + +char *unique_name(const char *src) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, creating unique temporary file name.")); + time_t t = time(NULL); + unsigned long l = getFileSerialNumber(src) ^ t; + // Length of ULONG_MAX + 1 + char *ret = malloc(11); + snprintf(ret, 11, "%lu", l); + return ret; +} + +char *compress_file(char *src, int level) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, compressing file.")); + char *buf; + char *dst = malloc(strlen(src)+4); + char dst_mode[8]; + sprintf(dst, "%s.gz", src); + sprintf(dst_mode, "wb%d", level); + + gzFile dst_file; + FILE *src_file; + + dst_file = gzopen(dst, dst_mode); + if(dst_file < 0) + { + free(dst); + return NULL; + } + + src_file = fopen(src, "r"); + + if(src_file < 0) + { + gzclose(dst_file); + free(dst); + return NULL; + } + + buf = malloc(Z_CHUNK_SZ); + + while(!feof(src_file)) + { + int read = fread(buf, 1, Z_CHUNK_SZ, src_file); + if(ferror(src_file)) + { + free(buf); + free(dst); + gzclose(dst_file); + return NULL; + } + gzwrite(dst_file, buf, read); + } + + remove(src); + free(buf); + fclose(src_file); + gzclose(dst_file); + return dst; +} + +int send_one(char *src, FiletransferOptions opts, int which) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, sending a file.")); + sleep(opts.TimeDelay); + + // Prepare all needed file names + char *fn = basename(src); + char *rn = unique_name(src); + char *dst = malloc(strlen(opts.TempDir)+strlen(rn)+2); + sprintf(dst, "%s/%s", opts.TempDir, rn); + rename(src, dst); + + // Compress if needed + if(opts.Compression[which] > 0) + { + dst = compress_file(dst, opts.CompressionLevel[which]); + char *old_fn = fn; + fn = malloc(strlen(old_fn)+4); + sprintf(fn, "%s.gz", old_fn); + } + + if(dlt_user_log_file_header_alias(&filetransferContext, dst, fn) == 0) + { + int pkgcount = dlt_user_log_file_packagesCount(&filetransferContext, dst); + int lastpkg = 0; + while(lastpkg < pkgcount) + { + int total = 2; + int used = 2; + while(total-used < total/2) + { + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 1000*opts.TimeoutBetweenLogs; + nanosleep(&t, NULL); + dlt_user_check_buffer(&total, &used); + } + lastpkg++; + if(dlt_user_log_file_data(&filetransferContext, dst, lastpkg, opts.TimeoutBetweenLogs) < 0) + break; + } + dlt_user_log_file_end(&filetransferContext, dst, 1); + } + + if(opts.Compression[which] > 0) + free(fn); + free(rn); + free(dst); + return 0; +} + +int flush_dir(FiletransferOptions opts, int which) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, flush directory of old files.")); + const char *sdir = opts.Directory[which]; + char *fn; + struct dirent *dp; + DIR *dir; + + dir = opendir(sdir); + if(dir > 0) + { + while((dp = readdir(dir)) != NULL) + { + if(dp->d_type != DT_REG) + continue; + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, old file found in directory.")); + fn = malloc(strlen(sdir)+dp->d_reclen+2); + sprintf(fn, "%s/%s", sdir, dp->d_name); + if(send_one(fn, opts, which) < 0) + return -1; + } + } + closedir(dir); + return 0; +} + +int init_filetransfer_dirs(FiletransferOptions opts) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, + DLT_STRING("dlt-system-filetransfer, initializing inotify on directories.")); + ino.handle = inotify_init(); + int i; + + if(ino.handle < 0) + { + DLT_LOG(filetransferContext, DLT_LOG_FATAL, + DLT_STRING("Failed to initialize inotify in dlt-system file transfer.")); + return -1; + } + for(i = 0;i < opts.Count;i++) + { + ino.fd[i] = inotify_add_watch(ino.handle, opts.Directory[i], + IN_CLOSE_WRITE|IN_MOVED_TO); + if(ino.fd[i] < 0) + { + char buf[1024]; + snprintf(buf, 1024, "Failed to add inotify watch to directory %s in dlt-system file transfer.", + opts.Directory[i]); + DLT_LOG(filetransferContext, DLT_LOG_FATAL, + DLT_STRING(buf)); + return -1; + } + flush_dir(opts, i); + } + return 0; +} + +int wait_for_files(FiletransferOptions opts) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, waiting for files.")); + char buf[INOTIFY_LEN]; + int len = read(ino.handle, buf, INOTIFY_LEN); + if(len < 0) + { + DLT_LOG(filetransferContext, DLT_LOG_ERROR, + DLT_STRING("Error while waiting for files in dlt-system file transfer.")); + return -1; + } + + int i = 0; + while(ilen > 0) + { + if(ie->mask & IN_CLOSE_WRITE || ie->mask & IN_MOVED_TO) + { + int j; + for(j = 0;j < opts.Count;j++) + { + if(ie->wd == ino.fd[j]) + { + DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, found new file.")); + char *tosend = malloc(strlen(opts.Directory[j])+ie->len+1); + sprintf(tosend, "%s/%s", opts.Directory[j], ie->name); + send_one(tosend, opts, j); + free(tosend); + } + } + } + } + i += INOTIFY_SZ + ie->len; + } + return 0; +} + +void filetransfer_thread(void *v_conf) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, in thread.")); + DltSystemConfiguration *conf = (DltSystemConfiguration *) v_conf; + DLT_REGISTER_CONTEXT(filetransferContext, conf->Filetransfer.ContextId, + "File transfer manager."); + + sleep(conf->Filetransfer.TimeStartup); + + if(init_filetransfer_dirs(conf->Filetransfer) < 0) + return; + + while(!threads.shutdown) + { + if(wait_for_files(conf->Filetransfer) < 0) + return; + sleep(conf->Filetransfer.TimeDelay); + } +} + +void start_filetransfer(DltSystemConfiguration *conf) +{ + DLT_LOG(dltsystem, DLT_LOG_DEBUG, DLT_STRING("dlt-system-filetransfer, start.")); + static pthread_attr_t t_attr; + static pthread_t pt; + pthread_create(&pt, &t_attr, (void *)filetransfer_thread, conf); + threads.threads[threads.count++] = pt; +} -- cgit v1.2.1