Skip to content

Commit

Permalink
Fix high I/O issue when removing session data
Browse files Browse the repository at this point in the history
  • Loading branch information
SujanSanjula96 committed Jan 7, 2025
1 parent c4f5431 commit 0d89c22
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@ public class SessionDataStore {
"FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND " +
"SESSION_TYPE=? ORDER BY TIME_CREATED DESC) WHERE ROWNUM < 2";

private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_MYSQL =
"SELECT OPERATION FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND" +
" SESSION_TYPE=? ORDER BY TIME_CREATED DESC LIMIT 1";
private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_DB2SQL =
"SELECT OPERATION FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND" +
" SESSION_TYPE=? ORDER BY TIME_CREATED DESC FETCH FIRST 1 ROWS ONLY";
private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_MSSQL =
"SELECT TOP 1 OPERATION FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND" +
" SESSION_TYPE=? ORDER BY TIME_CREATED DESC";
private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_POSTGRESQL =
"SELECT OPERATION FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND" +
" SESSION_TYPE=? ORDER BY TIME_CREATED DESC LIMIT 1";
private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_INFORMIX =
"SELECT FIRST 1 OPERATION FROM IDN_AUTH_SESSION_STORE " +
"WHERE SESSION_ID =? AND " +
"SESSION_TYPE=? ORDER BY TIME_CREATED DESC LIMIT 1";
private static final String SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_ORACLE =
"SELECT * FROM (SELECT OPERATION " +
"FROM IDN_AUTH_SESSION_STORE WHERE SESSION_ID =? AND " +
"SESSION_TYPE=? ORDER BY TIME_CREATED DESC) WHERE ROWNUM < 2";

private static final String SQL_DELETE_EXPIRED_DATA_TASK_MYSQL =
"DELETE FROM IDN_AUTH_SESSION_STORE WHERE EXPIRY_TIME < ? LIMIT %d";
private static final String SQL_DELETE_EXPIRED_DATA_TASK_MSSQL =
Expand Down Expand Up @@ -143,12 +164,14 @@ public class SessionDataStore {
private String sqlDeleteDELETETask;
private String sqlSelect;
private String sqlDeleteExpiredDataTask;
private String sqlGetLastOperation;
private int deleteChunkSize = DEFAULT_DELETE_LIMIT;
private boolean sessionDataCleanupEnabled = true;
private boolean operationDataCleanupEnabled = false;
private static boolean tempDataCleanupEnabled = false;
private static boolean periodicTempDataCleanupEnabled = true;
private static boolean sessionAndTempDataSeparationEnabled = false;
private static boolean checkExistingEntryForDeleteOperationInsert = false;

static {
try {
Expand Down Expand Up @@ -292,6 +315,14 @@ private SessionDataStore() {
sessionCleanupPeriod);
sessionCleanUpService.activateCleanUp();
}


String checkExistingEntryForDeleteOperationInsertProperty = IdentityUtil.getProperty(
"JDBCPersistenceManager.SessionDataPersist.CheckExistingEntryForDeleteOperationInsert");
if (StringUtils.isNotBlank(checkExistingEntryForDeleteOperationInsertProperty)) {
checkExistingEntryForDeleteOperationInsert = Boolean.parseBoolean(
checkExistingEntryForDeleteOperationInsertProperty);
}
}

public static SessionDataStore getInstance() {
Expand All @@ -312,11 +343,6 @@ public Object getSessionData(String key, String type) {

public SessionContextDO getSessionContextData(String key, String type) {

return getSessionContextDataByOperation(key, type, OPERATION_STORE);
}

private SessionContextDO getSessionContextDataByOperation(String key, String type, String requiredOperation) {

if (log.isDebugEnabled()) {
log.debug("Getting SessionContextData from DB. key : " + key + " type : " + type);
}
Expand Down Expand Up @@ -359,7 +385,7 @@ private SessionContextDO getSessionContextDataByOperation(String key, String typ
if (resultSet.next()) {
String operation = resultSet.getString(1);
long nanoTime = resultSet.getLong(3);
if (StringUtils.equalsIgnoreCase(requiredOperation, operation)) {
if (StringUtils.equalsIgnoreCase(OPERATION_STORE, operation)) {
return new SessionContextDO(key, type, getBlobObject(resultSet.getBinaryStream(2)), nanoTime);
}
}
Expand All @@ -374,6 +400,67 @@ private SessionContextDO getSessionContextDataByOperation(String key, String typ
return null;
}

public boolean isSessionDataExist(String key, String type, String requiredOperation) {

if (!enablePersist) {
return false;
}
Connection connection = null;
try {
connection = IdentityDatabaseUtil.getSessionDBConnection(false);
} catch (IdentityRuntimeException e) {
log.error(e.getMessage(), e);
return false;
}
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
if (StringUtils.isBlank(sqlGetLastOperation)) {
sqlGetLastOperation = getSqlGetLastOperation(connection);
}
preparedStatement = connection.prepareStatement(getSessionStoreDBQuery(sqlGetLastOperation, type));
preparedStatement.setString(1, key);
preparedStatement.setString(2, type);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
String operation = resultSet.getString(1);
if (StringUtils.equalsIgnoreCase(requiredOperation, operation)) {
return true;
}
}
} catch (SQLException e) {
if (log.isDebugEnabled()) {
log.debug("Error while checking session data", e);
}
} finally {
IdentityDatabaseUtil.closeAllConnections(connection, resultSet, preparedStatement);
}
return false;
}

private String getSqlGetLastOperation(Connection connection) throws SQLException {

String sqlGetLastOperation;
String driverName = connection.getMetaData().getDriverName();
if (driverName.contains(MYSQL_DATABASE) || driverName.contains(MARIA_DATABASE)
|| driverName.contains(H2_DATABASE)) {
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_MYSQL;
} else if (connection.getMetaData().getDatabaseProductName().contains(DB2_DATABASE)) {
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_DB2SQL;
} else if (driverName.contains(MS_SQL_DATABASE)
|| driverName.contains(MICROSOFT_DATABASE)) {
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_MSSQL;
} else if (driverName.contains(POSTGRESQL_DATABASE)) {
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_POSTGRESQL;
} else if (driverName.contains(INFORMIX_DATABASE)) {
// Driver name = "IBM Informix JDBC Driver for IBM Informix Dynamic Server"
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_INFORMIX;
} else {
sqlGetLastOperation = SQL_RETRIEVE_LAST_SESSION_DATA_OPERATION_ORACLE;
}
return sqlGetLastOperation;
}

public void storeSessionData(String key, String type, Object entry) {

storeSessionData(key, type, entry, MultitenantConstants.INVALID_TENANT_ID);
Expand Down Expand Up @@ -572,7 +659,7 @@ public void removeSessionData(String key, String type, long nanoTime) {
tempAuthnContextDataDeleteQueue.push(new SessionContextDO(key, type, null, nanoTime));
return;
}
if (getSessionContextDataByOperation(key, type, OPERATION_DELETE) != null) {
if (checkExistingEntryForDeleteOperationInsert && isSessionDataExist(key, type, OPERATION_DELETE)) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<UserSessionMapping>
<Enable>{{session_data.persistence.enable_user_session_mapping}}</Enable>
</UserSessionMapping>
<CheckExistingEntryForDeleteOperationInsert>{{session_data.session_data_persist.check_existing_entry_for_delete_operation_insert}}</CheckExistingEntryForDeleteOperationInsert>
</SessionDataPersist>
<PushedAuthReqCleanUp>
<Enable>{{par.cleanup.enable_expired_requests_cleanup}}</Enable>
Expand Down

0 comments on commit 0d89c22

Please sign in to comment.