void _SetSocketId(int sid) { /* entering critical zone */ int err = pthread_rwlock_wrlock(&socketIdLock); if (err != 0) zlog_fatal(gZlogCategories[ZLOG_MAIN], "_SetSocketId fail to acquire lock"); gActiveSocketId = sid; /* leaving critical zone */ err = pthread_rwlock_unlock(&socketIdLock); if (err != 0) zlog_fatal(gZlogCategories[ZLOG_MAIN], "_SetSocketId fail to release lock"); }
static int zmaster_server_accept(ZEVENT * zev, void *ctx) { int fd; int listen_fd; ___ACCEPT_CONTEXT *a_c; listen_fd = zev->fd; a_c = (___ACCEPT_CONTEXT *) ctx; if (a_c->type == 'i') { fd = zsocket_inet_accept(listen_fd); } else if (a_c->type == 'u') { fd = zsocket_unix_accept(listen_fd); } else { fd = listen_fd; } if (fd < 0) { if (errno != EAGAIN) { zlog_fatal("zmaster_server_accept: %m"); } return -1; } if ((a_c->type == 'i') || (a_c->type == 'u')) { zio_nonblocking(fd, 1); } if (a_c->callback) { a_c->callback(fd, a_c->ctx, a_c->type); } return 0; }
int UpdateReturnData() { /* pool size of the return data */ #define RETURN_DATA_POOL_SIZE 16 unsigned char buffer[RETURN_DATA_POOL_SIZE]; /* Returns data response set up by RadioNetwork module */ int size = RadioNetworkGetReturnData(buffer); if (size > 0) { zlog_debug(gZlogCategories[ZLOG_MAIN], "UpdateReturnData setting return data size -> %d", size); /* entering critical zone */ int err = pthread_rwlock_rdlock(&socketIdLock); if (err != 0) zlog_fatal(gZlogCategories[ZLOG_MAIN], "UpdateReturnData fail to acquire lock"); /** * locking the socket id does not prevent client from disconnecting, so this may still fail. * so, the right way to do this may be storing the socket id in the command, do not send if * socket id does not match. */ if (gActiveSocketId != 0) { zlog_debug(gZlogCategories[ZLOG_MAIN], "Sending return data to sid [%d]", gActiveSocketId); int ret = SocketServerSend(gActiveSocketId, buffer, size); if (ret > 0) { zlog_debug(gZlogCategories[ZLOG_MAIN], "[%d] bytes sent to sid [%d]", ret, gActiveSocketId); } if (ret != size) { zlog_warn(gZlogCategories[ZLOG_MAIN], "return data sent unsuccessfully with errno [%d]", errno); } } /* leaving critical zone */ err = pthread_rwlock_unlock(&socketIdLock); if (err != 0) zlog_fatal(gZlogCategories[ZLOG_MAIN], "UpdateReturnData fail to release lock"); } return size; }
dfv_repo_t* dfv_repo_open(int repo_id, const char* mnt_path, const char* dev_path, int flag) { struct stat info; int ret; char root_path[SPK_MAX_PATHNAME]; sprintf(root_path, "/%s/%s/%s", DFV_PREFIX_PATH, mnt_path, DFV_POSTFIX_PATH); ret = stat(root_path, &info); if (ret) { // root path not exist zlog_fatal(dfv_zc, "root_path not found: path=%s", root_path); return NULL; } dfv_repo_t* repo = malloc(sizeof(dfv_repo_t)); assert(repo); memset(repo, 0, sizeof(dfv_repo_t)); repo->repo_id = repo_id; strcpy(repo->root_path, root_path); strcpy(repo->mnt_path, mnt_path); if (dev_path) { strcpy(repo->dev_path, dev_path); } sprintf(repo->meta_path, "%s/.meta", root_path); ret = dfv_rmeta_load(&repo->rmeta, repo->meta_path); if (ret < 0) { zlog_warn(dfv_zc, "failed to load rmeta: path=%s, ret=%d", repo->meta_path, ret); dfv_rmeta_reset(&repo->rmeta); dfv_rmeta_save(&repo->rmeta, repo->meta_path); } zlog_notice(dfv_zc, "repo opened: id=%d, path=%s", repo_id, repo->root_path); dfv_rmeta_dump(ZLOG_LEVEL_NOTICE, &repo->rmeta); return(repo); }
static int __sys_job_do_config(sys_wkr_ctx_t* wkr_ctx, IPS_EPID src_id, int pc_id, char* config_buf, size_t buf_sz) { int ret = -1; #ifdef ARCH_ppc64 struct ips_pcctx* pcctx = NULL; int wkr_id = wkr_ctx->wkr_id; zlog_notice(sys_zc, "wkr#%d> prepare for config: ips={0x%x:%d}, config={0x%08x}+%lu", wkr_id, src_id, pc_id, *(uint32_t*)config_buf, buf_sz); // open ips srio pcctx = ips_chan_open(src_id, pc_id); if (!pcctx) { zlog_fatal(sys_zc, "wkr#%d> failed to open ips channel", wkr_id); ret = SPKERR_EACCESS; goto out; } zlog_notice(sys_zc, "wkr#%d> ---------- start config ----------", wkr_id); char *out_buf = NULL; size_t out_sz = 0; ret = ips_chan_config(pcctx, config_buf, buf_sz, &out_buf, &out_sz); memcpy(&sys_fpga_stat[wkr_id], (out_buf+8), sizeof(sys_fpga_stat[wkr_id])); free(out_buf); out: zlog_notice(sys_zc, "wkr#%d> ---------- stop config ---------- ret=%d", wkr_id, ret); // close ips srio if (pcctx) { ips_chan_close(pcctx); pcctx = NULL; } #endif return(ret); }
static void zmaster_server_register_one(char *service_str, ZMASTER_SERVER_SERVICE * service_list) { ZMASTER_SERVER_SERVICE *service; int type, sock_fd; ZEVENT *zev; ___ACCEPT_CONTEXT *a_c; char _service_str[1024]; char *stype, *uri, *p; strcpy(_service_str, service_str); stype = _service_str; p = strstr(_service_str, "://"); if (p) { *p = 0; uri = p + 3; } else { stype = "zdefault"; uri = _service_str; } if (!z_master_server_test_mode) { p = strchr(uri, ':'); if (p == 0) { zlog_fatal("%s: args error: %s", zvar_program_name, service_str); } *p = 0; type = *uri; sock_fd = atoi(p + 1); } else { char *host_path; int port; ___ziuf_parse(uri, type, host_path, port); if (type == ZSOCKET_TYPE_INET) { sock_fd = zsocket_inet_listen(host_path, port, -1); } else if (type == ZSOCKET_TYPE_UNIX) { sock_fd = zsocket_unix_listen(host_path, -1, 1, 0); } else if (type == ZSOCKET_TYPE_FIFO) { sock_fd = zsocket_fifo_listen(host_path, 1, 0); } else { sock_fd = -1; zlog_fatal("%s: args error: %s", zvar_program_name, service_str); } if (sock_fd < 0) { zlog_fatal("%s: open: %s error (%m)", zvar_program_name, service_str); } } service = zmaster_server_register_find_service(service_list, stype); if (service->raw_flag) { if (service->callback) { service->callback(sock_fd, service->ctx, type); } return; } a_c = (___ACCEPT_CONTEXT *) zmalloc(sizeof(___ACCEPT_CONTEXT)); a_c->callback = service->callback; a_c->type = type; a_c->ctx = service->ctx; zio_close_on_exec(sock_fd, 1); zio_nonblocking(sock_fd, 1); zev = (ZEVENT *) zmalloc(sizeof(ZEVENT)); zevent_init(zev, zvar_default_event_base, sock_fd); zevent_set(zev, ZEVENT_READ, zmaster_server_accept, a_c, 0); zarray_enter(z_master_server_listen_fd_list, ZINT_TO_VOID_PTR(sock_fd)); }
int cmi_intf_connect(cmi_intf_t* intf, const char* ipaddr, int port) { int sock_fd = -1; int ret = SPKERR_BADRES; struct sockaddr_in svr_addr; if (cmi_intf_is_connected(intf)) { return(SPKERR_BADSEQ); } // reset endian intf->endian_cur = intf->endian_req; zlog_notice(cmi_zc, "connecting interface: svraddr=%s:%d", ipaddr?ipaddr:"0.0.0.0", port); sock_fd = socket(AF_INET, (intf->intf_type == cmi_intf_tcp)?SOCK_STREAM:SOCK_DGRAM, 0); if (sock_fd < 0) { zlog_fatal(cmi_zc, "failed to create socket: errmsg=\'%s\'", strerror(errno)); goto errout; } if (intf->type == cmi_type_server) { // server // set SO_REUSEADDR int on = 1; setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); // bind socket memset(&svr_addr, 0, sizeof(svr_addr)); svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(port); svr_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock_fd, (struct sockaddr *)&svr_addr, sizeof(svr_addr)) < 0) { zlog_fatal(cmi_zc, "failed to bind socket: errmsg=\'%s\'", strerror(errno)); goto errout; } if (intf->intf_type == cmi_intf_tcp) { // tcp intf->sock_svr = sock_fd; sock_fd = -1; if (listen(intf->sock_svr, 1) < 0) { zlog_fatal(cmi_zc, "failed to listen: errmsg=\'%s\'", strerror(errno)); goto errout; } zlog_notice(cmi_zc, "tcp: waiting for accept ..."); socklen_t addr_len = sizeof(struct sockaddr_in); intf->conn_sockfd = accept(intf->sock_svr, (struct sockaddr *)&intf->conn_addr, &addr_len); if (intf->conn_sockfd < 0) { zlog_fatal(cmi_zc, "failed to accept: errmsg=\'%s\'", strerror(errno)); goto errout; } zlog_notice(cmi_zc, "connected from %s:%d via TCP", inet_ntoa(intf->conn_addr.sin_addr), htons(intf->conn_addr.sin_port)); zlog_notice(cmi_zc, "tcp: ready"); intf->conn_valid = 1; } else { // udp zlog_notice(cmi_zc, "udp: ready"); intf->conn_sockfd = sock_fd; sock_fd = -1; intf->conn_valid = 1; } } else { // client svr_addr.sin_family = AF_INET; svr_addr.sin_addr.s_addr = inet_addr(ipaddr); svr_addr.sin_port = htons(port); if (intf->intf_type == cmi_intf_tcp) { ret = connect(sock_fd, (struct sockaddr*)&svr_addr, sizeof(struct sockaddr_in)); if (ret < 0) { zlog_fatal(cmi_zc, "failed to connect to server: ip=%s:%d, errmsg=\'%s\'", ipaddr, port, strerror(errno)); goto errout; } } intf->conn_sockfd = sock_fd; sock_fd = -1; intf->conn_valid = 1; } if (intf->conn_sockfd > 0) { int x = fcntl(intf->conn_sockfd, F_GETFL, 0); fcntl(intf->conn_sockfd, F_SETFL, x | O_NONBLOCK); } #if 1 if (intf->conn_sockfd > 0) { int keepAlive = 1;//设定KeepAlive int keepIdle = 5;//开始首次KeepAlive探测前的TCP空闭时间 int keepInterval = 5;//两次KeepAlive探测间的时间间隔 int keepCount = 3;//判定断开前的KeepAlive探测次数 assert(setsockopt(intf->conn_sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive,sizeof(keepAlive)) >= 0); assert(setsockopt(intf->conn_sockfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle)) >= 0); assert(setsockopt(intf->conn_sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval)) >= 0); assert(setsockopt(intf->conn_sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount)) >= 0); } #endif zlog_notice(cmi_zc, "cmi interface connected: sock=%d", intf->conn_sockfd); return(SPK_SUCCESS); errout: if (sock_fd > 0) { close(sock_fd); } return(ret); }
int main(int argc, char** argv) { int rc; zlog_category_t *zc; int i = 0; struct stat stat_0, stat_1; /* Create the logging directory if not yet ceated */ mkdir("./test_multithread-logs", 0777); if (stat(CONFIG, &stat_0)) { printf("Configuration file not found\n"); return -1; } rc = zlog_init(CONFIG); if (rc) { printf("main init failed\n"); return -2; } zc = zlog_get_category("main"); if (!zc) { printf("main get cat fail\n"); zlog_fini(); return -3; } /* Interrupt (ANSI). <Ctrl-C> */ if (signal(SIGINT, intercept) == SIG_IGN ) { zlog_fatal(zc, "Can't caught the signal SIGINT, Interrupt (ANSI)"); signal(SIGINT, SIG_IGN ); return -4; } // start threads tinfo = calloc(NB_THREADS, sizeof(struct thread_info)); for (i=0; i<NB_THREADS; i++) { tinfo[i].thread_num = i + 1; tinfo[i].loop = 0; if(pthread_create(&tinfo[i].thread_id, NULL, myThread, &tinfo[i]) != 0) { zlog_fatal(zc, "Unable to start thread %d", i); zlog_fini(); return(-5); } } /* Wait and log thread informations */ sleep(1); for (i=0; i<NB_THREADS; i++) { zlog_info(zc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, tinfo[i].zc); } /* Log main loop status */ i=0; while(1) { int reload; sleep(1); i++; zlog_info(zc, "Running time: %02d:%02d:%02d", i/3600, (i/60)%60, i%60); /* Check configuration file update */ stat(CONFIG, &stat_1); /* Is configuration file modified */ reload = (stat_0.st_mtime != stat_1.st_mtime); /* Or do we want to reload periodicaly the configuration file */ if ( ! reload) if ( RELOAD_DELAY > 0) reload = (i % RELOAD_DELAY == 0); if (reload) { zlog_info(zc, "Will reload configuration..."); rc = zlog_reload(CONFIG); if (rc) { printf("main init failed\n"); return -6; } zlog_info(zc, "Configuration reloaded :)"); stat(CONFIG, &stat_0); } } exit(EXIT_SUCCESS); }
static int __sys_job_do_playback(sys_wkr_ctx_t* wkr_ctx, IPS_EPID src_id, int pc_id, size_t ips_sec_sz, dfv_slot_def_t* slot_def, uint64_t slot_sz) { int ret = -1; #ifdef ARCH_ppc64 struct ips_pcctx* pcctx = NULL; int wkr_id = wkr_ctx->wkr_id; spk_stats_t* stats = &wkr_ctx->stats; struct dfvcm_ctx* dfvcm = NULL; void * txbuf = NULL; size_t txbuf_sz = 0; int i; int dfv_cpu_base = 12+4*wkr_ctx->wkr_id; zlog_notice(sys_zc, "wkr#%d> prepare for playback: ips={0x%x:%d}, " "dfv={repo={%d:%d}, sz=%lu, cpu_base=%d}", wkr_id, src_id, pc_id, dfv_repo_get_id(slot_def->repo), slot_def->slot_id, slot_sz, dfv_cpu_base); // reset stats spk_stats_reset(stats); // open ips srio pcctx = ips_chan_open(src_id, pc_id); if (!pcctx) { zlog_fatal(sys_zc, "wkr#%d> failed to open ips channel", wkr_id); ret = SPKERR_EACCESS; goto out; } ret = ips_chan_start(pcctx, SPK_DIR_WRITE); if (ret != SPK_SUCCESS) { zlog_fatal(sys_zc, "wkr#%d> failed to start ips channel", wkr_id); goto out; } zlog_info(sys_zc, "wkr#%d> ips channel started for writing", wkr_id); // clean stats if (!(sys_env.features & SYSFEA_USE_LOCALSTATS)) { stats = ips_chan_get_stats(pcctx); } int dfvcm_buf_nodes = DFVCM_BUF_NODE_NUM;// // we use ips's tx_buffers directly (for zero-copy) // scratch bufs from ips txbuf = ips_chan_get_txbuf(pcctx, &txbuf_sz); // WARNING: IPS must allocated enough tx_buffer, so check it assert(txbuf && txbuf_sz >= dfvcm_buf_nodes*DFV_CHUNK_SIZE); // open dfv cache manager for read dfvcm = dfvcm_open(wkr_id, slot_def, SPK_DIR_READ, NULL, dfv_cpu_base); assert(dfvcm); dfv_bufq_node_t *local_node[DFVCM_BUF_NODE_NUM]; for (i=0; i<dfvcm_buf_nodes; i++) { // initialize buf nodes local_node[i] = malloc(sizeof(dfv_bufq_node_t)); assert(local_node[i]); memset(local_node[i], 0, sizeof(dfv_bufq_node_t)); // points to txbuf local_node[i]->buf_ptr = txbuf + i*DFV_CHUNK_SIZE; local_node[i]->buf_sz = DFV_CHUNK_SIZE; // enqueue to dfvcm's freeq // dfvcm will start reading immediatly dfv_bufq_enqueue(dfvcm_get_freeq(dfvcm), local_node[i]); zlog_notice(sys_zc, "wkr#%d> enqueue node to dfvcm: buf={%p+%zu}", wkr_id, local_node[i]->buf_ptr, local_node[i]->buf_sz); } // start playback zlog_notice(sys_zc, "wkr#%d> ---------- start playback ----------", wkr_id); uint64_t now = spk_get_tick_count(); uint64_t tm_log = now; ret = SPK_SUCCESS; uint64_t use_buf_num = 0; int current_buf_num = DFVCM_BUF_NODE_NUM; int dfv_status = 0; while(!wkr_ctx->reset_req) { // dequeue buffers from dfvcm if (dfvcm_get_eof(dfvcm)) { dfv_status=1; } dfv_bufq_node_t* node = dfv_bufq_dequeue(dfvcm_get_workq(dfvcm)); if (syslk_ips_mode.dma_use_chain) { if(current_buf_num <= (DFVCM_BUF_NODE_NUM/2)) { int free_buf_num = ips_chan_get_tx_freebn(pcctx, DFV_CHUNK_SIZE); if(free_buf_num > 0) { for(i=0; i<free_buf_num; i++) { int index = (use_buf_num % (DFVCM_BUF_NODE_NUM)); dfv_bufq_enqueue(dfvcm_get_freeq(dfvcm), local_node[index]); use_buf_num++; current_buf_num++; } } } } if (!node) { if (dfvcm_get_eof(dfvcm) && (dfv_status)) { break; } continue; } // got one node assert(node->valid_sz); // write to ips uint64_t tmout = spk_get_tick_count() + 5*1000; // timeout 5secs while(!wkr_ctx->reset_req) { ssize_t xfer = ips_chan_write(pcctx, node->buf_ptr, node->valid_sz); if (xfer == node->valid_sz) { // done if (!syslk_ips_mode.dma_use_chain) { spk_stats_inc_xfer(stats, node->valid_sz, 1); // recycle buffer to dfvcm dfv_bufq_enqueue(dfvcm_get_freeq(dfvcm), node); } else { spk_stats_inc_xfer(stats,node->valid_sz, 1); current_buf_num--;; } break; } if (xfer != 0) { zlog_error(sys_zc, "wkr#%d> failed to write to ips: xfer=%ld, expect=%ld", wkr_id, xfer, node->valid_sz); ret = SPKERR_EACCESS; goto out; } // nothing written spk_stats_inc_drop(stats, 0, 1); // just recored retried times if (spk_get_tick_count() > tmout) { // timeout zlog_error(sys_zc, "wkr#%d> write to ips timeout: xfer=%ld, expect=%ld", wkr_id, xfer, node->valid_sz); ret = SPKERR_EACCESS; goto out; } usleep(100); }; now = spk_get_tick_count(); if (now > tm_log) { zlog_notice(sys_zc, " wkr#%d> time=%lu pkts=%lu bytes=%lu spd:%.3f MBPS retried=%lu", wkr_id, spk_stats_get_time_elapsed(stats)/1000, spk_stats_get_xfer_pkts(stats), spk_stats_get_xfer_bytes(stats), BYTE2MB(spk_stats_get_bps_overall(stats)), spk_stats_get_drop_pkts(stats)); tm_log = now + 10*1000; } } if (wkr_ctx->reset_req || dfvcm_get_eof(dfvcm) > 0) ret = SPK_SUCCESS; else ret = dfvcm_get_eof(dfvcm); out: zlog_notice(sys_zc, "wkr#%d> ---------- stop playback ---------- ret=%d", wkr_id, ret); if (stats) { zlog_notice(sys_zc, "wkr#%d> elapsed=%lu, pkts=%lu, bytes=%lu, retried=%lu", wkr_id, spk_stats_get_time_elapsed(stats)/1000, stats->xfer.pkts, stats->xfer.bytes, stats->drop.bytes); } // close dfv cache manager if (dfvcm) { dfvcm_close(dfvcm, 0); dfvcm = NULL; } // close ips srio if (pcctx) { ips_chan_close(pcctx); pcctx = NULL; } #endif return(ret); }
static int __sys_job_do_record(sys_wkr_ctx_t* wkr_ctx, IPS_EPID src_id, int pc_id, size_t ips_sec_sz, dfv_slot_def_t* slot_def, dfv_slice_def_t* slice_def) { int ret = -1; #ifdef ARCH_ppc64 struct ips_pcctx* pcctx = NULL; struct dfv_file* file_ctx = NULL; int wkr_id = wkr_ctx->wkr_id; spk_stats_t* stats = &wkr_ctx->stats; void* chunk_buf = NULL; size_t chunk_size = slice_def->size * slice_def->num; int dfv_cpu_base = 12+4*wkr_ctx->wkr_id; zlog_notice(sys_zc, "wkr#%d> prepare for recording: ips={0x%x:%d}, dfv={repo={%d:%d}, " "slice={%d, 0x%lx}, cpu_base=%d}", wkr_id, src_id, pc_id, dfv_repo_get_id(slot_def->repo), slot_def->slot_id, slice_def->num, slice_def->size, dfv_cpu_base); // reset stats spk_stats_reset(stats); // open dfv slot file_ctx = dfv_file_open(slot_def->repo, slot_def->slot_id, SPK_DIR_WRITE, slice_def, dfv_cpu_base); if (!file_ctx) { zlog_fatal(sys_zc, "wkr#%d> failed to open dfv file", wkr_id); ret = SPKERR_BADRES; goto out; } // write to dfv #if 0 if (!(sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK)) { size_t warmup_sz = 128*1024*1024; size_t xferred = 0; void * txbuf = NULL; txbuf = memalign(SYS_INTERLACE_SIZE, DFV_CHUNK_SIZE); assert(txbuf); memset(txbuf, 0xfe, DFV_CHUNK_SIZE); while(xferred < warmup_sz) { ssize_t xfer = dfv_file_write(file_ctx, txbuf, DFV_CHUNK_SIZE); if (xfer != DFV_CHUNK_SIZE) { zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%u", wkr_id, xfer, DFV_CHUNK_SIZE); ret = SPKERR_EACCESS; SAFE_RELEASE(txbuf); goto out; } xferred += xfer; } dfv_file_seek(file_ctx, 0); SAFE_RELEASE(txbuf); } zlog_notice(sys_zc, "wkr#%d> dfv warmup done", wkr_id); #endif // open ips srio pcctx = ips_chan_open(src_id, pc_id); if (!pcctx) { zlog_fatal(sys_zc, "wkr#%d> failed to open ips channel", wkr_id); ret = SPKERR_EACCESS; goto out; } ret = ips_chan_start(pcctx, SPK_DIR_READ); if (ret != SPK_SUCCESS) { zlog_fatal(sys_zc, "wkr#%d> failed to start ips channel", wkr_id); goto out; } zlog_info(sys_zc, "wkr#%d> ips channel started for reading", wkr_id); // start recording uint64_t now = spk_get_tick_count(); uint64_t tm_upstats = now; uint64_t tm_log = now; uint64_t tm_heartbeat = now; ret = SPK_SUCCESS; size_t xfer; zlog_notice(sys_zc, "wkr#%d> ---------- start recording ----------", wkr_id); while(!wkr_ctx->reset_req) { // read from ips for one chunk // FIXME: our link partner must have enough data // before being stopped ssize_t read_size = ips_chan_read(pcctx, &chunk_buf, chunk_size, chunk_size); if (read_size > 0) { // got a chunk from ips assert(read_size == chunk_size); // preserve first buf for snapshot use pthread_mutex_lock(&wkr_ctx->buf_snap_lock); memcpy(wkr_ctx->buf_snap, chunk_buf, SYS_SNAP_BUF_SZ); pthread_mutex_unlock(&wkr_ctx->buf_snap_lock); // write to dfv if (sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK) { xfer = chunk_size; } else { xfer = dfv_file_write(file_ctx, chunk_buf, read_size); } // notify ips to free buffer first ips_chan_free_buf(pcctx, read_size); if (xfer != read_size) { zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%lu", wkr_id, xfer, read_size); ret = SPKERR_EACCESS; break; } } else if (read_size == 0) { // no data if (sys_ctx.auto_rec) { if (spk_get_tick_count() - tm_heartbeat > SYS_AUTOSTOP_TIMEOUT*1000) { // timeout zlog_warn(sys_zc, "wkr#%d> no data received since last %d secs, stop.", wkr_id, SYS_AUTOSTOP_TIMEOUT); break; } } } else { // failed to got a chunk from ips zlog_fatal(sys_zc, "wkr#%d> failed to read from ips: read_size=%ld", wkr_id, read_size); ret = read_size; break; } tm_heartbeat = now = spk_get_tick_count(); // update local stats spk_stats_inc_xfer(stats, read_size, (read_size / ips_sec_sz)); if (now > tm_upstats) { if (!(sys_env.features & SYSFEA_USE_LOCALSTATS)) { // update channel stats sys_job_update_stats(pcctx, wkr_id); } tm_upstats = now + 1000; } if (now > tm_log) { zlog_notice(sys_zc, " wkr#%d> time=%lu pkts=%lu bytes=%lu ovfl=%lu spd=%.3f MBPS", wkr_id, spk_stats_get_time_elapsed(stats)/1000, spk_stats_get_xfer_pkts(stats), spk_stats_get_xfer_bytes(stats), spk_stats_get_overflow_bytes(stats), BYTE2MB(spk_stats_get_bps_overall(stats))); tm_log = now + 10*1000; } } // // stop recording // // 1. send stop to link partner int stop_ret = ips_chan_stop(pcctx); if (stop_ret != SPK_SUCCESS) { zlog_fatal(sys_zc, "wkr#%d> failed to close ips channel: ret=%d", wkr_id, stop_ret); ret = stop_ret; goto out; } // 2. drain remained data if (ret == SPK_SUCCESS) { // wait for link partner to do padding sleep(1); ssize_t tail_size; do { tail_size = ips_chan_read(pcctx, &chunk_buf, 0, chunk_size); if (tail_size <= 0) { // done break; } zlog_notice(sys_zc, "wkr#%d> got remained data: size=%zd", wkr_id, tail_size); // data must been padded to 64k alignment by link partner assert(!(tail_size & (0x10000-1))); // save remained data to dfv slot if (sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK) { xfer = tail_size; } else { xfer = dfv_file_write(file_ctx, chunk_buf, tail_size); } ips_chan_free_buf(pcctx, tail_size); if (xfer != tail_size) { zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%lu", wkr_id, xfer, tail_size); ret = SPKERR_EACCESS; goto out; } } while(1); } // 3. update chstat for last time if (!(sys_env.features & SYSFEA_USE_LOCALSTATS)) { sys_job_update_stats(pcctx, wkr_id); } out: zlog_notice(sys_zc, "wkr#%d> ---------- stop recording ---------- ret=%d,", wkr_id, ret); if (stats) { zlog_notice(sys_zc, "wkr#%d> elapsed=%lu, pkts=%lu, bytes=%lu, ovfl=%lu", wkr_id, spk_stats_get_time_elapsed(stats)/1000, stats->xfer.pkts, stats->xfer.bytes, stats->overflow.bytes); } // close dfv slot if (file_ctx) { dfv_file_close(file_ctx); file_ctx = NULL; } // close ips srio if (pcctx) { ips_chan_close(pcctx); pcctx = NULL; } #endif return(ret); }
static int sys_cmd_exec_startul(cmi_cmd_t* cmd) { sys_ctx_t* ctx = &sys_ctx; int i; int ret = -1; if (ctx->sys_state != sys_state_idle) { return(SPKERR_EAGAIN); } for (i=0; i<SYS_MAX_PIPES; i++) { if (ctx->ul_ctx_tbl[i]) { assert(0); } } int slot_id = dfv_vault_get_freeslot(ctx->vault); if (slot_id < 0) { ret = SPKERR_BADRES; goto errout; } for (i=0; i<SYS_MAX_PIPES; i++) { sys_ul_ctx_t* ul_ctx = malloc(sizeof(sys_ul_ctx_t)); assert(ul_ctx); memset(ul_ctx, 0, sizeof(sys_ul_ctx_t)); struct dfvcm_ctx* dfvcm = NULL; dfv_slot_def_t slot_def; slot_def.repo = dfv_vault_get_repo(ctx->vault, i); slot_def.slot_id = slot_id; dfv_slice_def_t slice_def; slice_def.num = DFV_SLICE_NUM; slice_def.size = DFV_SLICE_SIZE; dfvcm = dfvcm_open(i, &slot_def, SPK_DIR_WRITE, &slice_def, 16+i*DFV_SLICE_NUM); if (!dfvcm) { ret = SPKERR_BADRES; goto errout; } void* buf_ptr = memalign(SYS_INTERLACE_SIZE, DFV_CHUNK_SIZE); if (!buf_ptr) { zlog_fatal(sys_zc, "not enough memroy: size_req=0x%x", DFV_CHUNK_SIZE); assert(0); } dfv_bufq_node_t* node = malloc(sizeof(dfv_bufq_node_t)); assert(node); memset(node, 0, sizeof(dfv_bufq_node_t)); node->buf_ptr = buf_ptr; node->buf_sz = DFV_CHUNK_SIZE; dfv_bufq_t* freeq = dfvcm_get_freeq(dfvcm); dfv_bufq_enqueue(freeq, node); ul_ctx->dfvcm = dfvcm; ul_ctx->work_node = NULL; ctx->ul_ctx_tbl[i] = ul_ctx; } sys_change_state(sys_state_ul); return(SPK_SUCCESS); errout: sys_cmd_exec_stopul(NULL); return(ret); }
int main(int argc, char **argv) { int ret; int i; char msg_ibuf[CMI_MAX_MSGSIZE]; umask(022); // build assert assert(DFV_MAX_SLOTS == CMI_MAX_SLOTS); assert(IPS_MAX_FCNUM == CMI_MAX_FCNUM); assert(!(SYS_CACHE_SIZE % CMI_MAX_FRAGSIZE)); printf("\n"); printf("SSSSSSSSSS\n"); printf("SSSSSSSSSS\n"); printf("SSS SSS PPPPP AA RRRRR KK KK\n"); printf("SS SS SS PP PP AAAA RR RR KK KK\n"); printf("SS SSSSSS PP PP AA AA RR RR KK KK\n"); printf("SSS SSSSS PP PP AA AA RR RR KK KK\n"); printf("SSSS SSSS PPPPP AA AA RRRRR KKKK\n"); printf("SSSSS SSS PP AAAAAA RR RR KK KK\n"); printf("SSSSSS SS PP AA AA RR RR KK KK\n"); printf("SS SS SS PP AA AA RR RR KK KK\n"); printf("SSS SSS PP AA AA RR RR KK KK\n"); printf("SSSSSSSSSS \n"); printf("SSSSSSSSSS ==SYS: LK ==VER: %s\n", SYS_VERSION); printf("\n"); // initialize log system zlog_init("./zlog.conf"); sys_zc = zlog_get_category("SYS"); assert(sys_zc); zlog_notice(sys_zc, "------------------------------------------"); zlog_notice(sys_zc, "==> system starting ..."); zlog_notice(sys_zc, "==> dump system versions ..."); zlog_notice(sys_zc, " SYS: %s", SYS_VERSION); zlog_notice(sys_zc, " IPS: %s", IPS_MOD_VER); zlog_notice(sys_zc, " DFV: %s", DFV_MOD_VER); zlog_notice(sys_zc, " IDT: %s", IDT_MOD_VER); zlog_notice(sys_zc, " CMI: %s", CMI_MOD_VER); // initialize env // TBD: should be read from .conf zlog_notice(sys_zc, "> loading conf ..."); memset(&sys_env, 0, sizeof(sys_env)); sys_env.features = SYSFEA_USE_LOCALSTATS; sys_env.intf_type = cmi_intf_tcp; sys_env.endian = cmi_endian_auto; sys_env.ipaddr = NULL; sys_env.port = 1235; sys_env.dfv_desc_tbl[0].mnt_path = "sdb"; sys_env.dfv_desc_tbl[0].dev_path = "sdb"; sys_env.dfv_desc_tbl[0].flag = 0; sys_env.dfv_desc_tbl[1].mnt_path = "sdf"; sys_env.dfv_desc_tbl[1].dev_path = "sdf"; sys_env.dfv_desc_tbl[1].flag = 0; sys_env.ips_linkdesc_tbl[0].mst_id = IPS_MAKE_EPID(IPS_EPMODE_MASTER, 0, 0); sys_env.ips_linkdesc_tbl[0].slv_id = IPS_MAKE_EPID(IPS_EPMODE_SLAVE, 0, 0); sys_env.ips_linkdesc_tbl[0].mst_port = 1; sys_env.ips_linkdesc_tbl[0].slv_port = 6; sys_env.ips_linkdesc_tbl[0].is_master = 1; sys_env.ips_linkdesc_tbl[1].mst_id = IPS_MAKE_EPID(IPS_EPMODE_MASTER, 0, 1); sys_env.ips_linkdesc_tbl[1].slv_id = IPS_MAKE_EPID(IPS_EPMODE_SLAVE, 0, 1); sys_env.ips_linkdesc_tbl[1].mst_port = 4; sys_env.ips_linkdesc_tbl[1].slv_port = 3; sys_env.ips_linkdesc_tbl[1].is_master = 1; assert(sys_env.ips_linkdesc_tbl[0].is_master); // I am master assert(sys_env.ips_linkdesc_tbl[1].is_master); // I am master sys_env.ips_desc_tbl[0].capacity = 0; sys_env.ips_desc_tbl[0].pc_num = 1; for (i = 0; i < 1; i++) { ips_pcdesc_t* pcdesc = &sys_env.ips_desc_tbl[0].pcdesc_tbl[i]; pcdesc->src_id = sys_env.ips_linkdesc_tbl[0].mst_id; pcdesc->dest_id = sys_env.ips_linkdesc_tbl[0].slv_id; pcdesc->sector_sz = IPS_CLS_SECTOR_SIZE; pcdesc->sector_num = IPS_CLS_SECTOR_NUM; } sys_env.ips_desc_tbl[1].capacity = 0; sys_env.ips_desc_tbl[1].pc_num = 1; for (i = 0; i < 1; i++) { ips_pcdesc_t* pcdesc = &sys_env.ips_desc_tbl[1].pcdesc_tbl[i]; pcdesc->src_id = sys_env.ips_linkdesc_tbl[1].mst_id; pcdesc->dest_id = sys_env.ips_linkdesc_tbl[1].slv_id; pcdesc->sector_sz = IPS_CLS_SECTOR_SIZE; pcdesc->sector_num = IPS_CLS_SECTOR_NUM; } // initialize each module zlog_notice(sys_zc, "==> initializing modules ..."); #ifdef ARCH_ppc64 ret = ips_module_init(NULL); assert(!ret); ret = idt_module_init(NULL); assert(!ret); #endif ret = dfv_module_init(NULL); assert(!ret); ret = cmi_module_init(NULL); assert(!ret); //init ips mode syslk_parse_ips_mode("./syslk_ips.conf"); ips_init_mode(syslk_ips_mode); zlog_notice(sys_zc,"dma_use_nlwr:%d dma_use_chain:%d tx_wmd:%d tx_rmd:%d rx_wmd:%d rx_rmd:%d", syslk_ips_mode.dma_use_nlwr, syslk_ips_mode.dma_use_chain, syslk_ips_mode.tx.use_wptr, syslk_ips_mode.tx.use_rptr, syslk_ips_mode.rx.use_wptr, syslk_ips_mode.rx.use_rptr); // initialize ctxs memset(&sys_ctx, 0, sizeof(sys_ctx)); zlog_notice(sys_zc, "==> initializing storage ..."); const char* repo_mnt_tbl[DFV_MAX_REPOS] = {NULL}; const char* repo_dev_tbl[DFV_MAX_REPOS] = {NULL}; for (i=0; i<SYS_MAX_PIPES; i++) { repo_mnt_tbl[i] = sys_env.dfv_desc_tbl[i].mnt_path; repo_dev_tbl[i] = sys_env.dfv_desc_tbl[i].dev_path; } sys_ctx.vault = dfv_vault_open(SYS_MAX_PIPES, DFV_SLICE_NUM, repo_mnt_tbl, repo_dev_tbl, 0); if (!sys_ctx.vault) { zlog_fatal(sys_zc, "failed to initializing storage, quit"); exit(-1); } sys_ctx.diskcap = dfv_vault_get_diskcap(sys_ctx.vault); // check freeslot int slot_id = dfv_vault_get_freeslot(sys_ctx.vault); if (slot_id < 0) { zlog_fatal(sys_zc, "no spece left on vault, quit"); exit(-1); } #ifdef ARCH_ppc64 zlog_notice(sys_zc, "==> initializing switch route table ..."); int idt_fd = idt_dev_open(2, 0x67); assert(idt_fd > 0); for (i=0; i<SYS_MAX_PIPES; i++) { ips_linkdesc_t* linkdesc = &sys_env.ips_linkdesc_tbl[i]; // reset link parnter // idt_port_recovery(idt_fd, linkdesc->slv_port); // reset routetbl entries idt_routetbl_set(idt_fd, linkdesc->mst_port, linkdesc->slv_id, linkdesc->slv_port); idt_routetbl_set(idt_fd, linkdesc->slv_port, linkdesc->mst_id, linkdesc->mst_port); } idt_dev_close(idt_fd); zlog_notice(sys_zc, "==> initializing srio ..."); for (i=0; i<SYS_MAX_PIPES; i++) { // init repo zlog_notice(sys_zc, " initializing ips_srio: pipe=%d, id=0x%x", i, sys_env.ips_linkdesc_tbl[i].mst_id); ret = ips_ep_init(sys_env.ips_linkdesc_tbl[i].mst_id, &sys_env.ips_desc_tbl[i]); assert(!ret); } #endif sys_ctx.file_cache = malloc(sizeof(sys_cache_t)); assert(sys_ctx.file_cache); memset(sys_ctx.file_cache, 0, sizeof(sys_cache_t)); sys_ctx.file_cache->slot_id = -1; sys_ctx.file_cache->data = malloc(SYS_CACHE_SIZE); assert(sys_ctx.file_cache->data); zlog_notice(sys_zc, "==> initializing job workers ..."); for (i=0; i<SYS_MAX_PIPES; i++) { sys_wkr_ctx_t* wkr_ctx = malloc(sizeof(sys_wkr_ctx_t)); assert(wkr_ctx); memset(wkr_ctx, 0, sizeof(sys_wkr_ctx_t)); wkr_ctx->wkr_state = sys_state_idle; wkr_ctx->wkr_id = i; pthread_mutex_init(&wkr_ctx->buf_snap_lock, NULL); sys_jobq_init(&wkr_ctx->job_in); sys_jobq_init(&wkr_ctx->job_out); wkr_ctx->wkr_thread = malloc(sizeof(pthread_t)); assert(wkr_ctx->wkr_thread); sys_ctx.wkr_ctx_tbl[i] = wkr_ctx; pthread_create(wkr_ctx->wkr_thread, NULL, __sys_wkr_job, (void*)wkr_ctx); } sys_ctx.auto_rec = 0; if (sys_ctx.auto_rec) { pthread_t thread_autorec; pthread_create(&thread_autorec, NULL, __sys_wkr_autorec, NULL); } RECONN: zlog_notice(sys_zc, "==> ---------- SERVER START ----------"); // stop all workers for (i=0; i<SYS_MAX_PIPES; i++) { sys_wkr_ctx_t* wkr_ctx = sys_ctx.wkr_ctx_tbl[i]; if (wkr_ctx->wkr_state != sys_state_idle) { zlog_notice(sys_zc, "==> stopping job worker#%d ...", i); wkr_ctx->reset_req = 1; while(wkr_ctx->wkr_state != sys_state_idle) { usleep(100); } } } sys_cmd_exec_stopul(NULL); if (sys_ctx.cmi_intf) { zlog_notice(sys_zc, "==> closing client cmi ..."); cmi_intf_close(sys_ctx.cmi_intf); sys_ctx.cmi_intf = NULL; } if (sys_ctx.sysdown_req) { goto out; } // open cmi zlog_notice(sys_zc, "==> opening client cmi ..."); sys_ctx.cmi_intf = cmi_intf_open(cmi_type_server, sys_env.intf_type, sys_env.endian); if (!sys_ctx.cmi_intf) { assert(0); exit(-1); } zlog_notice(sys_zc, "==> connecting client cmi ..."); ret = cmi_intf_connect(sys_ctx.cmi_intf, sys_env.ipaddr, sys_env.port); if (ret != SPK_SUCCESS) { assert(0); exit(-1); } while(1) { // main loop // update sys_state if (!sys_ctx.auto_rec) { // some jobs are done by job workers // we do not known when they finished // so we inquiry workers state in some states switch(sys_ctx.sys_state) { case sys_state_rec: case sys_state_play: case sys_state_dl: case sys_state_format: { int all_idle = 1; for (int i=0; i<SYS_MAX_PIPES; i++) { sys_wkr_ctx_t* wkr_ctx = sys_ctx.wkr_ctx_tbl[i]; if (wkr_ctx && wkr_ctx->wkr_state != sys_state_idle) { all_idle = 0; } } if (all_idle) { sys_change_state(sys_state_idle); } } break; } } // get message from cmi ssize_t msg_size = cmi_intf_read_msg(sys_ctx.cmi_intf, msg_ibuf, CMI_MAX_MSGSIZE); if (msg_size < 0) { zlog_warn(sys_zc, "failed to read from socket: ret=%ld", msg_size); goto RECONN; } if (msg_size == 0) { usleep(100); continue; } // msg arrived // cmi_msg_dump(ZLOG_LEVEL_NOTICE, msg_ibuf, msg_size); // zlog_notice(sys_zc, "> read msg: code=0x%x, size=%ld", MSG_CODE(msg_ibuf), msg_size); // notify auto_rec_thread() to quit sys_ctx.auto_rec = 0; ret = SPK_SUCCESS; // parse msg switch(MSG_CODE(msg_ibuf)) { case msg_code_cmd: ret = sys_cmd_exec((cmi_cmd_t*)msg_ibuf, msg_size); break; case msg_code_data: ret = sys_msg_parse_data((cmi_data_t*)msg_ibuf, msg_size); break; case msg_code_cmdresp: case msg_code_status: default: // impossible assert(0); break; } if (ret == SPKERR_RESETSYS) { zlog_warn(sys_zc, "socket error, restart"); goto RECONN; } if (sys_ctx.sysdown_req) { zlog_notice(sys_zc, "################# SYSTEM SHUTDOWN"); spk_os_exec("poweroff"); goto RECONN; } // TODO: other ret code } out: for (i=0; i<SYS_MAX_PIPES; i++) { sys_wkr_ctx_t* wkr_ctx = sys_ctx.wkr_ctx_tbl[i]; if (wkr_ctx) { wkr_ctx->quit_req = 1; pthread_join(*wkr_ctx->wkr_thread, NULL); SAFE_RELEASE(wkr_ctx->wkr_thread); SAFE_RELEASE(wkr_ctx); } } return 0; }
void hustlog_write_fatal(zlog_category_t * category, const char * data) { zlog_fatal(category, "%s", data); }
void saveFile(const std::string& data) { //zlog_fatal(zc,"filename:%s", "this is a test save"); zlog_fatal(zc,"save file:%s", data.c_str()); }
net_handle_t * net_open(const char *ipaddr,int port,int slice_num,int cpu_base,int dir,net_intf_type type) { int sock_fd; int ret = SPKERR_BADRES; //struct sockaddr_in svr_addr; int i=0; int flags; // create ctx net_handle_t* file_ctx = NULL; file_ctx = malloc(sizeof(net_handle_t)); assert(file_ctx); memset(file_ctx, 0, sizeof(net_handle_t)); file_ctx->slice_num = slice_num; file_ctx->dir = dir; //net_intf_type type=net_intf_udp; // spawn workers for (i=0; i<slice_num; i++) { net_slice_ctx_t* slice_ctx = malloc(sizeof(net_slice_ctx_t)); assert(slice_ctx); memset(slice_ctx, 0, sizeof(net_slice_ctx_t)); slice_ctx->slice_id = i; slice_ctx->dir = dir; slice_ctx->slice_sz=0x4000;//128K slice_ctx->slice_num=slice_num;//4 slice_ctx->type=type;// tcp or udp pthread_mutex_init(&slice_ctx->lock, NULL); pthread_cond_init(&slice_ctx->not_full, NULL); pthread_cond_init(&slice_ctx->not_empty, NULL); slice_ctx->wkr_thread = malloc(sizeof(pthread_t)); sock_fd = socket(AF_INET,(type == net_intf_tcp)?SOCK_STREAM:SOCK_DGRAM,0);//tcp?udp => SOCK_STREAM?SOCK_DGRAM if (sock_fd < 0) { zlog_fatal(net_zc, "failed to create socket: errmsg=\'%s\'", strerror(errno)); goto errout; } int sock_buf_size=0x5c00; ret = setsockopt(sock_fd,SOL_SOCKET,SO_SNDBUF,(char *)&sock_buf_size,sizeof(sock_buf_size)); sock_buf_size=0x15800; ret = setsockopt(sock_fd,SOL_SOCKET,SO_RCVBUF,(char *)&sock_buf_size,sizeof(sock_buf_size)); slice_ctx->svr_addr.sin_family = AF_INET; slice_ctx->svr_addr.sin_addr.s_addr = inet_addr(ipaddr); slice_ctx->svr_addr.sin_port = htons(port); if (type == net_intf_tcp) { ret = connect(sock_fd,(struct sockaddr*)&slice_ctx->svr_addr, sizeof(struct sockaddr_in)); if (ret < 0) { zlog_fatal(net_zc, "failed to connect to server: ip=%s:%d, errmsg=\'%s\'",ipaddr, port, strerror(errno)); goto errout; } } if(sock_fd > 0) { flags = fcntl(sock_fd,F_GETFL,0);//获取建立的sockfd的当前状态(非阻塞) fcntl(sock_fd,F_SETFL,flags|O_NONBLOCK);//将当前sockfd设置为非阻塞 } zlog_info(net_zc, "net connect successful: id=%d, sockfd=%d", i,sock_fd); file_ctx->conn_valid[i]=1; slice_ctx->fd = sock_fd; file_ctx->slice_tbl[i] = slice_ctx; slice_ctx->cpu_base = cpu_base; pthread_create(slice_ctx->wkr_thread, NULL, __net_slice_worker, slice_ctx); } if (file_ctx) { spk_stats_reset(&file_ctx->xfer_stats); } errout: return (file_ctx); }
int main(void) { int error; pthread_t command_processor_pid; /* Initializes zlog first.*/ if ((error = zLogInit()) != 0) { return error; } /* Parses ini file for config. */ memset(&gAppConfig, 0, sizeof(AppConfig)); if (ini_parse(INI_FILENAME, iniHandler, &gAppConfig) < 0) { zlog_fatal(gZlogCategories[ZLOG_MAIN], "Can't load '%s'\n", INI_FILENAME); return 1; } /* Initializes SocketServer */ SocketServerConfig config; config.eventHandler = SSECallback; config.port = gAppConfig.uServerPort; zlog_info(gZlogCategories[ZLOG_MAIN], "Initializing SocketServer on port %d\n", config.port); SocketServerInit(&config); /* Initializes local XBee radio */ XBeeRadioInit(&gAppConfig.xbeeRadioConfig); /* Initializes Radio Network */ RadioNetworkInit(&gAppConfig.radioNetworkConfig); _SocketIdInit(); /* Initializes command processing thread with default settings */ pthread_create(&command_processor_pid, NULL, &RadioNetworkProcessCommandQueue, UpdateReturnData); SocketServerStart(); SocketServerRun(); /* Wait to join the command processing thread */ pthread_join(command_processor_pid, NULL); _SocketIdDestroy(); SocketServerStop(); SocketServerDestroy(); /* Destroys Radio Network */ RadioNetworkDestroy(); /* Destroys local XBee radio */ XBeeRadioDestroy(); zLogDestroy(); /* final clean ups of memory */ FinalCleanup(); return 0; }