In some cases the Users want to rotate log file at the time althouth
the file size hasn't been reached MAX FILE SIZE. Log service provides the
new feature that user can rotate log file via admin operation.
---
 src/ais/include/saLog.h        |   3 +-
 src/log/apitest/tet_LogOiOps.c |  76 ++++++++++++
 src/log/logd/lgs_imm.cc        | 258 ++++++++++++++++++++++++-----------------
 src/log/logd/lgs_mbcsv.cc      |  51 ++++++--
 src/log/logd/lgs_stream.cc     | 153 ++++++++++++------------
 src/log/logd/lgs_stream.h      |   3 +
 6 files changed, 342 insertions(+), 202 deletions(-)

diff --git a/src/ais/include/saLog.h b/src/ais/include/saLog.h
index 313c8d287..c28750600 100644
--- a/src/ais/include/saLog.h
+++ b/src/ais/include/saLog.h
@@ -196,7 +196,8 @@ extern "C" {
 
 /* Admin operation IDs */
        typedef enum {
-               SA_LOG_ADMIN_CHANGE_FILTER = 1
+               SA_LOG_ADMIN_CHANGE_FILTER = 1,
+               SA_LOG_ADMIN_ROTATE_FILE = 2
        } saLogAdminOperationIdT;
 
 /* 
diff --git a/src/log/apitest/tet_LogOiOps.c b/src/log/apitest/tet_LogOiOps.c
index e74cd5331..ea96d86ce 100644
--- a/src/log/apitest/tet_LogOiOps.c
+++ b/src/log/apitest/tet_LogOiOps.c
@@ -5479,6 +5479,78 @@ done:
                       &v_saLogStreamFixedLogRecordSize, SA_IMM_ATTR_SAUINT32T);
 }
 
+//
+// Test case for verifying the admin operation rotate log file for
+// configuration application is ok
+// Steps:
+// 1. Create configuration app stream
+// 2. Verify command admin operation rotate log file is ok
+// 3. Delete configuration app stream
+//
+void admin_rotate_log_file(void)
+{
+       int rc = 0;
+       char command[MAX_DATA];
+       const char *object_dn =
+                       "safLgStrCfg=admin_rotate_file,safApp=safLogService";
+
+       // Create configuration application stream
+       sprintf(command, "immcfg -c SaLogStreamConfig %s "
+                       "-a saLogStreamPathName=. "
+                       "-a saLogStreamFileName=admin_rotate_file ", object_dn);
+       rc = systemCall(command);
+       osaf_nanosleep(&kOneSecond);
+       if (rc == 0) {
+               // Admin operation rotate log file
+               sprintf(command, "immadm -o 2 %s", object_dn);
+               rc = systemCall(command);
+               rc_validate(rc, 0);
+
+               // Delete object
+               sprintf(command, "immcfg -d %s", object_dn);
+               systemCall(command);
+       } else {
+               rc_validate(rc, 0);
+       }
+}
+
+//
+// Test case for verifying the admin operation rotate log file for
+// configuration application is ok
+// Steps:
+// 1. Create configuration app stream
+// 2. Verify command admin operation rotate log file with param fails
+// 3. Delete configuration app stream
+//
+void admin_rotate_log_file_with_param(void)
+{
+       int rc = 0;
+       char command[MAX_DATA];
+       const char *object_dn =
+                       "safLgStrCfg=admin_rotate_file1,safApp=safLogService";
+
+       // Create configuration application stream
+       sprintf(command, "immcfg -c SaLogStreamConfig %s"
+                       " -a saLogStreamPathName=. "
+                       "-a saLogStreamFileName=admin_rotate_file1 ",
+                       object_dn);
+       rc = systemCall(command);
+       if (rc == 0) {
+               // Admin operation opId = 2 with parameter
+               sprintf(command, "immadm -o 2 -p "
+                               "saLogStreamSeverityFilter:SA_UINT32_T:7 %s >"
+                               " /dev/null 2>&1 ", object_dn);
+               rc = system(command);
+               rc_validate(WEXITSTATUS(rc), 1);
+
+               // Delete object
+               sprintf(command, "immcfg -d %s", object_dn);
+               systemCall(command);
+       } else {
+               rc_validate(rc, 0);
+       }
+}
+
 __attribute__((constructor)) static void saOiOperations_constructor(void)
 {
        /* Stream objects */
@@ -5835,4 +5907,8 @@ __attribute__((constructor)) static void 
saOiOperations_constructor(void)
        test_case_add(
            6, verLogFileRotate,
            "Verify that log file is not rotated if file size doesn't reach max 
file size (ticket1439)");
+       test_case_add(6, admin_rotate_log_file,
+                     "Verify admin operation rotate log file is ok");
+       test_case_add(6, admin_rotate_log_file_with_param,
+                     "Verify admin operation rotate log file with parameter 
fails");
 }
diff --git a/src/log/logd/lgs_imm.cc b/src/log/logd/lgs_imm.cc
index 45c69f9db..c010142f3 100644
--- a/src/log/logd/lgs_imm.cc
+++ b/src/log/logd/lgs_imm.cc
@@ -81,6 +81,12 @@ static std::vector<std::string> file_path_list;
 /* FUNCTIONS
  * ---------
  */
+static void lgs_admin_change_filter(
+    SaImmOiHandleT immOiHandle, SaInvocationT invocation,
+    SaConstStringT objectName, const SaImmAdminOperationParamsT_2 *parameter);
+static void lgs_admin_rotate_log_file(SaImmOiHandleT immOiHandle,
+                                      SaInvocationT invocation,
+                                      SaConstStringT objectName);
 
 static void report_oi_error(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT ccbId,
                             const char *format, ...)
@@ -127,14 +133,18 @@ static void report_om_error(SaImmOiHandleT immOiHandle,
 
   va_list ap;
   va_start(ap, format);
-  (void)vsnprintf(ao_err_string, 256, format, ap);
+  (void)vsnprintf(ao_err_string, sizeof(ao_err_string), format, ap);
   va_end(ap);
 
   TRACE("%s", ao_err_string);
-  if (saImmOiAdminOperationResult_o2(immOiHandle, invocation,
-                                     SA_AIS_ERR_INVALID_PARAM,
-                                     ao_err_params) == SA_AIS_ERR_BAD_HANDLE) {
+  SaAisErrorT rc = saImmOiAdminOperationResult_o2(immOiHandle, invocation,
+                                                  SA_AIS_ERR_INVALID_PARAM,
+                                                  ao_err_params);
+  if (rc == SA_AIS_ERR_BAD_HANDLE) {
     lgsOiCreateBackground();
+  } else if (rc != SA_AIS_OK) {
+    LOG_ER("immutil_saImmOiAdminOperationResult failed %s", saf_error(rc));
+    osaf_abort(0);
   }
 }
 
@@ -376,122 +386,26 @@ static void adminOperationCallback(
     SaImmOiHandleT immOiHandle, SaInvocationT invocation,
     const SaNameT *objectName, SaImmAdminOperationIdT opId,
     const SaImmAdminOperationParamsT_2 **params) {
-  SaUint32T severityFilter;
   const SaImmAdminOperationParamsT_2 *param = params[0];
-  log_stream_t *stream;
-  SaAisErrorT ais_rc = SA_AIS_OK;
   SaConstStringT objName = osaf_extended_name_borrow(objectName);
 
   TRACE_ENTER2("%s", objName);
 
   if (lgs_cb->ha_state != SA_AMF_HA_ACTIVE) {
     LOG_ER("admin op callback in applier");
-    goto done;
-  }
-
-  if ((stream = log_stream_get_by_name(objName)) == NULL) {
-    report_om_error(immOiHandle, invocation, "Stream %s not found", objName);
-    goto done;
-  }
-
-  if (opId == SA_LOG_ADMIN_CHANGE_FILTER) {
-    /* Only allowed to update runtime objects (application streams) */
-    if (stream->streamType != STREAM_TYPE_APPLICATION_RT) {
-      report_om_error(immOiHandle, invocation,
-                      "Admin op change filter for non app stream");
-      goto done;
-    }
-
-    /* Not allow perform adm op on configurable app streams */
-    if (stream->isRtStream != SA_TRUE) {
-      ais_rc = immutil_saImmOiAdminOperationResult(immOiHandle, invocation,
-                                                   SA_AIS_ERR_NOT_SUPPORTED);
-      // TODO(Lennart) May be relevant to recover OI if BAD HANDLE
-      if (ais_rc != SA_AIS_OK) {
-        LOG_ER("immutil_saImmOiAdminOperationResult failed %s",
-               saf_error(ais_rc));
-        osaf_abort(0);
-      }
-
-      goto done;
-    }
-
-    if (param == NULL) {
-      /* No parameters given in admin op */
-      report_om_error(immOiHandle, invocation,
-                      "Admin op change filter: parameters are missing");
-      goto done;
-    }
-
-    if (strcmp(param->paramName, "saLogStreamSeverityFilter") != 0) {
-      report_om_error(immOiHandle, invocation,
-                      "Admin op change filter, invalid param name");
-      goto done;
-    }
-
-    if (param->paramType != SA_IMM_ATTR_SAUINT32T) {
-      report_om_error(immOiHandle, invocation,
-                      "Admin op change filter: invalid parameter type");
-      goto done;
-    }
-
-    severityFilter = *((SaUint32T *)param->paramBuffer);
-
-    if (severityFilter > 0x7f) { /* not a level, a bitmap */
-      report_om_error(immOiHandle, invocation,
-                      "Admin op change filter: invalid severity");
-      goto done;
-    }
-
-    if (severityFilter == stream->severityFilter) {
-      ais_rc = immutil_saImmOiAdminOperationResult(immOiHandle, invocation,
-                                                   SA_AIS_ERR_NO_OP);
-      // TODO(Lennart) May be relevant to recover OI if BAD HANDLE
-      if (ais_rc != SA_AIS_OK) {
-        LOG_ER("immutil_saImmOiAdminOperationResult failed %s",
-               saf_error(ais_rc));
-        osaf_abort(0);
-      }
-
-      goto done;
-    }
-
-    TRACE("Changing severity for stream %s to %u", stream->name.c_str(),
-          severityFilter);
-    stream->severityFilter = severityFilter;
-
-    ais_rc = immutil_update_one_rattr(
-        immOiHandle, objName,
-        const_cast<SaImmAttrNameT>("saLogStreamSeverityFilter"),
-        SA_IMM_ATTR_SAUINT32T, &stream->severityFilter);
-    if (ais_rc != SA_AIS_OK) {
-      LOG_ER("%s: immutil_update_one_rattr failed %s", __FUNCTION__,
-             saf_error(ais_rc));
-      osaf_abort(0);
-    }
-
-    ais_rc =
-        immutil_saImmOiAdminOperationResult(immOiHandle, invocation, 
SA_AIS_OK);
-    // TODO(Lennart) May be relevant to recover OI if BAD HANDLE
-    if (ais_rc != SA_AIS_OK) {
-      LOG_ER("immutil_saImmOiAdminOperationResult failed %s",
-             saf_error(ais_rc));
-      osaf_abort(0);
+  } else if (opId == SA_LOG_ADMIN_CHANGE_FILTER) {
+    lgs_admin_change_filter(immOiHandle, invocation, objName, param);
+  } else if (opId == SA_LOG_ADMIN_ROTATE_FILE) {
+    if (param != nullptr) {
+        report_om_error(immOiHandle, invocation,
+                        "Admin op rotate log file: parameters is not empty");
+    } else {
+      lgs_admin_rotate_log_file(immOiHandle, invocation, objName);
     }
-
-    /* Send changed severity filter to clients */
-    lgs_send_severity_filter_to_clients(stream->streamId, severityFilter);
-
-    /* Checkpoint to standby LOG server */
-    ckpt_stream_config(stream);
   } else {
-    report_om_error(
-        immOiHandle, invocation,
-        "Invalid operation ID, should be %d (one) for change filter",
-        SA_LOG_ADMIN_CHANGE_FILTER);
+    report_om_error( immOiHandle, invocation, "Invalid operation ID");
   }
 
-done:
   TRACE_LEAVE();
 }
 
@@ -3401,3 +3315,129 @@ done:
   TRACE_LEAVE();
   return rc_attr_val;
 }
+
+/**
+ * Handle admin operation that changes the severity filter
+ *
+ * @param immOiHandle
+ * @param invocation
+ * @param objectName
+ * @param stream
+ * @param parameter
+ */
+static void lgs_admin_change_filter(
+    SaImmOiHandleT immOiHandle, SaInvocationT invocation,
+    SaConstStringT objectName, const SaImmAdminOperationParamsT_2 *parameter) {
+  SaAisErrorT rc = SA_AIS_OK;
+  TRACE_ENTER();
+
+  osafassert(objectName != nullptr);
+  log_stream_t *stream = log_stream_get_by_name(objectName);
+
+  if (parameter == nullptr) {
+      // No parameters given in admin op
+      report_om_error(immOiHandle, invocation,
+                      "Admin op change filter: parameters are missing");
+      return;
+  }
+
+  SaUint32T severityFilter =
+        *(reinterpret_cast<SaUint32T *>(parameter->paramBuffer));
+
+  if (stream == nullptr) {
+    report_om_error(immOiHandle, invocation, "Stream %s not found", 
objectName);
+  } else if (stream->streamType != STREAM_TYPE_APPLICATION_RT) {
+    // Only allowed to update runtime objects (application streams)
+    report_om_error(immOiHandle, invocation,
+                    "Admin op change filter for non runtime app stream");
+  } else if (strcmp(parameter->paramName, "saLogStreamSeverityFilter") != 0) {
+    report_om_error(immOiHandle, invocation,
+                    "Admin op change filter, invalid param name");
+  } else if (parameter->paramType != SA_IMM_ATTR_SAUINT32T) {
+    report_om_error(immOiHandle, invocation,
+                    "Admin op change filter: invalid parameter type");
+  } else if (severityFilter > 0x7f) {
+    report_om_error(immOiHandle, invocation,
+                    "Admin op change filter: invalid severity");
+  } else if (severityFilter == stream->severityFilter) {
+    rc = immutil_saImmOiAdminOperationResult(immOiHandle, invocation,
+                                             SA_AIS_ERR_NO_OP);
+    if (rc == SA_AIS_ERR_BAD_HANDLE) {
+      lgsOiCreateBackground();
+    } else if (rc != SA_AIS_OK) {
+      LOG_ER("immutil_saImmOiAdminOperationResult failed %s", saf_error(rc));
+      osaf_abort(0);
+    }
+  } else {
+    TRACE("Changing severity for stream %s to %u",
+          stream->name.c_str(), severityFilter);
+    stream->severityFilter = severityFilter;
+
+    rc = immutil_update_one_rattr(immOiHandle, objectName,
+                       const_cast<SaImmAttrNameT>("saLogStreamSeverityFilter"),
+                       SA_IMM_ATTR_SAUINT32T, &stream->severityFilter);
+    if (rc == SA_AIS_ERR_BAD_HANDLE) {
+      lgsOiCreateBackground();
+    } else if (rc != SA_AIS_OK) {
+      LOG_ER("%s: update_one_rattr failed %s", __FUNCTION__, saf_error(rc));
+      osaf_abort(0);
+    }
+
+    rc = immutil_saImmOiAdminOperationResult(immOiHandle, invocation,
+                                             SA_AIS_OK);
+    if (rc == SA_AIS_ERR_BAD_HANDLE) {
+      lgsOiCreateBackground();
+    } else if (rc != SA_AIS_OK) {
+      LOG_ER("immutil_saImmOiAdminOperationResult failed %s", saf_error(rc));
+      osaf_abort(0);
+    }
+
+    // Send changed severity filter to all clients that subscribed the callback
+    lgs_send_severity_filter_to_clients(stream->streamId, severityFilter);
+
+    // Checkpoint to standby LOG server
+    ckpt_stream_config(stream);
+  }
+  TRACE_LEAVE();
+}
+
+/**
+ * Handle admin operation that rotates the log file
+ *
+ * @param immOiHandle
+ * @param invocation
+ * @param objectName
+ */
+static void lgs_admin_rotate_log_file(SaImmOiHandleT immOiHandle,
+                                      SaInvocationT invocation,
+                                      SaConstStringT objectName) {
+  SaAisErrorT rc = SA_AIS_OK;
+  TRACE_ENTER();
+
+  osafassert(objectName != nullptr);
+  log_stream_t *stream = log_stream_get_by_name(objectName);
+
+  if (stream == nullptr) {
+    report_om_error(immOiHandle, invocation, "Stream %s not found", 
objectName);
+  } else {
+    // Rotate log file.
+    // Send the result "FAILED_OPERATION" to admin if the rotation fails
+    SaAisErrorT result = SA_AIS_OK;
+    int ret = log_rotation_act(stream);
+    if (ret == 0)
+      // Checkpoint the stream to standby to rotate the log file
+      // in case the split file system
+      ckpt_stream_config(stream);
+    else
+      result = SA_AIS_ERR_FAILED_OPERATION;
+
+    rc = immutil_saImmOiAdminOperationResult(immOiHandle, invocation, result);
+    if (rc == SA_AIS_ERR_BAD_HANDLE) {
+      lgsOiCreateBackground();
+    } else if (rc != SA_AIS_OK) {
+      LOG_ER("immutil_saImmOiAdminOperationResult failed %s", saf_error(rc));
+      osaf_abort(0);
+    }
+  }
+  TRACE_LEAVE();
+}
diff --git a/src/log/logd/lgs_mbcsv.cc b/src/log/logd/lgs_mbcsv.cc
index 8f66fb926..cd3d70009 100644
--- a/src/log/logd/lgs_mbcsv.cc
+++ b/src/log/logd/lgs_mbcsv.cc
@@ -2316,6 +2316,7 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
   char *dest_names = nullptr;
   SaUint32T severityFilter;
   char *logFileCurrent;
+  bool new_cfg_file_needed = false;
 
   TRACE_ENTER();
 
@@ -2370,9 +2371,16 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
     goto done;
   }
 
+  if ((stream->maxLogFileSize != maxLogFileSize) ||
+      (stream->fixedLogRecordSize != fixedLogRecordSize) ||
+      (stream->logFullAction != logFullAction) ||
+      (stream->maxFilesRotated != maxFilesRotated) ||
+      (strcmp(stream->logFileFormat, logFileFormat) != 0) ||
+      (stream->fileName != fileName))
+    new_cfg_file_needed = true;
+
   TRACE("config stream %s, id: %u", stream->name.c_str(), stream->streamId);
   stream->act_last_close_timestamp = closetime; /* Not used if ver 1 */
-  stream->fileName = fileName;
   stream->maxLogFileSize = maxLogFileSize;
   stream->fixedLogRecordSize = fixedLogRecordSize;
   stream->logFullAction = logFullAction;
@@ -2408,22 +2416,43 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
     }
   }
 
-  /* If split file mode, update standby files */
+  // If split file system mode, update standby files
   if (lgs_is_split_file_system()) {
-    int rc = 0;
     std::string root_path =
         static_cast<const char *>(lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
-    if ((rc = log_stream_config_change(LGS_STREAM_CREATE_FILES, root_path,
-                                       stream, stream->stb_logFileCurrent,
-                                       &closetime)) != 0) {
-      LOG_WA("log_stream_config_change failed: %d", rc);
+    if (new_cfg_file_needed) {
+      int rc = 0;
+      // Change config file if need
+      if ((rc = log_stream_config_change(!LGS_STREAM_CREATE_FILES, root_path,
+                                         stream, stream->stb_logFileCurrent,
+                                         &closetime)) != 0)
+        LOG_WA("log_stream_config_change failed: %d", rc);
+
+      stream->fileName = fileName;
+
+      if ((rc = lgs_create_config_file_h(root_path, stream)) != 0)
+        LOG_WA("lgs_create_config_file_h failed: %d", rc);
+
+      stream->stb_logFileCurrent = stream->logFileCurrent;
+
+      // Create the new log file based on updated configuration
+      *stream->p_fd = log_file_open(root_path, stream,
+                                    stream->stb_logFileCurrent, NULL);
+      if (*stream->p_fd == -1)
+        LOG_WA("New log file could not be created for stream: %s",
+               stream->name.c_str());
+    } else if (stream->stb_prev_actlogFileCurrent != logFileCurrent) {
+      // If there is no changed attributes that needs to change cfg file
+      // but the current log file has already changed in ACTIVE, the log file
+      // has already rotated in ACTIVE. Should also rotate in STANDBY
+      if (log_rotation_stb(stream) != 0)
+        LOG_WA("Rotate log file fails");
     }
 
-    /* When modifying old files are closed and new are opened meaning that
-     * we have a new  standby current log-file
-     */
     stream->stb_prev_actlogFileCurrent = stream->logFileCurrent;
-    stream->stb_logFileCurrent = stream->logFileCurrent;
+  } else {
+    stream->fileName = fileName;
+    stream->logFileCurrent = logFileCurrent;
   }
 
 done:
diff --git a/src/log/logd/lgs_stream.cc b/src/log/logd/lgs_stream.cc
index 28344c8cd..d31ae170b 100644
--- a/src/log/logd/lgs_stream.cc
+++ b/src/log/logd/lgs_stream.cc
@@ -1043,10 +1043,9 @@ done:
  * This handler shall be used on standby only
  *
  * @param stream
- * @param count
- * @return
+ * @return -1 on error
  */
-static int log_rotation_stb(log_stream_t *stream, size_t count) {
+int log_rotation_stb(log_stream_t *stream) {
   int rc = 0;
   int errno_save;
   int errno_ret;
@@ -1058,8 +1057,6 @@ static int log_rotation_stb(log_stream_t *stream, size_t 
count) {
 
   TRACE_ENTER();
 
-  stream->stb_curFileSize += count;
-
   /* If active node has rotated files there is a new "logFileCurrent"
    * (check pointed). Standby always follows active rotation.
    *
@@ -1068,85 +1065,83 @@ static int log_rotation_stb(log_stream_t *stream, 
size_t count) {
    * as described above.
    */
 
-  /* XXX Should be handled...??
-   * If local rotate has been done within one second before active is rotating
+  /* If local rotate has been done within one second before active is rotating
    * the file name in stb_logFileCurrent and logFileCurrent may be the same!
    * This means that a rotation on active when standby is running is not
    * guaranteed. This situation though is very unlikely.
    */
   if (stream->logFileCurrent != stream->stb_prev_actlogFileCurrent) {
     TRACE("Active has rotated (follow active)");
-    /* Active has rotated */
+    // Active has rotated
     stream->stb_prev_actlogFileCurrent = stream->logFileCurrent;
-    /* Use close time from active for renaming of closed file
-     */
-
+    // Use close time from active for renaming of closed file
     current_time_str = lgs_get_time(&stream->act_last_close_timestamp);
     do_rotate = true;
-    /* Use same name as active for new current log file */
+    // Use same name as active for new current log file
     new_current_log_filename = stream->logFileCurrent;
   } else if (stream->stb_curFileSize > stream->maxLogFileSize) {
     TRACE("Standby has rotated (filesize)");
-    /* Standby current log file has reached max limit */
-    /* Use internal time since active has not yet rotated */
+    // Standby current log file has reached max limit */
+    // Use internal time since active has not yet rotated
     current_time_str = lgs_get_time(NULL);
     do_rotate = true;
-    /* Create new name for current log file based on local time */
+    // Create new name for current log file based on local time
     new_current_log_filename = stream->fileName + "_" + current_time_str;
   }
 
   if (do_rotate) {
-    /* Time to use as "close time stamp" and "open time stamp" for new
-     * log file as created by active.
-     */
-
-    /* Close current log file */
-    rc = fileclose_h(*stream->p_fd, &errno_ret);
-    *stream->p_fd = -1;
-    if (rc == -1) {
-      LOG_NO("close FAILED: %s", strerror(errno_ret));
-      goto done;
+    // Close current log file
+    if (*stream->p_fd != -1) {
+      rc = fileclose_h(*stream->p_fd, &errno_ret);
+      *stream->p_fd = -1;
+      if (rc == -1) {
+        LOG_NO("Close log file failed: %s", strerror(errno_ret));
+        return rc;
+      }
     }
 
     std::string emptyStr = "";
-    /* Rename file to give it the "close timestamp" */
+    // Rename file to give it the "close timestamp"
     rc = lgs_file_rename_h(root_path, stream->pathName,
                            stream->stb_logFileCurrent, current_time_str,
                            LGS_LOG_FILE_EXT, &emptyStr);
-    if (rc == -1) goto done;
+    if (rc == -1) {
+      LOG_NO("Rename log file failed");
+      return rc;
+    }
 
-    /* Remove oldest file if needed */
+    // Remove oldest file if needed
     if (rotate_if_needed(stream) == -1) {
       TRACE("Old file removal failed");
     }
-
-    /* Save new name for current log file and open it */
+    // Save new name for current log file and open it
     stream->stb_logFileCurrent = new_current_log_filename;
+    // Reset file size
+    stream->stb_curFileSize = 0;
+
     if ((*stream->p_fd = log_file_open(
              root_path, stream, stream->stb_logFileCurrent, &errno_save)) ==
         -1) {
       LOG_IN("Could not open '%s' - %s", stream->stb_logFileCurrent.c_str(),
              strerror(errno_save));
       rc = -1;
-      goto done;
     }
-
-    stream->stb_curFileSize = 0;
   }
 
-done:
   TRACE_LEAVE();
   return rc;
 }
 
 /**
- * Handle log file rotation. Do rotation if needed
+ * Handle log file rotation in ACTIVE node
+ *
+ * Step1: Close the log file and create a new one.
+ * Step2: If number of files > max number of files, deleting the oldest
  *
  * @param stream
- * @param count
  * @return -1 on error
  */
-static int log_rotation_act(log_stream_t *stream, size_t count) {
+int log_rotation_act(log_stream_t *stream) {
   int rc;
   int errno_save;
   int errno_ret;
@@ -1155,58 +1150,49 @@ static int log_rotation_act(log_stream_t *stream, 
size_t count) {
       static_cast<const char *>(lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
   std::string emptyStr = "";
 
-  /* If file size > max file size:
-   *  - Close the log file and create a new.
-   *  - If number of files > max number of files delete the oldest
-   */
-  rc = 0;
-  stream->curFileSize += count;
-
-  if ((stream->curFileSize) > stream->maxLogFileSize) {
-    osaf_clock_gettime(CLOCK_REALTIME, &closetime_tspec);
-    time_t closetime = closetime_tspec.tv_sec;
-    char *current_time = lgs_get_time(&closetime);
+  TRACE_ENTER();
+  osaf_clock_gettime(CLOCK_REALTIME, &closetime_tspec);
+  time_t closetime = closetime_tspec.tv_sec;
+  char *current_time = lgs_get_time(&closetime);
 
-    /* Close current log file */
+  // Close current log file
+  if (*stream->p_fd != -1) {
     rc = fileclose_h(*stream->p_fd, &errno_ret);
     *stream->p_fd = -1;
     if (rc == -1) {
-      LOG_NO("close FAILED: %s", strerror(errno_ret));
-      goto done;
+      LOG_NO("Close log file failed: %s", strerror(errno_ret));
+      return rc;
     }
+  }
 
-    /* Rename file to give it the "close timestamp" */
-    rc = lgs_file_rename_h(root_path, stream->pathName, stream->logFileCurrent,
-                           current_time, LGS_LOG_FILE_EXT, &emptyStr);
-    if (rc == -1) goto done;
-
-    /* Save time when logFileCurrent was closed */
-    stream->act_last_close_timestamp = closetime;
-
-    /* Invalidate logFileCurrent for this stream */
-    stream->logFileCurrent[0] = 0;
-
-    /* Reset file size for current log file */
-    stream->curFileSize = 0;
+  // Rename file to give it the "close timestamp"
+  rc = lgs_file_rename_h(root_path, stream->pathName, stream->logFileCurrent,
+                         current_time, LGS_LOG_FILE_EXT, &emptyStr);
+  if (rc == -1) {
+    LOG_NO("Rename log file failed");
+    return rc;
+  }
 
-    /* Remove oldest file if needed */
-    if (rotate_if_needed(stream) == -1) {
-      TRACE("Old file removal failed");
-    }
+  // Save time when logFileCurrent was closed
+  stream->act_last_close_timestamp = closetime;
+  // Invalidate logFileCurrent for this stream
+  stream->logFileCurrent[0] = 0;
+  // Reset file size for current log file
+  stream->curFileSize = 0;
+  // Remove oldest file if needed
+  if (rotate_if_needed(stream) == -1)
+    TRACE("Old file removal failed");
 
-    /* Create a new file name that includes "open time stamp" and open the file
-     */
-    stream->logFileCurrent = stream->fileName + "_" + current_time;
-    if ((*stream->p_fd = log_file_open(
-             root_path, stream, stream->logFileCurrent, &errno_save)) == -1) {
-      LOG_IN("Could not open '%s' - %s", stream->logFileCurrent.c_str(),
-             strerror(errno_save));
-      rc = -1;
-      goto done;
-    }
+  // Create a new file name that includes "open time stamp" and open the file
+  stream->logFileCurrent = stream->fileName + "_" + current_time;
+  if ((*stream->p_fd = log_file_open(
+      root_path, stream, stream->logFileCurrent, &errno_save)) == -1) {
+    LOG_IN("Could not open '%s' - %s", stream->logFileCurrent.c_str(),
+           strerror(errno_save));
+    rc = -1;
   }
 
-done:
+  TRACE_LEAVE();
   return rc;
 }
 
@@ -1328,9 +1314,12 @@ int log_stream_write_h(log_stream_t *stream, const char 
*buf, size_t count) {
    *       for split file system.
    */
   if (lgs_cb->ha_state == SA_AMF_HA_ACTIVE) {
-    rc = log_rotation_act(stream, count);
+    stream->curFileSize += count;
+    if (stream->curFileSize > stream->maxLogFileSize)
+      rc = log_rotation_act(stream);
   } else {
-    rc = log_rotation_stb(stream, count);
+    stream->stb_curFileSize += count;
+    rc = log_rotation_stb(stream);
   }
 
 done:
@@ -1545,6 +1534,8 @@ int log_stream_config_change(bool create_files_f, const 
std::string &root_path,
     }
   }
 
+  rotate_if_needed(stream);
+
   /* Reset file size for new log file */
   stream->curFileSize = 0;
 
diff --git a/src/log/logd/lgs_stream.h b/src/log/logd/lgs_stream.h
index ad8c7412f..2aa6922f4 100644
--- a/src/log/logd/lgs_stream.h
+++ b/src/log/logd/lgs_stream.h
@@ -147,4 +147,7 @@ void log_stream_form_dest_names(log_stream_t *stream);
 
 void lgs_ckpt_stream_open(log_stream_t *stream, uint32_t client_id);
 
+int log_rotation_act(log_stream_t *stream);
+int log_rotation_stb(log_stream_t *stream);
+
 #endif  // LOG_LOGD_LGS_STREAM_H_
-- 
2.15.1



_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to