📄 d2s_util.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* $Id: d2s_util.c,v 1.4 2002/09/27 21:11:13 toonen Exp $ * * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. *//******************** d2s_util.c ****************************//* This program converts a dlog file generated using DLOG Logging calls into an slog file.*//* a dlog file format: a record consists of a header which contains the timestamp, record type and process id. the headers are the same for all record types but the records themselves are different. this converter only pays attention to the following record types: DLOG_STATEDEF, DLOG_OPEN_EVENT, DLOG_ARROW_EVENT, DLOG_COMMEVENT.*/#include <stdio.h>#include <fcntl.h> #include <string.h>#include <stdlib.h>#if defined( HAVE_UNISTD_H )#include <unistd.h> #endif#include "dlog2slog.h"#include "slog.h"#include "mpi.h"#if defined( D2S_BYTESWAP )#undef D2S_BYTESWAP#endif/* the preprocessor variable STANDALONE should be defined when the file is compiled for standalone dlog2slog converter. Because byteswapping is needed to be done only in the converter. D2S_BYTESWAP = ! WORDS_BIGENDIAN*/#if defined( STANDALONE )# if ! defined( WORDS_BIGENDIAN )# define D2S_BYTESWAP# endif#endifstatic int proc_num = 0; static long num_events = 0;static int state_id = 1024; /* state id for dlog2slog independent of the dlog state id's.*/static struct state_info *first, /* pointers to the beginning and end */ *last; /* of the list of state defs.*/static struct state_info *pEventStateList;static struct list_elemnt *list_first, /* pointers to the beginning and end */ *list_last; /* of the list of start events. */static struct list_elemnt *msg_list_first, /* pointers to the beginning and end */ *msg_list_last; /* of the list of start events. */static SLOG slog; /* a handle to the slog format. *//* function prototypes */int logEvent(int, double, double, int);int logOpenEvent(DLOG_HEADER *, int, int);int logMsgEvent(DLOG_HEADER *, int, int);int handle_extra_state_defs(DLOG_OPEN_STATE *);int writeSLOGEvent(int state_id, double start_time, double end_time, int procid);int writeSLOGInterval(double, int, struct list_elemnt);int writeSLOGMsgInterval(double, int, int, struct list_elemnt);int handleStartEvent(int, double, int, int);int handleStartMsgEvent(int, double, int, int, int);int addEventState(int, char *, char *);int addState(int, int, int, char *, char *);int replace_state_in_list(int, int, char *, char *);int findState_strtEvnt(int);int findState_endEvnt(int);int addToList(int, int, int, double);int addToMsgList(int, int, int, int, double);int remove_element(int, int, int, struct list_elemnt *);int remove_msg_elemnt(int, int, int, int, struct list_elemnt *);void freeList(void);void freeMsgList(void);int get_new_state_id(void);/**** initialize dlog2slog data structures.****/int init_dlog2slog(char *dlog_file, char *slog_file){ char *pExt; first = NULL; last = NULL; list_first = NULL; list_last = NULL; msg_list_first = NULL; msg_list_last = NULL; pEventStateList = NULL; /* slog_file has the same name as the dlog file - the .dlog extension is changed to .slog extension. the file is created in the same directory as dlog file. */ strcpy(slog_file, dlog_file); pExt = strrchr(slog_file,'d'); if (pExt) *pExt = 's'; else strcat(slog_file, ".slog"); return D2S_SUCCESS;} /**** returns memory resources used by dlog2slog****/void DLOG_free_resources(){ DLOG_freeStateInfo(); freeList(); freeMsgList(); SLOG_CloseOutputStream( slog );} /**** the memory buffer read in from the dlog file is passed to this function the state definitions list initialized. the return value of this function represents the end of a dlog block or the end of the log itself. this function is only interested in DLOG_STATEDEF and DLOG_COMMEVENT. the others are ignored. DLOG_COMMEVENT helps to initialize the proc_num global variable which is used in the thread initialization. WARNING: to be used when a first pass is made for initializing state definitions.****/int DLOG_init_state_defs(char *filename){ DLOG_IOStruct *pInput; pInput = DLOG_CreateInputStruct(filename); if (pInput == NULL) { printf("DLOG_init_state_defs: Error, unable to create an input structure\n"); return D2S_ERROR; } do { switch(pInput->header.type) { case DLOG_EVENT_TYPE: case DLOG_OPEN_EVENT_TYPE: num_events++; break; case DLOG_COMM_TYPE: if (pInput->header.procid > proc_num) proc_num = pInput->header.procid; break; case DLOG_STATE_TYPE: if (addEventState( pInput->record.state.stateid, pInput->record.state.color, pInput->record.state.description) == D2S_ERROR) { DLOG_CloseInputStruct(&pInput); return D2S_ERROR; } break; case DLOG_OPEN_STATE_TYPE: if ( (findState_strtEvnt(pInput->record.ostate.endetype) == D2S_ERROR) || (findState_endEvnt(pInput->record.ostate.startetype) == D2S_ERROR) ) { if (addState( pInput->record.ostate.stateid, pInput->record.ostate.startetype, pInput->record.ostate.endetype, pInput->record.ostate.color, pInput->record.ostate.description) == D2S_ERROR) { DLOG_CloseInputStruct(&pInput); return D2S_ERROR; } } else { fprintf(stderr,__FILE__":%d: event ids defined for state %s already " "exist. Use MPE_Log_get_event_number() to define new event ids.\n", __LINE__, pInput->record.ostate.description); DLOG_CloseInputStruct(&pInput); return D2S_ERROR; } break; } } while (!DLOG_GetNextRecord(pInput)); if (addState(MSG_STATE, LOG_MESG_SEND, LOG_MESG_RECV, "White", "Message") == D2S_ERROR) { DLOG_CloseInputStruct(&pInput); return D2S_ERROR; } DLOG_CloseInputStruct(&pInput); return D2S_SUCCESS;}/**** initialization of slog when all state definitions and the number of processes and number of events are known.****/int init_SLOG (long num_frames, long frame_size, char *slog_file ){ long fixed_record_size, kilo_byte = 1024, error = D2S_SUCCESS; slog = SLOG_OpenOutputStream( slog_file ); if (slog == NULL) { fprintf(stderr, __FILE__":%d: SLOG_OpenOutputStream returns null - " "check SLOG documentation for more information.\n",__LINE__); DLOG_freeStateInfo(); return D2S_ERROR; } fixed_record_size = SLOG_typesz[ min_IntvlRec ] + SLOG_typesz[ taskID_t ]; /* calculating the number of frames that would be required to convert the dlog file. it is not possible to estimate this value for small frame byte sizes because the number of pseudo records in the slog file maybe much larger than the number of individual records. */ if (num_frames == 0) { num_frames = (num_events * fixed_record_size) / ((frame_size*kilo_byte)-SLOG_typesz[FrameHdr]); num_frames++; } SLOG_SetMaxNumOfFramesPerDir(slog, num_frames); SLOG_SetFrameByteSize(slog, frame_size*kilo_byte ); SLOG_SetFrameReservedSpace(slog, 0); SLOG_SetIncreasingEndtimeOrder(slog); /* this is of no use and should be taken out whenever the dependency on the file "SLOG_Preview.txt" gets removed */#ifndef HAVE_WINDOWS_H SLOG_SetPreviewName(slog,SLOG_PREVIEW_NAME);#endif /* initializing slog tread table, profiling and record definition table. */ error = init_SLOG_TTAB(); if (error == D2S_ERROR) return error; error = init_SLOG_PROF_RECDEF(); return error;}/**** initialize number of events and number of processes****/void DLOG_init_essential_values(long event_count, int process_count){ num_events = event_count; proc_num = process_count;}/**** this is the function which does all the logging in the second pass. it looks for DLOG_RAWEVENT types and then passes it on to the logOpenEvent function where all the details are handled.****/int DLOG_makeSLOG(char *filename){ DLOG_IOStruct *pInput; int result; pInput = DLOG_CreateInputStruct(filename); if (pInput == NULL) { printf("DLOG_init_state_defs: Error, unable to create an input structure\n"); return D2S_ERROR; } do { switch(pInput->header.type) { case DLOG_EVENT_TYPE: result = logEvent( pInput->record.event.event, pInput->record.event.start_time, pInput->record.event.end_time, pInput->header.procid); break; case DLOG_OPEN_EVENT_TYPE: result = logOpenEvent(&pInput->header, pInput->record.oevent.event, pInput->record.oevent.data); break; case DLOG_ARROW_TYPE: result = logMsgEvent(&pInput->header, pInput->record.arrow.event, pInput->record.arrow.data); break; case DLOG_OPEN_STATE_TYPE: result = handle_extra_state_defs(&pInput->record.ostate); break; } if (result == D2S_ERROR) { DLOG_CloseInputStruct(&pInput); return D2S_ERROR; } } while (DLOG_GetNextRecord(pInput) == 0); DLOG_CloseInputStruct(&pInput); return D2S_SUCCESS;}int logEvent(int event, double start_time, double end_time, int procid){ return writeSLOGEvent(event, start_time, end_time, procid);}/**** the most important function of all. this function takes the decision whether to add an event log into the start event list and reserve space in the slog file OR to match it with a matching start event in the list and log the interval. the arguments to the function include a pointer to the header of the event log as well as a pointer to the event log itself.****/int logOpenEvent(DLOG_HEADER *headr, int event, int data){ int stat_id; struct list_elemnt one; /* a structure that will contain information gathered from the start event list if there is a start event corresponding to the incoming event. */ if ( (stat_id = findState_strtEvnt(event)) != D2S_ERROR ) { /* if the above condition is true then we have run into a start event. now you know why that state definition list is so important. how else would one know if an event is a start event or an end event or neither. */ return handleStartEvent( stat_id, headr->timestamp, headr->procid, data ); } if ( (stat_id = findState_endEvnt(event)) != D2S_ERROR ) { /* if the above condition is true we have run into an end event. so now we find the corresponding start event in the start event list and log an slog interval. a lot of memory allocation and deallocation happening around this point. */ if ( remove_element(stat_id, data, headr->procid, &one) == D2S_ERROR ) { /* if the above condition is true then we haven't found a matching start event in the list of start events. hence there has been an error in the logging. an end event without a start event - definitely something wrong - either in this code or in the logging itself. Of course, if it is the other way around then it is ignored. but that case arises only when the list of start events is not empty at the end of the second pass. i havent taken it into account. */ fprintf( stderr, __FILE__":%d: couldnt find matching start event" ",state=%d,processid=%d,data=%d,timestamp=%f\n", __LINE__, stat_id, headr->procid, data, headr->timestamp ); return D2S_ERROR; } return writeSLOGInterval( headr->timestamp, headr->procid, one ); } return D2S_SUCCESS;}/**** the most important function of all. this function takes the decision whether to add an event log into the start event list and reserve space in the slog file OR to match it with a matching start event in the list and log the interval. the arguments to the function include a pointer to the header of the event log as well as a pointer to the event log itself.****/int logMsgEvent(DLOG_HEADER *headr, int event, int data){ int stat_id; struct list_elemnt one; /* a structure that will contain information gathered from the start event list if there is a start event corresponding to the incoming event. */ if (data == MPI_PROC_NULL) return D2S_SUCCESS; if ( (stat_id = findState_strtEvnt(event)) != D2S_ERROR ) { /* if the above condition is true then we have run into a start event. */ if ( remove_msg_elemnt( stat_id, data, headr->procid, event, &one ) == D2S_ERROR ) { return handleStartMsgEvent( stat_id, headr->timestamp, headr->procid, data, event ); } return writeSLOGMsgInterval( headr->timestamp, headr->procid, event, one ); } if ( (stat_id = findState_endEvnt(event)) != D2S_ERROR ) { /* if the above condition is true we have run into an end event. so now we find the corresponding start event in the start event list and log an slog interval. */ if ( remove_element(stat_id, data, headr->procid, &one) == D2S_ERROR ) { if ( remove_msg_elemnt( stat_id, data, headr->procid, event, &one ) == D2S_ERROR ) { return handleStartMsgEvent( stat_id, headr->timestamp, headr->procid, data, event ); } return writeSLOGMsgInterval( headr->timestamp, headr->procid, event, one ); } return writeSLOGMsgInterval( headr->timestamp, headr->procid, event, one ); } return D2S_SUCCESS;}/**** handles state definitions during parsing of log file when slog conversion begins.****/int handle_extra_state_defs(DLOG_OPEN_STATE *state){ SLOG_intvltype_t intvltype; SLOG_bebit_t bebit_0 = 1; SLOG_bebit_t bebit_1 = 1; SLOG_N_assocs_t Nassocs = 0; SLOG_N_args_t Nargs = 0; int ierr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -