More functions converted to use threaded file handling:
- check_path_exists_hdl(..)
- This is the first inc for error handling updates.
diff --git a/README_LOGENH b/README_LOGENH
new file mode 100644
--- /dev/null
+++ b/README_LOGENH
@@ -0,0 +1,36 @@
+DESCRIPTION OF ONGOING ENHANCEMENT
+----------------------------------
+
+See ticket #9 and #124. The main problem to solve ist to prevent the log
service to "hang",
+including e.g. not beeing able to handle health check etc. when the
communication with a
+NFS file system is broken.
+
+This is not done by creating a thread for each stream and asynch IO is not
used either, as
+suggested in #9.
+This enhancement creates a second thread and functions or parts of functions
using file IO
+are moved to this thread.
+
+The enhancement is done i three steps:
+1. Create a mechanism that can handle functions with in and out parameters
and that times out
+ if such a function does not return "hangs". See lgs_file.c
+
+2. Use 1. to handle already existing complete functions or parts of functions
that has any type
+ of interaction with the file system. This is done without changing any of
the existing structure
+ of the log service. Affected functions remains "as is" with the same in
and out parameters as before,
+ but internally all or some of the code is moved to a "handler" that is
running in the second thread.
+ The original function will now return with error instead of "hang" if an
operation including file IO
+ "hangs". See lgs_filehdl.c, lgs_stream.c and lgs_util.c
+
+3. Handle new error situations that may occur. Log streams can now be created
and opened even if the
+ corresponding files cannot be handled. If a stream is opened without
creating files an attempt to
+ create the files is done when a client tries to write a log record.
+ In this version the callback function will report "TRY AGAIN" if the
logserver fails to write the
+ log record. This is the same behaviour as before, the only difference is
that i may happen also if
+ there is communication problems with the file system.
+
+TODO
+----
+
+Handling of streams via IMM objects has to be improved. E.g. Some admin
operations must be rejected if
+the filsystem is not available e.g. creating a new stream with a configuration
object.
+
diff --git a/osaf/services/saf/logsv/lgs/lgs.h
b/osaf/services/saf/logsv/lgs/lgs.h
--- a/osaf/services/saf/logsv/lgs/lgs.h
+++ b/osaf/services/saf/logsv/lgs/lgs.h
@@ -75,6 +75,12 @@
/* The name of log service config object */
#define LGS_IMM_LOG_CONFIGURATION "logConfig=1,safApp=safLogService"
+/* The maximum size of a path to a file. A path normally consists of
+ * a root path (PATH_MAX), a relative path (PATH_MAX) and a file name
(NAME_MAX)
+ */
+#define LGS_FILEPATH_MAX (PATH_MAX + PATH_MAX + NAME_MAX)
+#define LGS_DIRPATH_MAX (PATH_MAX + PATH_MAX)
+
/* ========================================================================
* TYPE DEFINITIONS
* ========================================================================
diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.c
b/osaf/services/saf/logsv/lgs/lgs_evt.c
--- a/osaf/services/saf/logsv/lgs/lgs_evt.c
+++ b/osaf/services/saf/logsv/lgs/lgs_evt.c
@@ -707,6 +707,10 @@ static uint32_t lgs_ckpt_stream_open(lgs
ckpt.ckpt_rec.stream_open.streamType = logStream->streamType;
ckpt.ckpt_rec.stream_open.logRecordId = logStream->logRecordId;
+
+ ckpt.ckpt_rec.stream_open.files_initiated =
logStream->files_initiated;
+ TRACE("LLDTEST2: %s - logFileCurrent
\"%s\"",__FUNCTION__,logStream->logFileCurrent);
+ TRACE("LLDTEST2: %s - files_initiated =
%d",__FUNCTION__,logStream->files_initiated);
async_rc = lgs_ckpt_send_async(cb, &ckpt, NCS_MBCSV_ACT_ADD);
if (async_rc == NCSCC_RC_SUCCESS) {
@@ -1082,6 +1086,9 @@ static uint32_t proc_write_log_async_msg
ckpt.ckpt_rec.write_log.streamId = stream->streamId;
ckpt.ckpt_rec.write_log.curFileSize = stream->curFileSize;
ckpt.ckpt_rec.write_log.logFileCurrent = stream->logFileCurrent;
+ ckpt.ckpt_rec.write_log.files_initiated =
stream->files_initiated;
+ TRACE("LLDTEST2: %s - logFileCurrent
\"%s\"",__FUNCTION__,stream->logFileCurrent);
+ TRACE("LLDTEST2: %s - files_initiated =
%d",__FUNCTION__,stream->files_initiated);
(void)lgs_ckpt_send_async(cb, &ckpt, NCS_MBCSV_ACT_ADD);
}
diff --git a/osaf/services/saf/logsv/lgs/lgs_file.c
b/osaf/services/saf/logsv/lgs/lgs_file.c
--- a/osaf/services/saf/logsv/lgs/lgs_file.c
+++ b/osaf/services/saf/logsv/lgs/lgs_file.c
@@ -123,6 +123,12 @@ static void *file_hndl_thread(void *nopa
void *outbuf;
uint32_t max_outsize;
+//#define LLD_DELAY_TST
+#ifdef LLD_DELAY_TST /* LLDTEST Let "file system" hang for n sec after start */
+ static bool lld_start_f = true;
+ const unsigned int lld_sleep_sec = 3600;
+#endif
+
TRACE("LLDTEST: %s - is started",__FUNCTION__);
osaf_mutex_lock_ordie(&lgs_ftcom_mutex); /* LOCK */
@@ -159,6 +165,16 @@ static void *file_hndl_thread(void *nopa
* assumed to know the data format.
*/
osaf_mutex_unlock_ordie(&lgs_ftcom_mutex); /* UNLOCK */
+
+#ifdef LLD_DELAY_TST /* LLDTEST Wait first time thread is used */
+ if (lld_start_f == true) {
+ lld_start_f = false;
+ TRACE("LLDTEST1: file_hndl_thread sleeping");
+ sleep(lld_sleep_sec);
+ goto lld_wait_end;
+ }
+#endif
+
switch (lgs_com_data.request_code) {
case LGSF_FILEOPEN:
TRACE("LLDTEST: %s - LGSF_FILEOPEN
received",__FUNCTION__);
@@ -192,9 +208,18 @@ static void *file_hndl_thread(void *nopa
TRACE("LLDTEST: %s - LGSF_RENAME_FILE
received",__FUNCTION__);
hndl_rc = rename_file_hdl(inbuf, outbuf,
max_outsize);
break;
+ case LGSF_CHECKPATH:
+ TRACE("LLDTEST: %s - LGSF_CHECKPATH
received",__FUNCTION__);
+ hndl_rc = check_path_exists_hdl(inbuf, outbuf,
max_outsize);
default:
break;
}
+
+#ifdef LLD_DELAY_TST
+ lld_wait_end:
+ TRACE("LLDTEST1: file_hndl_thread is awake!");
+#endif
+
osaf_mutex_lock_ordie(&lgs_ftcom_mutex); /* LOCK */
/* Handle answer flag and return data
@@ -224,8 +249,8 @@ static void *file_hndl_thread(void *nopa
} else {
free(outbuf);
}
- }
- }
+ }
+ } /* End while(1) */
}
/**
@@ -311,7 +336,8 @@ lgsf_retcode_t log_file_api(lgsf_apipar_
*/
if (lgs_com_data.request_f == true) {
api_rc = LGSF_BUSY;
- goto done;
+ TRACE("LLDTEST: %s - LGSF_BUSY",__FUNCTION__);
+ goto api_exit;
}
/* Enter data for a request */
@@ -331,7 +357,7 @@ lgsf_retcode_t log_file_api(lgsf_apipar_
}
lgs_com_data.outdata_size = apipar_in->data_out_size;
- lgs_com_data.request_f = true; /* We have a request */
+ lgs_com_data.request_f = true; /* We have a pending request */
lgs_com_data.timeout_f = false;
/* Wake up the thread */
@@ -382,8 +408,10 @@ lgsf_retcode_t log_file_api(lgsf_apipar_
done:
/* Prepare for new request/answer cycle */
- free(lgs_com_data.indata);
- free(lgs_com_data.outdata);
+ if (lgs_com_data.indata != NULL) free(lgs_com_data.indata);
+ if (lgs_com_data.outdata != NULL) free(lgs_com_data.outdata);
+
+api_exit:
osaf_mutex_unlock_ordie(&lgs_ftcom_mutex); /* UNLOCK */
TRACE_LEAVE2("LLDTEST");
return api_rc;
diff --git a/osaf/services/saf/logsv/lgs/lgs_file.h
b/osaf/services/saf/logsv/lgs/lgs_file.h
--- a/osaf/services/saf/logsv/lgs/lgs_file.h
+++ b/osaf/services/saf/logsv/lgs/lgs_file.h
@@ -44,6 +44,7 @@ typedef enum {
LGSF_WRITELOGREC,
LGSF_CREATECFGFILE,
LGSF_RENAME_FILE,
+ LGSF_CHECKPATH,
LGSF_NOREQ
}lgsf_treq_t;
diff --git a/osaf/services/saf/logsv/lgs/lgs_filehdl.c
b/osaf/services/saf/logsv/lgs/lgs_filehdl.c
--- a/osaf/services/saf/logsv/lgs/lgs_filehdl.c
+++ b/osaf/services/saf/logsv/lgs/lgs_filehdl.c
@@ -56,6 +56,24 @@
*****************************************************************************/
/**
+ * Check if a path exists. See also stat(..)
+ *
+ * @param indata[in] path[]
+ * @param outdata[out] Not used
+ * @param max_outsize[in] Must be 0
+ * @return (-1) if not exists, 0 if exists
+ */
+int check_path_exists_hdl(void *indata, void *outdata, size_t max_outsize)
+{
+ struct stat pathstat;
+ char *path_str = (char *) indata;
+ int rc = 0;
+
+ rc = stat(path_str, &pathstat);
+ return rc;
+}
+
+/**
* Rename a file
*
* @param indata[in] old_path[], new_path[]
@@ -211,7 +229,7 @@ int make_log_dir_hdl(void *indata, void
char *relpath = params_in->rel_path;
char *rootpath = params_in->root_dir;
char dir_to_make[PATH_MAX + PATH_MAX+2];
- char mpath[PATH_MAX+1];
+ char mpath[PATH_MAX + PATH_MAX+2];
char *spath_p;
char *epath_p;
struct stat statbuf;
@@ -235,6 +253,7 @@ int make_log_dir_hdl(void *indata, void
strncpy(out_path, rootpath, max_outsize);
#endif
LOG_NO("LOG Root path does not exist. Will be created");
+ TRACE("LLDTEST: %s - create rootpath
\"%s\"",__FUNCTION__,rootpath);
}
/* Create complete path string */
@@ -432,7 +451,7 @@ int get_number_of_log_files_hdl(void *in
{
struct dirent **namelist;
int n, old_date = -1, old_time = -1, old_ind = -1, files, i, failed = 0;
- char path[PATH_MAX];
+ char path[LGS_DIRPATH_MAX];
gnolfh_in_t *params_in;
char *oldest_file;
int rc;
@@ -445,9 +464,9 @@ int get_number_of_log_files_hdl(void *in
/* Initialize the filter */
strncpy(file_prefix, params_in->file_name, NAME_MAX);
- n = snprintf(path, PATH_MAX, "%s/%s",
+ n = snprintf(path, LGS_DIRPATH_MAX, "%s/%s",
params_in->logsv_root_dir, params_in->pathName);
- if (n >= PATH_MAX) {
+ if (n >= LGS_DIRPATH_MAX) {
LOG_ER("Parameter error: Path is longer than PATH_MAX");
rc = -1;
goto done_exit;
diff --git a/osaf/services/saf/logsv/lgs/lgs_filehdl.h
b/osaf/services/saf/logsv/lgs/lgs_filehdl.h
--- a/osaf/services/saf/logsv/lgs/lgs_filehdl.h
+++ b/osaf/services/saf/logsv/lgs/lgs_filehdl.h
@@ -124,6 +124,16 @@ typedef struct {
* No out parameters
*/
+/*
+ * check_path_exists_hdl(..)
+ *
+ * Inpar:
+ * char path_str[], string containing path to check
+ *
+ * No out parameters
+ */
+
+int check_path_exists_hdl(void *indata, void *outdata, size_t max_outsize);
int rename_file_hdl(void *indata, void *outdata, size_t max_outsize);
int create_config_file_hdl(void *indata, void *outdata, size_t max_outsize);
int write_log_record_hdl(void *indata, void *outdata, size_t max_outsize);
diff --git a/osaf/services/saf/logsv/lgs/lgs_imm.c
b/osaf/services/saf/logsv/lgs/lgs_imm.c
--- a/osaf/services/saf/logsv/lgs/lgs_imm.c
+++ b/osaf/services/saf/logsv/lgs/lgs_imm.c
@@ -15,6 +15,17 @@
*
*/
+/*****************************************************************************
+ * Important information
+ * ---------------------
+ * To prevent log service thread from "hanging" if communication with NFS is
+ * not working or is very slow all functions using file I/O must run their file
+ * handling in a separate thread.
+ * For more information on how to do that see the following files:
+ * lgs_file.h, lgs_file.c, lgs_filendl.c and lgs_filehdl.h
+ * Examples can be found in file lgs_stream.c, e.g. function fileopen(...)
+ */
+
#include <poll.h>
#include <stdio.h>
#include <errno.h>
@@ -179,7 +190,7 @@ static uint32_t ckpt_stream_open_close(l
* return: true = Path is valid
* false = Path is invalid
*/
-static bool path_is_writeable_dir(const char *pathname)
+static bool path_is_writeable_dir_fop(const char *pathname)
{
bool is_writeable_dir = false;
struct stat pathstat;
@@ -412,7 +423,7 @@ static SaAisErrorT config_ccb_completed_
if (!strcmp(attribute->attrName, "logRootDirectory")) {
char *pathName = *((char **)value);
- if (!path_is_writeable_dir(pathName)) {
+ if (!path_is_writeable_dir_fop(pathName)) {
LOG_NO("pathName: %s is NOT accepted",
pathName);
rc = SA_AIS_ERR_BAD_OPERATION;
goto done;
@@ -497,7 +508,7 @@ static SaAisErrorT config_ccb_completed(
*
* @return SaAisErrorT
*/
-static SaAisErrorT check_attr_validity(const struct CcbUtilOperationData
*opdata)
+static SaAisErrorT check_attr_validity_fop(const struct CcbUtilOperationData
*opdata)
{
SaAisErrorT rc = SA_AIS_OK;
void *value;
@@ -525,16 +536,13 @@ static SaAisErrorT check_attr_validity(c
TRACE("attribute %s", attribute->attrName);
if (!strcmp(attribute->attrName,
"saLogStreamFileName")) {
- struct stat pathstat;
char *fileName = *((char **) value);
- if (stat(fileName, &pathstat) == 0) {
-
+ if (lgs_check_path_exists(fileName) == 0) {
LOG_ER("File %s already exist",
fileName);
rc = SA_AIS_ERR_EXIST;
}
TRACE("fileName: %s", fileName);
} else if (!strcmp(attribute->attrName,
"saLogStreamPathName")) {
- struct stat pathstat;
char fileName[PATH_MAX];
strcpy(fileName, lgs_cb->logsv_root_dir);
strcat(fileName, "//");
@@ -543,7 +551,7 @@ static SaAisErrorT check_attr_validity(c
if (lgs_relative_path_check_ts(fileName)) {
LOG_ER("Path %s not valid", fileName);
rc = SA_AIS_ERR_INVALID_PARAM;
- } else if (stat(lgs_cb->logsv_root_dir,
&pathstat) != 0) {
+ } else if
(lgs_check_path_exists(lgs_cb->logsv_root_dir) != 0) {
LOG_ER("Path %s does not exist",
fileName);
rc = SA_AIS_ERR_BAD_OPERATION;
}
@@ -643,7 +651,7 @@ static SaAisErrorT stream_ccb_completed_
SaAisErrorT rc = SA_AIS_ERR_BAD_OPERATION;
TRACE_ENTER2("CCB ID %llu", opdata->ccbId);
- rc = check_attr_validity(opdata);
+ rc = check_attr_validity_fop(opdata);
TRACE_LEAVE2("%u", rc);
return rc;
}
@@ -653,7 +661,7 @@ static SaAisErrorT stream_ccb_completed_
SaAisErrorT rc;
TRACE_ENTER2("CCB ID %llu, '%s'", opdata->ccbId,
opdata->objectName.value);
- rc = check_attr_validity(opdata);
+ rc = check_attr_validity_fop(opdata);
TRACE_LEAVE2("%u", rc);
return rc;
}
@@ -780,7 +788,7 @@ static SaAisErrorT ccbCompletedCallback(
*
* @param logRootDirectory
*/
-static void logRootDirectory_set(const char *logRootDirectory)
+static void logRootDirectory_set_hf(const char *logRootDirectory)
{
log_stream_t *stream;
char *current_time = lgs_get_time();
@@ -841,7 +849,7 @@ static void config_ccb_apply_modify(cons
const char *logRootDirectory = *((char **)value);
if (lgs_cb->ha_state == SA_AMF_HA_ACTIVE) {
- logRootDirectory_set(logRootDirectory);
+ logRootDirectory_set_hf(logRootDirectory);
} else {
strcpy(lgs_conf->logRootDirectory,
logRootDirectory);
}
@@ -873,7 +881,7 @@ static void config_ccb_apply(const CcbUt
osafassert(0);
break;
default:
- assert(0);
+ osafassert(0);
break;
}
@@ -1087,6 +1095,7 @@ static void stream_ccb_apply_delete(cons
/* Checkpoint to standby LOG server */
ckpt_stream_open_close(stream, LGS_CKPT_CLOSE_STREAM);
+ TRACE("LLDTEST: %s - log_stream_close_hfop()",__FUNCTION__);
log_stream_close_hfop(&stream);
}
@@ -1849,7 +1858,11 @@ SaAisErrorT lgs_imm_activate_hfop(lgs_cb
"saLogStreamCreationTimestamp",
SA_IMM_ATTR_SATIMET,
&cb->systemStream->creationTimeStamp);
- /* Open all streams */
+ /* Open all streams
+ * Config file and log file will be created. If this fails we give up
+ * without returning any error. A new attempt to create the files will
+ * be done when trying to write a log record to the stream.
+ */
stream = log_stream_getnext_by_name_nof(NULL);
while (stream != NULL) {
if (log_stream_open_fh(stream) != SA_AIS_OK)
diff --git a/osaf/services/saf/logsv/lgs/lgs_mbcsv.c
b/osaf/services/saf/logsv/lgs/lgs_mbcsv.c
--- a/osaf/services/saf/logsv/lgs/lgs_mbcsv.c
+++ b/osaf/services/saf/logsv/lgs/lgs_mbcsv.c
@@ -1095,6 +1095,9 @@ static uint32_t ckpt_proc_log_write(lgs_
stream->logRecordId = param->recordId;
stream->curFileSize = param->curFileSize;
strcpy(stream->logFileCurrent, param->logFileCurrent);
+ stream->files_initiated = param->files_initiated; /* LLDTEST */
+ TRACE("LLDTEST2: %s - logFileCurrent
\"%s\"",__FUNCTION__,stream->logFileCurrent);
+ TRACE("LLDTEST2 %s - stream->files_initiated =
%d",__FUNCTION__,stream->files_initiated);
done:
free_edu_mem(param->logFileCurrent);
@@ -1132,6 +1135,7 @@ static uint32_t ckpt_proc_close_stream(l
(void)lgs_client_stream_rmv(param->clientId, param->streamId);
+ TRACE("LLDTEST: %s - log_stream_close_hfop()",__FUNCTION__);
if (log_stream_close_hfop(&stream) != 0) {
/* Do not allow standby to get out of sync */
lgs_exit("Client attributes differ", SA_AMF_COMPONENT_RESTART);
@@ -1160,6 +1164,7 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
{
lgs_ckpt_stream_open_t *param = &data->ckpt_rec.stream_open;
log_stream_t *stream;
+ int lldi=1; /*LLDTEST remove*/
TRACE_ENTER();
@@ -1168,6 +1173,7 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
LOG_WA("Client %u does not exist, failed to create stream
'%s'", param->clientId, param->logStreamName);
goto done;
}
+ TRACE("LLDTEST1 - %d",lldi++);
stream = log_stream_get_by_name_nof(param->logStreamName);
if (stream != NULL) {
@@ -1184,18 +1190,24 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
strcpy((char *)name.value, param->logStreamName);
name.length = strlen(param->logStreamName);
+ TRACE("LLDTEST1 - %d",lldi++);
stream = log_stream_new_nof(&name, param->logFile,
param->logPath, param->maxFileSize, param->maxLogRecordSize,
param->logFileFullAction, param->maxFilesRotated, param->fileFmt,
param->streamType, param->streamId, SA_FALSE, // FIX sync or calculate?
param->logRecordId);
+ TRACE("LLDTEST1 - %d",lldi++);
if (stream == NULL) {
/* Do not allow standby to get out of sync */
LOG_ER("Failed to create stream '%s'",
param->logStreamName);
goto done;
}
+ TRACE("LLDTEST1 - %d",lldi++);
stream->numOpeners = param->numOpeners;
stream->creationTimeStamp = param->creationTimeStamp;
strcpy(stream->logFileCurrent, param->logFileCurrent);
+ stream->files_initiated = param->files_initiated; /* LLDTEST */
+ TRACE("LLDTEST2: %s - logFileCurrent
\"%s\"",__FUNCTION__,stream->logFileCurrent);
+ TRACE("LLDTEST2: %s - stream->files_initiated =
%d",__FUNCTION__,stream->files_initiated);
}
log_stream_print(stream);
@@ -1204,13 +1216,16 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
** Create an association between this client_id and the stream
** A client ID of -1 indicates that no client exist, skip this step.
*/
+ TRACE("LLDTEST1 - %d",lldi++);
if ((param->clientId != -1) && lgs_client_stream_add(param->clientId,
stream->streamId) != 0) {
/* Do not allow standby to get out of sync */
LOG_ER("Failed to add stream '%s' to client %u",
param->logStreamName, param->clientId);
lgs_exit("Could not add stream to client",
SA_AMF_COMPONENT_RESTART);
}
+ TRACE("LLDTEST1 - %d",lldi++);
done:
+ TRACE("LLDTEST1 - %d",lldi++);
/* Free strings allocated by the EDU encoder */
free_edu_mem(param->logFile);
free_edu_mem(param->logPath);
@@ -1319,6 +1334,9 @@ static uint32_t ckpt_proc_cfg_stream(lgs
strcpy(stream->logFileFormat, param->logFileFormat);
stream->severityFilter = param->severityFilter;
strcpy(stream->logFileCurrent, param->logFileCurrent);
+ stream->files_initiated = param->files_initiated;
+ TRACE("LLDTEST2: %s - logFileCurrent
\"%s\"",__FUNCTION__,stream->logFileCurrent);
+ TRACE("LLDTEST2 %s - files_initiated
=%d",__FUNCTION__,param->files_initiated);
done:
/* Free strings allocated by the EDU encoder */
@@ -1376,6 +1394,7 @@ uint32_t lgs_ckpt_send_async(lgs_cb_t *c
/* Send async update */
if (NCSCC_RC_SUCCESS != (rc = ncs_mbcsv_svc(&mbcsv_arg))) {
LOG_ER("MBCSV send FAILED rc=%u.", rc);
+ TRACE("LLDTEST2: %s - MBCSV send FAILED rc=%u.",__FUNCTION__,
rc);
TRACE_LEAVE();
return NCSCC_RC_FAILURE;
}
@@ -1567,9 +1586,12 @@ static uint32_t edp_ed_write_rec(EDU_HDL
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_write_log_t *)0)->streamId, 0, NULL},
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_write_log_t *)0)->curFileSize, 0, NULL},
{EDU_EXEC, ncs_edp_string, 0, 0, 0,
(long)&((lgs_ckpt_write_log_t *)0)->logFileCurrent, 0, NULL},
+ {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_write_log_t *)0)->files_initiated, 0, NULL},
{EDU_END, 0, 0, 0, 0, 0, 0, NULL},
};
+ TRACE("LLDTEST2: %s",__FUNCTION__);
+
if (op == EDP_OP_TYPE_ENC) {
ckpt_write_msg_ptr = (lgs_ckpt_write_log_t *)ptr;
} else if (op == EDP_OP_TYPE_DEC) {
@@ -1633,6 +1655,7 @@ static uint32_t edp_ed_open_stream_rec(E
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_open_t *)0)->numOpeners, 0, NULL},
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_open_t *)0)->streamType, 0, NULL},
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_open_t *)0)->logRecordId, 0, NULL},
+ {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_open_t *)0)->files_initiated, 0, NULL},
{EDU_END, 0, 0, 0, 0, 0, 0, NULL},
};
@@ -1800,6 +1823,7 @@ static uint32_t edp_ed_cfg_stream_rec(ED
{EDU_EXEC, ncs_edp_string, 0, 0, 0,
(long)&((lgs_ckpt_stream_cfg_t *)0)->logFileFormat, 0, NULL},
{EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_cfg_t *)0)->severityFilter, 0, NULL},
{EDU_EXEC, ncs_edp_string, 0, 0, 0,
(long)&((lgs_ckpt_stream_cfg_t *)0)->logFileCurrent, 0, NULL},
+ {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
(long)&((lgs_ckpt_stream_cfg_t *)0)->files_initiated , 0, NULL},
{EDU_END, 0, 0, 0, 0, 0, 0, NULL},
};
diff --git a/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
b/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
--- a/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
+++ b/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
@@ -60,6 +60,7 @@ typedef struct {
uint32_t recordId;
uint32_t curFileSize;
char *logFileCurrent;
+ bool files_initiated; /* LLDTEST */
} lgs_ckpt_write_log_t;
typedef struct {
@@ -80,6 +81,7 @@ typedef struct {
char *logFileCurrent;
logStreamTypeT streamType;
uint32_t logRecordId; /* log record indentifier increased for each
record */
+ bool files_initiated; /* LLDTEST */
} lgs_ckpt_stream_open_t;
typedef struct {
@@ -109,6 +111,7 @@ typedef struct {
char *logFileFormat;
SaUint32T severityFilter;
char *logFileCurrent;
+ bool files_initiated; /* LLDTEST */
} lgs_ckpt_stream_cfg_t;
typedef struct {
diff --git a/osaf/services/saf/logsv/lgs/lgs_stream.c
b/osaf/services/saf/logsv/lgs/lgs_stream.c
--- a/osaf/services/saf/logsv/lgs/lgs_stream.c
+++ b/osaf/services/saf/logsv/lgs/lgs_stream.c
@@ -72,7 +72,7 @@ static int fileopen_hfop(char *filepath,
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
fd = -1;
} else {
fd = apipar.hdl_ret_code_out;
@@ -105,7 +105,7 @@ static int fileclose_hfop(int fd)
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
rc = -1;
} else {
rc = apipar.hdl_ret_code_out;
@@ -160,12 +160,12 @@ static int file_unlink_hfop(char *filepa
static int delete_config_file_fh(log_stream_t *stream)
{
int rc, n;
- char pathname[PATH_MAX + NAME_MAX];
+ char pathname[LGS_FILEPATH_MAX];
TRACE_ENTER2("LLDTEST");
/* create absolute path for config file */
- n = snprintf(pathname, PATH_MAX, "%s/%s/%s.cfg",
lgs_cb->logsv_root_dir, stream->pathName, stream->fileName);
+ n = snprintf(pathname, LGS_FILEPATH_MAX, "%s/%s/%s.cfg",
lgs_cb->logsv_root_dir, stream->pathName, stream->fileName);
osafassert(n < sizeof(pathname));
@@ -177,7 +177,7 @@ static int delete_config_file_fh(log_str
static int rotate_if_needed_fh(log_stream_t *stream)
{
- char oldest_file[PATH_MAX + NAME_MAX];
+ char oldest_file[LGS_FILEPATH_MAX];
int rc = 0;
int file_cnt;
@@ -253,6 +253,61 @@ static uint32_t log_stream_remove_nof(co
return rc;
}
+/**
+ * Initiate the files belonging to a stream if they are not already initiated.
+ * The stream->files_initiated flag is set when the files are initiated.
+ * If the files could not be initiated e.g. the file system is not working, the
+ * files_initiated flag will not be set.
+ * This function should be used when a stream is opened and every time a log
+ * record is written.
+ *
+ * @param stream
+ */
+static void log_initiate_stream_files(log_stream_t *stream)
+{
+ int errno_save;
+
+ TRACE_ENTER2("LLDTEST");
+ TRACE("LLDTEST %s - stream->files_initiated =
%d",__FUNCTION__,stream->files_initiated);
+
+ if (stream->files_initiated == false) {
+ TRACE("LLDTEST: %s - Creating new files",__FUNCTION__);
+
+ /* Delete to get counting right. It might not exist. */
+ (void)delete_config_file_fh(stream);
+
+ /* Save what filename that shall be the current log file */
+ sprintf(stream->logFileCurrent, "%s_%s", stream->fileName,
lgs_get_time());
+
+ /* Remove files from a previous life if needed */
+ if (rotate_if_needed_fh(stream) == -1) {
+ TRACE("LLDTEST: %s - rotate_if_needed_fh()
FAIL",__FUNCTION__);
+ goto done;
+ }
+
+ if (lgs_make_dir_hfop(stream->pathName) != 0){
+ TRACE("LLDTEST: %s - lgs_make_dir_hfop()
FAIL",__FUNCTION__);
+ goto done;
+ }
+
+ if (lgs_create_config_file_hfop(stream) != 0) {
+ TRACE("LLDTEST: %s - lgs_create_config_file_hfop()
FAIL",__FUNCTION__);
+ goto done;
+ }
+
+ if ((stream->fd = log_file_open_fh(stream, &errno_save)) == -1)
{
+ TRACE("LLDTEST: %s - Could not open '%s' -
%s",__FUNCTION__,
+ stream->logFileCurrent,
strerror(errno_save));
+ goto done;
+ }
+
+ stream->files_initiated = true;
+ }
+
+done:
+ TRACE_LEAVE2("LLDTEST");
+}
+
log_stream_t *log_stream_get_by_name_nof(const char *name)
{
char nname[SA_MAX_NAME_LENGTH + 1];
@@ -633,6 +688,7 @@ int log_file_open_fh(log_stream_t *strea
return fd;
}
+#if 0
SaAisErrorT log_stream_open_fh(log_stream_t *stream)
{
SaAisErrorT rc = SA_AIS_OK;
@@ -700,6 +756,40 @@ SaAisErrorT log_stream_open_fh(log_strea
TRACE_LEAVE2("rc=%u, numOpeners=%u", rc, stream->numOpeners);
return rc;
}
+#endif
+
+SaAisErrorT log_stream_open_fh(log_stream_t *stream)
+{
+ SaAisErrorT rc = SA_AIS_OK;
+
+ osafassert(stream != NULL);
+ TRACE_ENTER2("%s, numOpeners=%u", stream->name, stream->numOpeners);
+
+ /* first time open? */
+ if (stream->numOpeners == 0) {
+ TRACE("LLDTEST3 %s name \"%s\", files_initiated=%d, HA
state=%d",
+ __FUNCTION__,
+ stream->name,stream->files_initiated,
lgs_cb->ha_state);
+ log_initiate_stream_files(stream);
+ } else {
+ /* Second or more open on a stream */
+ if (stream->fd == -1) {
+ TRACE("LLDTEST3 fd = -1");
+ TRACE("LLDTEST3 %s name \"%s\", files_initiated=%d, HA
state=%d",
+ __FUNCTION__,
+ stream->name,stream->files_initiated,
lgs_cb->ha_state);
+ log_initiate_stream_files(stream);
+ }
+ }
+
+ /* Opening a stream will always succeed. If file system problem a new
+ * attempt to open the files is done when trying to write to the stream
+ */
+ stream->numOpeners++;
+
+ TRACE_LEAVE2("rc=%u, numOpeners=%u", rc, stream->numOpeners);
+ return rc;
+}
/**
* if ref. count allows, close the associated file, rename it and delete the
@@ -715,6 +805,9 @@ int log_stream_close_hfop(log_stream_t *
osafassert(stream != NULL);
TRACE_ENTER2("%s, numOpeners=%u", stream->name, stream->numOpeners);
+ if (stream->numOpeners == 0) {
+ TRACE("LLDTEST: %s - numOpeners = 0, streamType =
%u",__FUNCTION__,stream->streamType);
+ }
osafassert(stream->numOpeners > 0);
stream->numOpeners--;
@@ -799,7 +892,7 @@ static int get_number_of_log_files_hfop(
apipar.req_code_in = LGSF_GET_NUM_LOGFILES;
apipar.data_in_size = sizeof(gnolfh_in_t);
apipar.data_in = (void*) ¶meters_in;
- apipar.data_out_size = (PATH_MAX + NAME_MAX);
+ apipar.data_out_size = LGS_FILEPATH_MAX;
apipar.data_out = (void *) oldest_file;
api_rc = log_file_api(&apipar);
@@ -840,7 +933,6 @@ int log_stream_write_hfop(log_stream_t *
/* Open files on demand e.g. on new active after fail/switch-over. This
* enables LOG to cope with temporary file system problems. */
-
if (stream->fd == -1) {
/* Creating directory of given path to store log and cfg files,
* if not using shared file system. */
@@ -863,7 +955,7 @@ int log_stream_write_hfop(log_stream_t *
}
TRACE("stream %s now opened", stream->name);
}
-
+
TRACE("LLDTEST: %s - stream->fd = %d",__FUNCTION__,stream->fd);
/* Write the log record
*/
@@ -888,7 +980,7 @@ int log_stream_write_hfop(log_stream_t *
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
rc = -1;
} else {
rc = apipar.hdl_ret_code_out;
diff --git a/osaf/services/saf/logsv/lgs/lgs_stream.h
b/osaf/services/saf/logsv/lgs/lgs_stream.h
--- a/osaf/services/saf/logsv/lgs/lgs_stream.h
+++ b/osaf/services/saf/logsv/lgs/lgs_stream.h
@@ -47,6 +47,7 @@ typedef struct log_stream {
SaUint64T filtered; /* discarded by server due to filtering */
/* --- end correspond to IMM Class --- */
+ bool files_initiated; /* True when all files belonging to stream are
initiated */
uint32_t streamId; /* The unique stream id for this stream */
int32_t fd; /* The stream file descriptor */
char logFileCurrent[NAME_MAX]; /* Current file name */
diff --git a/osaf/services/saf/logsv/lgs/lgs_util.c
b/osaf/services/saf/logsv/lgs/lgs_util.c
--- a/osaf/services/saf/logsv/lgs/lgs_util.c
+++ b/osaf/services/saf/logsv/lgs/lgs_util.c
@@ -130,7 +130,7 @@ int lgs_create_config_file_hfop(log_stre
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
rc = -1;
} else {
rc = apipar.hdl_ret_code_out;
@@ -209,9 +209,8 @@ int lgs_file_rename_hfop(
const char *suffix)
{
int rc;
- char oldpath[PATH_MAX + NAME_MAX];
- char newpath[PATH_MAX + NAME_MAX];
- const size_t maxsize = PATH_MAX + NAME_MAX;
+ char oldpath[LGS_FILEPATH_MAX];
+ char newpath[LGS_FILEPATH_MAX];
size_t n;
lgsf_apipar_t apipar;
void *params_in_p;
@@ -224,13 +223,13 @@ int lgs_file_rename_hfop(
TRACE_ENTER2("LLDTEST");
LOG_NO("LLDTEST: lgs_file_rename_hfop >>");
- n = snprintf(oldpath, maxsize, "%s/%s/%s%s",
+ n = snprintf(oldpath, LGS_FILEPATH_MAX, "%s/%s/%s%s",
lgs_cb->logsv_root_dir, path, old_name, suffix);
- if (n >= maxsize) osafassert(0);
+ if (n >= LGS_FILEPATH_MAX) osafassert(0);
- n = snprintf(newpath, maxsize, "%s/%s/%s_%s%s",
+ n = snprintf(newpath, LGS_FILEPATH_MAX, "%s/%s/%s_%s%s",
lgs_cb->logsv_root_dir, path, old_name, time_stamp,
suffix);
- if (n >= maxsize) osafassert(0);
+ if (n >= LGS_FILEPATH_MAX) osafassert(0);
TRACE_4("LLDTEST: Rename file from %s", oldpath);
TRACE_4("LLDTEST: to %s", newpath);
@@ -261,7 +260,7 @@ int lgs_file_rename_hfop(
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
rc = -1;
} else {
rc = apipar.hdl_ret_code_out;
@@ -413,7 +412,7 @@ int lgs_make_dir_hfop(const char* path)
lgsf_retcode_t api_rc;
int rc = -1;
mld_in_t params_in;
- char new_rootstr[PATH_MAX + NAME_MAX+2];
+ char new_rootstr[LGS_DIRPATH_MAX+2];
//const int MAX_DEPTH = 10;
//int dir_depth_cnt;
//char *dirdc_p;
@@ -423,19 +422,25 @@ int lgs_make_dir_hfop(const char* path)
/* Check depth of path TBD */
// while (strchr)
+ TRACE("LLDTEST: lgs_cb->logsv_root_dir \"%s\"",lgs_cb->logsv_root_dir);
+ TRACE("LLDTEST: path \"%s\"",path);
+
strncpy(params_in.root_dir, lgs_cb->logsv_root_dir, PATH_MAX+1);
strncpy(params_in.rel_path, path, PATH_MAX+1);
+ TRACE("LLDTEST: root_dir \"%s\"",params_in.root_dir);
+ TRACE("LLDTEST: rel_path \"%s\"",params_in.rel_path);
+
/* Fill in API structure */
apipar.req_code_in = LGSF_MAKELOGDIR;
apipar.data_in_size = sizeof(mld_in_t);
apipar.data_in = (void*) ¶ms_in;
- apipar.data_out_size = PATH_MAX + NAME_MAX;
+ apipar.data_out_size = LGS_DIRPATH_MAX;
apipar.data_out = &new_rootstr;
api_rc = log_file_api(&apipar);
if (api_rc != LGSF_SUCESS) {
- TRACE("%s - API error %d",__FUNCTION__,api_rc);
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
rc = -1;
} else {
rc = apipar.hdl_ret_code_out;
@@ -450,4 +455,43 @@ int lgs_make_dir_hfop(const char* path)
TRACE_LEAVE2("LLDTEST");
return rc;
+}
+
+/**
+ * Check if a path exists. See also stat(..)
+ *
+ * @param path_to_check
+ * @return (-1) if not exists, 0 if exists
+ */
+int lgs_check_path_exists(const char *path_to_check)
+{
+ lgsf_apipar_t apipar;
+ lgsf_retcode_t api_rc;
+ void *params_in_p;
+ int rc = 0;
+
+ /* Allocate memory for parameter */
+ size_t params_in_size = strlen(path_to_check)+1;
+ params_in_p = malloc(params_in_size);
+
+ /* Fill in path */
+ memcpy(params_in_p, path_to_check, params_in_size);
+
+ /* Fill in API structure */
+ apipar.req_code_in = LGSF_CHECKPATH;
+ apipar.data_in_size = params_in_size;
+ apipar.data_in = params_in_p;
+ apipar.data_out_size = 0;
+ apipar.data_out = NULL;
+
+ api_rc = log_file_api(&apipar);
+ if (api_rc != LGSF_SUCESS) {
+ TRACE("%s - API error
%s",__FUNCTION__,lgsf_retcode_str(api_rc));
+ rc = -1;
+ } else {
+ rc = apipar.hdl_ret_code_out;
+ }
+
+ free(params_in_p);
+ return rc;
}
\ No newline at end of file
diff --git a/osaf/services/saf/logsv/lgs/lgs_util.h
b/osaf/services/saf/logsv/lgs/lgs_util.h
--- a/osaf/services/saf/logsv/lgs/lgs_util.h
+++ b/osaf/services/saf/logsv/lgs/lgs_util.h
@@ -58,5 +58,6 @@ extern int lgs_file_rename_hfop(const ch
extern void lgs_exit(const char *msg, SaAmfRecommendedRecoveryT rec_rcvr);
extern bool lgs_relative_path_check_ts(const char* path);
extern int lgs_make_dir_hfop(const char* path);
+extern int lgs_check_path_exists(const char *path_to_check);
#endif /* ifndef __LGS_UTIL_H */
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel