From c59e20fbcba0697e45ca24f4be7e076316212160 Mon Sep 17 00:00:00 2001 From: Dinitha Wijewardhana Date: Tue, 17 Mar 2026 13:51:02 +0530 Subject: [PATCH 1/2] Refactor cache operations to use read-safe methods for concurrent environments --- .../registry/core/jdbc/dao/JDBCPathCache.java | 164 ++++++++++++++++++ .../core/jdbc/dao/JDBCResourceDAO.java | 29 +++- .../authorization/AuthorizationCache.java | 33 ++++ .../JDBCAuthorizationManager.java | 4 +- .../core/common/AbstractUserStoreManager.java | 105 ++++++++--- .../user/core/common/DefaultRealmService.java | 4 +- .../core/common/GroupIdResolverCache.java | 20 +++ .../carbon/user/core/common/RealmCache.java | 40 +++++ .../user/core/common/UserIdResolverCache.java | 30 ++++ .../user/core/common/UserRolesCache.java | 33 ++++ .../common/UserUniqueIDDomainResolver.java | 71 ++++++++ .../user/core/common/UserUniqueIDManger.java | 91 ++++++++++ .../jdbc/UniqueIDJDBCUserStoreManager.java | 8 +- .../ldap/ReadOnlyLDAPUserStoreManager.java | 33 +++- .../UniqueIDReadOnlyLDAPUserStoreManager.java | 4 +- .../core/tenant/FileSystemTenantManager.java | 2 +- .../user/core/tenant/JDBCTenantManager.java | 19 +- .../carbon/user/core/tenant/TenantCache.java | 40 +++++ .../user/core/tenant/TenantDomainCache.java | 31 ++++ .../user/core/tenant/TenantIdCache.java | 32 ++++ .../user/core/tenant/TenantUniqueIdCache.java | 37 ++++ 21 files changed, 779 insertions(+), 51 deletions(-) diff --git a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCPathCache.java b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCPathCache.java index b8a5024689d..2933874c2fa 100644 --- a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCPathCache.java +++ b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCPathCache.java @@ -449,6 +449,74 @@ public String getPath(AbstractConnection conn, int id) throws SQLException { } } + /** + * Method to get the path of a given path id. + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param conn the database connection to use. + * @param id the path. + * + * @return the path corresponding to the given path id. + * @throws SQLException if an error occurs while obtaining the path id. + */ + public String getPathOnRead(AbstractConnection conn, int id) throws SQLException { + + String connectionId; + if (conn != null && conn.getConnectionId() != null) { + connectionId = conn.getConnectionId(); + } else { + throw new SQLException("Connection is null"); + } + RegistryCacheKey key = + RegistryUtils.buildRegistryCacheKey(connectionId, + CurrentSession.getTenantId(), Integer.toString(id)); + Cache cache = getCache(); + RegistryCacheEntry result = cache.get(key); + if (result != null) { + return result.getPath(); + } else { + PreparedStatement ps = null; + ResultSet results = null; + try { + String sql = + "SELECT REG_PATH_VALUE FROM REG_PATH WHERE REG_PATH_ID=? AND REG_TENANT_ID=?"; + + ps = conn.prepareStatement(sql); + ps.setInt(1, id); + ps.setInt(2, CurrentSession.getTenantId()); + + results = ps.executeQuery(); + if (results.next()) { + result = new RegistryCacheEntry(results.getString(DatabaseConstants.PATH_VALUE_FIELD)); + cache.putOnRead(key, result); + return result.getPath(); + } + + } finally { + try { + try { + if (results != null) { + results.close(); + } + } finally { + if (ps != null) { + ps.close(); + } + } + } catch (SQLException ex) { + String msg = RegistryConstants.RESULT_SET_PREPARED_STATEMENT_CLOSE_ERROR; + log.error(msg, ex); + } + } + return null; + } + } + /** * Method to get the path id of a given path. * @@ -539,6 +607,102 @@ public int getPathID(AbstractConnection conn, String path) throws SQLException { return -1; } + /** + * Method to get the path id of a given path. + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param conn the database connection to use. + * @param path the path. + * + * @return the path id corresponding to the given path. + * @throws SQLException if an error occurs while obtaining the path id. + */ + public int getPathIDOnRead(AbstractConnection conn, String path) throws SQLException { + String connectionId = null; + if (conn != null && conn.getConnectionId() != null) { + connectionId = conn.getConnectionId(); + } else { + throw new SQLException("Connection is null"); + } + RegistryCacheKey key = + RegistryUtils.buildRegistryCacheKey(connectionId, + CurrentSession.getTenantId(), path); + Cache cache = getCache(); + RegistryCacheEntry result = (RegistryCacheEntry) cache.get(key); + + // TODO: FIX: Path Cache should only be updated if the key yields a valid registry path. + // Recently, this has lead to: + // org.wso2.carbon.registry.core.exceptions.RegistryException: Failed to add resource to + // path /_system. Cannot add or update a child row: a foreign key constraint fails + // (`stratos_db`.`REG_RESOURCE`, CONSTRAINT `REG_RESOURCE_FK_BY_PATH_ID` FOREIGN KEY + // (`REG_PATH_ID`, `REG_TENANT_ID`) REFERENCES `REG_PATH` (`REG_PATH_ID`, `REG_TENANT_ID`)) + // + // when registry separation is enabled. Thus, we need a better solution to address this, and + // a better key which also contains the name of the DB in use. Un-comment the below once + // this has been done. + // + // IMPORTANT: Never remove this comment until we are certain that the current fix is + // actually working - Senaka. + + if (result != null) { + return result.getPathId(); + } else { + ResultSet results = null; + PreparedStatement ps = null; + try { + String sql = + "SELECT REG_PATH_ID FROM REG_PATH WHERE REG_PATH_VALUE=? " + + "AND REG_TENANT_ID=?"; + ps = conn.prepareStatement(sql); + ps.setString(1, path); + ps.setInt(2, CurrentSession.getTenantId()); + results = ps.executeQuery(); + + int pathId; + if (results.next()) { + pathId = results.getInt(DatabaseConstants.PATH_ID_FIELD); + + if (pathId > 0) { + RegistryCacheEntry e = new RegistryCacheEntry(pathId); + cache.putOnRead(key, e); + return pathId; + } + } else { + //not found . set -1 in the cache as well for the path + RegistryCacheEntry e = new RegistryCacheEntry(-1); + cache.putOnRead(key, e); + } + + } catch (SQLException e) { + String msg = "Failed to retrieving resource from " + path + ". " + e.getMessage(); + log.error(msg, e); + throw e; + } finally { + try { + try { + if (results != null) { + results.close(); + } + } finally { + if (ps != null) { + ps.close(); + } + } + } catch (SQLException e) { + String msg = RegistryConstants.RESULT_SET_PREPARED_STATEMENT_CLOSE_ERROR + + e.getMessage(); + log.error(msg, e); + } + } + } + return -1; + } + /** * Retrieves the existing path ID after rolling back an aborted transaction * caused by a constraint violation during concurrent path creation. diff --git a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java index cbd7ce6e60a..3bc5b473c95 100644 --- a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java +++ b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java @@ -72,7 +72,7 @@ public ResourceIDImpl getResourceID(String path) throws RegistryException { try { // step1: need to check whether it is a resource or collection while retrieving path id JDBCPathCache pathCache = JDBCPathCache.getPathCache(); - int pathID = pathCache.getPathID(conn, path); + int pathID = pathCache.getPathIDOnRead(conn, path); boolean isCollection = true; if (pathID == -1) { isCollection = false; @@ -86,7 +86,7 @@ public ResourceIDImpl getResourceID(String path) throws RegistryException { String parentPath = RegistryUtils.getParentPath(path); resourceName = RegistryUtils.getResourceName(path); - pathID = pathCache.getPathID(conn, parentPath); + pathID = pathCache.getPathIDOnRead(conn, parentPath); } if (pathID != -1) { @@ -118,7 +118,7 @@ public ResourceIDImpl getResourceID(String path, boolean isCollection) int pathID; String resourceName = null; if (isCollection) { - pathID = JDBCPathCache.getPathCache().getPathID(conn, path); + pathID = JDBCPathCache.getPathCache().getPathIDOnRead(conn, path); } else { // we have to re-get the path id for the parent path.. String parentPath; @@ -129,7 +129,7 @@ public ResourceIDImpl getResourceID(String path, boolean isCollection) } resourceName = RegistryUtils.getResourceName(path); - pathID = JDBCPathCache.getPathCache().getPathID(conn, parentPath); + pathID = JDBCPathCache.getPathCache().getPathIDOnRead(conn, parentPath); } if (pathID != -1) { @@ -2202,6 +2202,25 @@ public String getPathFromId(int pathId) throws RegistryException { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + */ + public String getPathFromIdOnRead(int pathId) throws RegistryException { + try { + return JDBCPathCache.getPathCache() + .getPathOnRead(JDBCDatabaseTransaction.getConnection(), pathId); + } catch (SQLException e) { + String msg = "Failed to get the path for the path id " + pathId + ". " + e.getMessage(); + log.error(msg, e); + throw new RegistryException(msg, e); + } + } + public String getPath(long version) throws RegistryException { ResourceDO resourceDO = getResourceDO(version); if (resourceDO == null) { @@ -2212,7 +2231,7 @@ public String getPath(long version) throws RegistryException { public String getPath(int pathId, String resourceName, boolean checkExistence) throws RegistryException { - String pathCollection = getPathFromId(pathId); + String pathCollection = getPathFromIdOnRead(pathId); if (pathCollection == null) { return null; } diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/AuthorizationCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/AuthorizationCache.java index 3861a6710e9..acb8f44e631 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/AuthorizationCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/AuthorizationCache.java @@ -123,6 +123,39 @@ public void addToCache(String serverId, int tenantId, String userName, cache.put(key, cacheEntry); } + /** + * Add a cache entry during a READ operation. + * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Adds an entry to the cache. Says whether given user or role is authorized + * or not. + * + * @param serverId unique identifier for carbon server instance + * @param userName Name of the user which was authorized. If this is null + * roleName must not be null. + * @param resourceId The resource on which user/role was authorized. + * @param action The action which user/role authorized for. + * @param isAuthorized Whether role/user was authorized or not. true for + * authorized else false. + */ + public void addToCacheOnRead(String serverId, int tenantId, String userName, + String resourceId, String action, boolean isAuthorized) { + + if (!isCaseSensitiveUsername(userName, tenantId)) { + userName = userName.toLowerCase(); + } + + Cache cache = this.getAuthorizationCache(); + if (isCacheNull(cache)) { + return; + } + AuthorizationKey key = new AuthorizationKey(serverId, tenantId, userName, resourceId, action); + AuthorizeCacheEntry cacheEntry = new AuthorizeCacheEntry(isAuthorized); + cache.putOnRead(key, cacheEntry); + } + /** * Looks up from cache whether given user is already authorized. If an entry * is not found throws an exception. diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/JDBCAuthorizationManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/JDBCAuthorizationManager.java index b10bc60a7cd..d71f5c2750b 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/JDBCAuthorizationManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/authorization/JDBCAuthorizationManager.java @@ -287,7 +287,7 @@ public boolean isUserAuthorized(String userName, String resourceId, String actio null, null, PermissionTreeUtil.toComponenets(resourceId)); if (sr.getLastNodeAllowedAccess()) { - authorizationCache.addToCache(cacheIdentifier, tenantId, userName, resourceId, action, true); + authorizationCache.addToCacheOnRead(cacheIdentifier, tenantId, userName, resourceId, action, true); return true; } @@ -370,7 +370,7 @@ public boolean isUserAuthorized(String userName, String resourceId, String actio } //need to add the authorization decision taken by role based permission - authorizationCache.addToCache(cacheIdentifier, this.tenantId, userName, resourceId, action, + authorizationCache.addToCacheOnRead(cacheIdentifier, this.tenantId, userName, resourceId, action, userAllowed); if (log.isDebugEnabled()) { diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java index 05b0b02c213..9cef42b17d8 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java @@ -8504,7 +8504,7 @@ private UserStore getUserStoreInternalWithId(String userId) throws UserStoreExce // in our local database. If so we can use that. String domainName = null; if (userUniqueIDDomainResolver != null) { - domainName = userUniqueIDDomainResolver.getDomainForUserId(userId, tenantId); + domainName = userUniqueIDDomainResolver.getDomainForUserIdOnRead(userId, tenantId); } // If we don't have the domain name in our side, then we have to iterate through each user store and find @@ -9499,6 +9499,23 @@ protected void addToUserRolesCache(int tenantID, String userName, String[] roleL } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + */ + protected void addToUserRolesCacheOnRead(int tenantID, String userName, String[] roleList) { + + if (userRolesCache != null) { + String usernameWithDomain = UserCoreUtil.addDomainToName(userName, getMyDomainName()); + String[] rolesWithDomain = UserCoreUtil.addDomainToNames(roleList, getMyDomainName()); + userRolesCache.addToCacheOnRead(cacheIdentifier, tenantID, usernameWithDomain, rolesWithDomain); + } + } + protected void clearUserRolesCache(String userIdentifier) { String usernameWithDomain = UserCoreUtil.addDomainToName(userIdentifier, getMyDomainName()); @@ -9825,7 +9842,7 @@ private List getUserRolesWithID(String userID, String filter) throws Use // Add to user role cache uisng username. String username = getUserNameFromUserID(userID); if (username != null) { - addToUserRolesCache(this.tenantId, username, roleList); + addToUserRolesCacheOnRead(this.tenantId, username, roleList); } return Arrays.asList(roleList); } @@ -9889,7 +9906,7 @@ private String[] getUserRoles(String username, String filter) throws UserStoreEx } } } - addToUserRolesCache(this.tenantId, username, roleList); + addToUserRolesCacheOnRead(this.tenantId, username, roleList); return roleList; } @@ -12360,7 +12377,7 @@ private AuthenticationResult authenticateInternalWithID(String preferredUserName if (status) { String userID = userUniqueIDManger.getUniqueId(users.get(0), this); User user = userUniqueIDManger. - getUser(userID, this, abstractUserStoreManager.getMyDomainName()); + getUserOnRead(userID, this, abstractUserStoreManager.getMyDomainName()); user.setTenantDomain(getTenantDomain(tenantId)); authenticationResult.setAuthenticatedUser(user); } else { @@ -12614,7 +12631,7 @@ private AuthenticationResult authenticateInternalWithID(String userID, Object cr .doAuthenticateWithID(userID, credential); } else { User user = userUniqueIDManger - .getUser(userID, (AbstractUserStoreManager) abstractUserStoreManager); + .getUserOnRead(userID, (AbstractUserStoreManager) abstractUserStoreManager); boolean status = ((AbstractUserStoreManager) abstractUserStoreManager) .doAuthenticate(user.getUsername(), credential); if (status) { @@ -12806,7 +12823,7 @@ public User getUserWithID(String userID, String[] requestedClaims, String profil if (isUniqueIdEnabled) { isUserExists = doCheckExistingUserWithID(userID); } else { - user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); isUserExists = user != null; } @@ -12827,7 +12844,7 @@ public User getUserWithID(String userID, String[] requestedClaims, String profil // If unique id feature is not enabled, we have to call the legacy methods. if (!isUniqueUserIdEnabledInUserStore(userStore)) { if (user == null) { - user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); } } else { user = getUserFromID(userID, requestedClaims, userStore.getDomainName(), profileName); @@ -12891,7 +12908,7 @@ public boolean isExistingUserWithID(String userID) throws UserStoreException { // If unique id feature is not enabled, we have to call the legacy methods. if (!isUniqueUserIdEnabledInUserStore(userStore)) { - User user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + User user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); if (user == null) { return false; } @@ -13186,7 +13203,7 @@ public final String getUserClaimValueWithID(String userID, String claim, String if (isUniqueIdEnabled) { isUserExists = doCheckExistingUserWithID(userID); } else{ - user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); isUserExists = user != null; } @@ -13284,9 +13301,9 @@ public final Map getUserClaimValuesWithID(String userID, String[ isUserExists = doCheckExistingUserWithID(userID); } else { if (userStore != null && StringUtils.isNotBlank(userStore.getDomainName())) { - user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); } else { - user = userUniqueIDManger.getUser(userID, this); + user = userUniqueIDManger.getUserOnRead(userID, this); } isUserExists = user != null; } @@ -13381,7 +13398,7 @@ public final List getUserClaimValuesWithID(String userID, String profileN // If unique id feature is not enabled, we have to call the legacy methods. if (!isUniqueIdEnabled) { - User user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + User user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); return Arrays.asList(getUserClaimValues(user.getDomainQualifiedUsername(), profileName)); } @@ -13808,7 +13825,7 @@ public User getUser(String userID, String userName) throws UserStoreException { user.setUserStoreDomain(domain); if (StringUtils.isNotEmpty(userID) && - StringUtils.isEmpty(userUniqueIDDomainResolver.getDomainForUserId(userID, tenantId))) { + StringUtils.isEmpty(userUniqueIDDomainResolver.getDomainForUserIdOnRead(userID, tenantId))) { userUniqueIDDomainResolver.setDomainForUserIdIfNotExists(userID, domain, tenantId); } return user; @@ -13944,7 +13961,7 @@ protected String doGetUserNameFromUserID(String userID) throws UserStoreExceptio } return doGetUserNameFromUserIDWithID(userID); } - User user = userUniqueIDManger.getUser(userID, this); + User user = userUniqueIDManger.getUserOnRead(userID, this); return user.getUsername(); } @@ -13966,7 +13983,7 @@ public String getUserNameFromUserID(String userID) throws UserStoreException { if (isUniqueUserIdEnabledInUserStore(userStore)) { return getUserNameFromCurrentUserStore(userID, userStore); } else { - User user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + User user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); if (user == null) { if (log.isDebugEnabled()) { log.debug(String.format("User with user id %s is not available in cache or database.", userID)); @@ -14039,14 +14056,14 @@ private String getFromUserIDCache(String userName, UserStore userStore) { private void addToUserIDCache(String userID, String userName, UserStore userStore) { UserIdResolverCache.getInstance() - .addToCache(UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), userID, + .addToCacheOnRead(UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), userID, RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); } private void addToUserNameCache(String userID, String userName, UserStore userStore) { UserIdResolverCache.getInstance() - .addToCache(userID, UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), + .addToCacheOnRead(userID, UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); } @@ -14067,7 +14084,7 @@ private void addUsersToUserIdCache(List userList) { UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); for (User user : userList) { - userIdResolverCacheInstance.addToCache( + userIdResolverCacheInstance.addToCacheOnRead( UserCoreUtil.addDomainToName(user.getUsername(), user.getUserStoreDomain()), user.getUserID(), RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); } @@ -14077,7 +14094,7 @@ private void addUsersToUserNameCache(List userList) { UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); for (User user : userList) { - userIdResolverCacheInstance.addToCache( + userIdResolverCacheInstance.addToCacheOnRead( user.getUserID(), UserCoreUtil.addDomainToName(user.getUsername(), user.getUserStoreDomain()), RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); } @@ -16478,7 +16495,7 @@ public boolean isUserInRoleWithID(String userID, String roleName) throws UserSto // #################### Domain Name Free Zone Starts Here ################################ // If unique id feature is not enabled, we have to call the legacy methods. if (!isUniqueUserIdEnabledInUserStore(userStore)) { - User user = userUniqueIDManger.getUser(userID, this, userStore.getDomainName()); + User user = userUniqueIDManger.getUserOnRead(userID, this, userStore.getDomainName()); // If we don't have a record for this user, let's try to call directly using the user id. if (user == null) { return false; @@ -16883,8 +16900,8 @@ public List getUserListWithID(Condition condition, String domain, String p User user = getUser(getUserIDFromUserName(username), username); user.setUserStoreDomain(UserCoreUtil.extractDomainFromName(username)); identityClaimFilteredUsers.add(user); - addToUserIDCache(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); - addToUserNameCache(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); + addToUserIDCacheOnRead(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); + addToUserNameCacheOnRead(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); } return identityClaimFilteredUsers; } @@ -20073,6 +20090,26 @@ public UserUniqueIDDomainResolver getUserUniqueIDDomainResolver() { return userUniqueIDDomainResolver; } + /** + * Add userID and username to UserID cache + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param userID User id. + * @param userName Username. + * @param userStoreDomain User store Domain. + */ + protected void addToUserIDCacheOnRead(String userID, String userName, String userStoreDomain) { + + UserIdResolverCache.getInstance() + .addToCacheOnRead(UserCoreUtil.addDomainToName(userName, userStoreDomain), userID, + RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); + } + /** * Retrieves the user count that belongs to a given group. * @@ -20134,6 +20171,26 @@ protected boolean isCircuitBreakerEnabledAndOpen() throws UserStoreException { return false; } + /** + * Add userID and username to Username cache + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param userID User id. + * @param userName Username. + * @param userStoreDomain User store Domain. + */ + protected void addToUserNameCacheOnRead(String userID, String userName, String userStoreDomain) { + + UserIdResolverCache.getInstance() + .addToCacheOnRead(userID, UserCoreUtil.addDomainToName(userName, userStoreDomain), + RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); + } + /** * Merge all identity claim filtered usernames and non identity claim filtered usernames in an efficient manner. * @@ -20210,8 +20267,8 @@ private List getUserListByUsernames(List usernames) throws UserSto User user = getUser(getUserIDFromUserName(username), username); user.setUserStoreDomain(UserCoreUtil.extractDomainFromName(username)); userList.add(user); - addToUserIDCache(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); - addToUserNameCache(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); + addToUserIDCacheOnRead(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); + addToUserNameCacheOnRead(user.getUserID(), user.getUsername(), user.getUserStoreDomain()); } return userList; } diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/DefaultRealmService.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/DefaultRealmService.java index ef8f1d19593..9818e5735d9 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/DefaultRealmService.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/DefaultRealmService.java @@ -188,7 +188,7 @@ private org.wso2.carbon.user.api.UserRealm getTenantUserRealmInternal(int tenant userRealm = getCachedUserRealm(tenantId); if (userRealm == null) { userRealm = initializeRealm(tenantRealmConfig, tenantId); - realmCache.addToCache(tenantId, PRIMARY_TENANT_REALM, userRealm); + realmCache.addToCacheOnRead(tenantId, PRIMARY_TENANT_REALM, userRealm); } } } @@ -256,7 +256,7 @@ private UserRealm getUserRealmInternal(RealmConfiguration tenantRealmConfig) thr userRealm = (UserRealm) realmCache.getUserRealm(tenantId, PRIMARY_TENANT_REALM); if (userRealm == null) { userRealm = initializeRealm(tenantRealmConfig, tenantId); - realmCache.addToCache(tenantId, PRIMARY_TENANT_REALM, userRealm); + realmCache.addToCacheOnRead(tenantId, PRIMARY_TENANT_REALM, userRealm); } } } diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/GroupIdResolverCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/GroupIdResolverCache.java index 8e06f0f8066..cfa4baa4fdf 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/GroupIdResolverCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/GroupIdResolverCache.java @@ -86,6 +86,26 @@ public void addToCache(String key, String entry, String cacheName, int tenantId) } } + public void addToCacheOnRead(String key, String entry, String cacheName, int tenantId) { + + if (validateAddToCacheRequest(key, entry, cacheName)) { + return; + } + try { + startTenantFlow(tenantId); + Cache cache = getGroupIdResolverCache(cacheName); + if (cache != null && !cache.containsKey(key)) { + cache.putOnRead(key, entry); + if (log.isDebugEnabled()) { + log.debug(String.format("Cache: %s which is under %s, added the entry: %s for the key: " + + "%s successfully", cacheName, GROUP_ID_RESOLVER_CACHE_MANAGER, entry, key)); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/RealmCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/RealmCache.java index 5f6db448d63..4dcb77e6abd 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/RealmCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/RealmCache.java @@ -102,6 +102,20 @@ public void addToCache(int tenantId, String realmName, UserRealm userRealm) { new RealmCacheEntry(userRealm)); } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + */ + public void addToCacheOnRead(int tenantId, String realmName, UserRealm userRealm) { + + instance.addToCacheOnRead(new RealmCacheKey(tenantId, realmName), + new RealmCacheEntry(userRealm)); + } + /** * Clear the cache entry * @@ -139,6 +153,32 @@ public void addToCache(RealmCacheKey key, RealmCacheEntry entry) { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + */ + public void addToCacheOnRead(RealmCacheKey key, RealmCacheEntry entry) { + + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + carbonContext.setTenantId(MultitenantConstants.SUPER_TENANT_ID); + carbonContext.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + Cache cache = getRealmCache(); + if (!cache.containsKey(key)) { + cache.putOnRead(key, entry); + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserIdResolverCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserIdResolverCache.java index 87150575aca..3370649fe66 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserIdResolverCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserIdResolverCache.java @@ -82,6 +82,36 @@ public void addToCache(String key, String entry, String cacheName, int tenantId) } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + * @param cacheName Name of the cache. + * @param tenantId Tenant ID. + */ + public void addToCacheOnRead(String key, String entry, String cacheName, int tenantId) { + + if (validateAddToCacheRequest(key, entry, cacheName)) return; + try { + startTenantFlow(tenantId); + Cache cache = UserIdResolverCache(cacheName); + if (cache != null && !cache.containsKey(key)) { + cache.putOnRead(key, entry); + if (log.isDebugEnabled()) { + log.debug("Cache: " + cacheName + " which is under " + USER_ID_RESOLVER_CACHE_MANAGER + "," + + "added the entry: " + entry + " for the key: " + key + " successfully"); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java index 574273b7ddd..4652fcda1ac 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java @@ -126,6 +126,39 @@ public void addToCache(String serverId, int tenantId, String userName, String[] } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + */ + public void addToCacheOnRead(String serverId, int tenantId, String userName, String[] userRoleList) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + carbonContext.setTenantId(tenantId, true); + + Cache cache = this.getUserRolesCache(); + //check for null + if (isCacheNull(cache)) { + return; + } + if (!isCaseSensitiveUsername(userName, tenantId)) { + userName = userName.toLowerCase(); + } + //create cache key + UserRolesCacheKey userRolesCacheKey = new UserRolesCacheKey(serverId, tenantId, userName); + //create cache entry + UserRolesCacheEntry userRolesCacheEntry = new UserRolesCacheEntry(userRoleList); + //add to cache + cache.putOnRead(userRolesCacheKey, userRolesCacheEntry); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + //get roles list of user public String[] getRolesListOfUser(String serverId, int tenantId, String userName) { try { diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDDomainResolver.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDDomainResolver.java index 0da4b9aeb8d..8bdfcfebbe6 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDDomainResolver.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDDomainResolver.java @@ -151,6 +151,77 @@ public String getDomainForUserId(String userId, int tenantId) throws UserStoreEx } } + /** + * Get the domain for the given user id. + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param userId Unique user id of the user. + * @return Domain related to this user. Null if no domain name recorded. + * @throws UserStoreException If error occurred. + */ + public String getDomainForUserIdOnRead(String userId, int tenantId) throws UserStoreException { + + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + carbonContext.setTenantId(tenantId, true); + CacheManager cacheManager = Caching.getCacheManagerFactory() + .getCacheManager(UNIQUE_ID_DOMAIN_RESOLVER_CACHE_MANGER_NAME); + Cache uniqueIdDomainCache = cacheManager.getCache(UNIQUE_ID_DOMAIN_RESOLVER_CACHE_NAME); + + if (StringUtils.isEmpty(userId)) { + throw new UserStoreException("User Id cannot be empty or null."); + } + + // Read the cache first. + String domainName = uniqueIdDomainCache.get(userId); + + if (StringUtils.isBlank(domainName)) { + if (log.isDebugEnabled()) { + log.debug("Cache miss for user id: " + userId + " searching from the database."); + } + + // Read the domain name from the Database; + domainName = getDomainFromDB(userId, tenantId); + + // Update the cache. + if (StringUtils.isNotBlank(domainName)) { + uniqueIdDomainCache.putOnRead(userId, domainName); + if (log.isDebugEnabled()) { + log.debug("Domain with name: " + domainName + " retrieved from the database."); + } + } + } + if (StringUtils.isNotBlank(domainName) && + !UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME.equals(domainName)) { + RealmService realmService = UserCoreUtil.getRealmService(); + UserStoreManager userStoreManager = null; + if (realmService != null) { + userStoreManager = ((AbstractUserStoreManager) realmService.getTenantUserRealm(tenantId) + .getUserStoreManager()).getSecondaryUserStoreManager(domainName); + } + if (userStoreManager == null) { + if (log.isDebugEnabled()) { + log.debug("Entry is outdated. Clearing cache and the database entries."); + } + deleteDomainFromDB(domainName, userId, tenantId); + clearUserIDResolverCache(userId, tenantId); + domainName = null; + } + } + return domainName; + } catch (org.wso2.carbon.user.api.UserStoreException e) { + throw new UserStoreException("Tenant user realm cannot be resolved for tenantId: " + tenantId, e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Set the domain for the user id. This will update the domain name if there is already a record available. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java index 9b13564d8a7..9c6465b9b0c 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java @@ -117,6 +117,63 @@ public User getUser(String uniqueId, AbstractUserStoreManager userStoreManager, return user; } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Get user from unique id. + * @param uniqueId User's unique id. + * @return User object if user presents for the unique id. Null otherwise. + */ + public User getUserOnRead(String uniqueId, AbstractUserStoreManager userStoreManager) + throws UserStoreException { + + return getUserOnRead(uniqueId, userStoreManager, null); + } + + /** + * Get user from unique id with user store domain present. + * @param uniqueId User's unique id. + * @param userStoreManager User store manager instance. + * @param userStoreDomain User store domain of the user. + * @return User object if user presents for the unique id. Null otherwise. + */ + public User getUserOnRead(String uniqueId, AbstractUserStoreManager userStoreManager, String userStoreDomain) + throws UserStoreException { + + String userName = getFromUserNameCache(uniqueId); + if (StringUtils.isEmpty(userName)) { + String[] usernames; + if (StringUtils.isNotEmpty(userStoreDomain)) { + usernames = userStoreManager.getUserList(UserCoreClaimConstants.USER_ID_CLAIM_URI, + UserCoreUtil.addDomainToName(uniqueId, userStoreDomain), null); + } else { + usernames = userStoreManager.getUserList(UserCoreClaimConstants.USER_ID_CLAIM_URI, + uniqueId, null); + } + + if (usernames.length > 1) { + throw new UserStoreException("More than one user presents with the same user unique id."); + } + + if (usernames.length == 0) { + return null; + } + userName = usernames[0]; + addToUserNameCacheOnRead(uniqueId, userName); + addToUserIDCacheOnRead(uniqueId, userName); + } + + User user = new User(); + user.setUserID(uniqueId); + user.setUsername(UserCoreUtil.removeDomainFromName(userName)); + user.setUserStoreDomain(UserCoreUtil.extractDomainFromName(userName)); + return user; + } + private void addToUserIDCache(String userID, String userName) { UserIdResolverCache.getInstance() @@ -124,6 +181,23 @@ private void addToUserIDCache(String userID, String userName) { RESOLVE_USER_UNIQUE_ID_FROM_USER_NAME_CACHE_NAME, SUPER_TENANT_ID); } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param userID + * @param userName + */ + private void addToUserIDCacheOnRead(String userID, String userName) { + + UserIdResolverCache.getInstance() + .addToCacheOnRead(userName, userID, + RESOLVE_USER_UNIQUE_ID_FROM_USER_NAME_CACHE_NAME, SUPER_TENANT_ID); + } + private void addToUserNameCache(String userID, String userName) { UserIdResolverCache.getInstance() @@ -131,6 +205,23 @@ private void addToUserNameCache(String userID, String userName) { RESOLVE_USER_NAME_FROM_UNIQUE_USER_ID_CACHE_NAME, SUPER_TENANT_ID); } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param userID + * @param userName + */ + private void addToUserNameCacheOnRead(String userID, String userName) { + + UserIdResolverCache.getInstance() + .addToCacheOnRead(userID, userName, + RESOLVE_USER_NAME_FROM_UNIQUE_USER_ID_CACHE_NAME, SUPER_TENANT_ID); + } + private String getFromUserNameCache(String userID) { return UserIdResolverCache.getInstance().getValueFromCache(userID, diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/jdbc/UniqueIDJDBCUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/jdbc/UniqueIDJDBCUserStoreManager.java index 44c28d312ad..d0cde532b05 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/jdbc/UniqueIDJDBCUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/jdbc/UniqueIDJDBCUserStoreManager.java @@ -4029,8 +4029,8 @@ private void processUserResultSet(ResultSet rs, List userList) throws SQLE String userID = rs.getString(1); String userName = rs.getString(2); if (StringUtils.isNotBlank(userID) && StringUtils.isNotBlank(userName)) { - addToUserIDCache(userID, userName, getMyDomainName()); - addToUserNameCache(userID, userName, getMyDomainName()); + addToUserIDCacheOnRead(userID, userName, getMyDomainName()); + addToUserNameCacheOnRead(userID, userName, getMyDomainName()); } User user = getUser(userID, userName); @@ -4043,8 +4043,8 @@ private void processUsernameResultSet(ResultSet rs, List usernameList) t String userID = rs.getString(1); String userName = rs.getString(2); if (StringUtils.isNotBlank(userID) && StringUtils.isNotBlank(userName)) { - addToUserIDCache(userID, userName, getMyDomainName()); - addToUserNameCache(userID, userName, getMyDomainName()); + addToUserIDCacheOnRead(userID, userName, getMyDomainName()); + addToUserNameCacheOnRead(userID, userName, getMyDomainName()); } userName = UserCoreUtil.addDomainToName(userName, getMyDomainName()); usernameList.add(userName); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java index dbe4b2dc6e7..ba4a0328a97 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java @@ -908,7 +908,7 @@ public boolean doCheckExistingUser(String userName) throws UserStoreException { if (userDN != null && userDN.length() > 0) { bFound = true; LdapName ldapName = new LdapName(userDN); - putToUserCache(userName, ldapName); + putToUserCacheOnRead(userName, ldapName); break; } } @@ -2525,7 +2525,7 @@ protected String getNameInSpaceForUserName(String userName, String searchBase, S } if (userDN != null) { LdapName ldn = new LdapName(userDN); - putToUserCache(userName, ldn); + putToUserCacheOnRead(userName, ldn); } if (debug) { log.debug("Name in space for " + userName + " is " + userDN); @@ -4662,6 +4662,35 @@ protected void putToUserCache(String name, LdapName value) { } } + /** + * Puts the DN into the cache. + *

+ * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + * + * @param name the username. + * @param value the LDAP name (DN) + */ + protected void putToUserCacheOnRead(String name, LdapName value) { + try { + startTenantFlow(); + Cache userDnCache = createOrGetUserDnCache(); + if (userDnCache == null) { + // User cache may be null while initializing. + return; + } + userDnCache.putOnRead(name, value); + } catch (IllegalStateException e) { + // There is no harm ignoring the put, as the cache(local) is already is of no use. Mis-penalty is low. + log.error("Error occurred while putting User DN to the cache having search base : " + userSearchBase, e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Returns the LDAP Name (DN) for the given user name, if it exists in the cache. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java index 50d9ae42dfa..9cbb9c0235b 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java @@ -1634,8 +1634,8 @@ protected UniqueIDPaginatedUsernameSearchResult doGetUsernameListWithID(Conditio doGetUserListWithID(condition, profileName, limit, offset, sortBy, sortOrder); List usernames = new ArrayList<>(); uniqueIDPaginatedSearchResult.getUsers().forEach(user -> { - addToUserIDCache(user.getUserID(), user.getUsername(), getMyDomainName()); - addToUserNameCache(user.getUserID(), user.getUsername(), getMyDomainName()); + addToUserIDCacheOnRead(user.getUserID(), user.getUsername(), getMyDomainName()); + addToUserNameCacheOnRead(user.getUserID(), user.getUsername(), getMyDomainName()); usernames.add(user.getDomainQualifiedUsername()); }); result.setUsers(usernames); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/FileSystemTenantManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/FileSystemTenantManager.java index fbaab129630..5b9ab3fedc2 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/FileSystemTenantManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/FileSystemTenantManager.java @@ -142,7 +142,7 @@ public Tenant getTenant(int tenantId) throws UserStoreException { tenant.setRealmConfig(realmConfig); tenant.setAdminName(realmConfig.getAdminUserName()); - tenantCacheManager.addToCache(new TenantIdKey(tenantId), new TenantCacheEntry(tenant)); + tenantCacheManager.addToCacheOnRead(new TenantIdKey(tenantId), new TenantCacheEntry(tenant)); } catch (CarbonException e) { String errorMessage = "Error occurred while getting tenant from tenant id : " + tenant; diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java index 7b8ae855e70..f2d950c5bc9 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java @@ -498,9 +498,9 @@ public Tenant getTenant(int tenantId) throws UserStoreException { + ", hence adding tenant to cache where tenantDomain: {" + domain + "}"); } tenantDomainNameValidation(domain); - tenantCacheManager.addToCache(new TenantIdKey(id), new TenantCacheEntry(tenant)); - tenantDomainCache.addToCache(new TenantIdKey(id), new TenantDomainEntry(domain)); - tenantIdCache.addToCache(new TenantDomainKey(domain), new TenantIdEntry(id)); + tenantCacheManager.addToCacheOnRead(new TenantIdKey(id), new TenantCacheEntry(tenant)); + tenantDomainCache.addToCacheOnRead(new TenantIdKey(id), new TenantDomainEntry(domain)); + tenantIdCache.addToCacheOnRead(new TenantDomainKey(domain), new TenantIdEntry(id)); } dbConnection.commit(); } catch (SQLException e) { @@ -648,7 +648,7 @@ public String getDomain(int tenantId) throws UserStoreException { + "tenant ID:" + tenantId + ", hence adding tenant domain and tenant ID to cache."); } tenantDomainNameValidation(tenantDomain); - tenantDomainCache.addToCache(tenantIdKey, new TenantDomainEntry(tenantDomain)); + tenantDomainCache.addToCacheOnRead(tenantIdKey, new TenantDomainEntry(tenantDomain)); tenantIdCache.addToCache(new TenantDomainKey(tenantDomain), new TenantIdEntry(tenantId)); } @@ -750,7 +750,7 @@ public int getTenantId(String tenantDomain) throws UserStoreException { + tenantDomain + "}, hence adding tenant domain and tenant ID to cache."); } tenantDomainNameValidation(tenantDomain); - tenantIdCache.addToCache(tenantDomainKey, new TenantIdEntry(tenantId)); + tenantIdCache.addToCacheOnRead(tenantDomainKey, new TenantIdEntry(tenantId)); tenantDomainCache.addToCache(new TenantIdKey(tenantId), new TenantDomainEntry(tenantDomain)); } } catch (SQLException e) { @@ -830,10 +830,11 @@ public Tenant getTenant(String tenantUniqueID) throws UserStoreException { + ", hence adding tenant to cache where tenantDomain: {" + domain + "}"); } tenantDomainNameValidation(domain); - tenantUniqueIdCache.addToCache(new TenantUniqueIDKey(uniqueId), new TenantCacheEntry(tenant)); - tenantCacheManager.addToCache(new TenantIdKey(id), new TenantCacheEntry(tenant)); - tenantDomainCache.addToCache(new TenantIdKey(id), new TenantDomainEntry(domain)); - tenantIdCache.addToCache(new TenantDomainKey(domain), new TenantIdEntry(id)); + tenantUniqueIdCache + .addToCacheOnRead(new TenantUniqueIDKey(uniqueId), new TenantCacheEntry(tenant)); + tenantCacheManager.addToCacheOnRead(new TenantIdKey(id), new TenantCacheEntry(tenant)); + tenantDomainCache.addToCacheOnRead(new TenantIdKey(id), new TenantDomainEntry(domain)); + tenantIdCache.addToCacheOnRead(new TenantDomainKey(domain), new TenantIdEntry(id)); } dbConnection.commit(); } catch (SQLException e) { diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantCache.java index 3cf8c381705..9b01782fe1c 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantCache.java @@ -94,6 +94,46 @@ public void addToCache(TenantIdKey key, T entry) { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Add a cache entry. + * Tenant + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + */ + public void addToCacheOnRead(TenantIdKey key, T entry) { + + PrivilegedCarbonContext.startTenantFlow(); + + try { + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + carbonContext.setTenantId(MultitenantConstants.SUPER_TENANT_ID); + carbonContext.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + + Cache cache = getTenantCache(); + if (cache != null) { + cache.putOnRead(key, entry); + if (log.isDebugEnabled()) { + log.debug(TENANT_CACHE + " which is under " + TENANT_CACHE_MANAGER + ", added the entry : " + entry + + " for the key : " + key + " successfully"); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Error while getting the cache : " + TENANT_CACHE + " which is under " + + TENANT_CACHE_MANAGER); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java index 8335fb6f50f..2290dc6ea27 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java @@ -84,6 +84,37 @@ public void addToCache(TenantIdKey key, TenantDomainEntry entry) { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Add a cache entry. + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + */ + public void addToCacheOnRead(TenantIdKey key, TenantDomainEntry entry) { + + try { + startSuperTenantFlow(); + Cache cache = getTenantDomainCache(); + if (cache != null) { + cache.putOnRead(key, entry); + log.debug(TENANT_DOMAIN_CACHE + " which is under " + TENANT_DOMAIN_CACHE_MANAGER + ", added the entry : " + entry + + " for the key : " + key + " successfully"); + } else { + if (log.isDebugEnabled()) { + log.debug("Error while getting the cache : " + TENANT_DOMAIN_CACHE + " which is under " + TENANT_DOMAIN_CACHE_MANAGER); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantIdCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantIdCache.java index ad28972bf89..474d45f4e3c 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantIdCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantIdCache.java @@ -88,6 +88,38 @@ public void addToCache(TenantDomainKey key, TenantIdEntry entry) { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Add a cache entry. + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + */ + public void addToCacheOnRead(TenantDomainKey key, TenantIdEntry entry) { + + try { + startSuperTenantFlow(); + Cache cache = getTenantIdCache(); + if (cache != null) { + cache.putOnRead(key, entry); + log.debug(TENANT_ID_CACHE + " which is under " + TENANT_ID_CACHE_MANAGER + ", added the entry : " + + entry + " for the key : " + key + " successfully"); + } else { + if (log.isDebugEnabled()) { + log.debug("Error while getting the cache : " + TENANT_ID_CACHE + " which is under " + + TENANT_ID_CACHE_MANAGER); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantUniqueIdCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantUniqueIdCache.java index 5a661df81fd..be7e15b1296 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantUniqueIdCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantUniqueIdCache.java @@ -93,6 +93,43 @@ public void addToCache(TenantUniqueIDKey key, T entry) { } } + /** + * Add a cache entry during a READ operation. + *

+ * This populates the cache only if the key does not already have a value. + * If a value already exists, the cache is left unchanged, which avoids + * unnecessary cache invalidation broadcasts in clustered environments. + *

+ * Add a cache entry. + * Tenant + * + * @param key Key which cache entry is indexed. + * @param entry Actual object where cache entry is placed. + */ + public void addToCacheOnRead(TenantUniqueIDKey key, T entry) { + + PrivilegedCarbonContext.startTenantFlow(); + + try { + startSuperTenantFlow(); + Cache cache = getTenantUUIDCache(); + if (cache != null) { + cache.putOnRead(key, entry); + if (log.isDebugEnabled()) { + log.debug(TENANT_UNIQUE_ID_CACHE + " which is under " + TENANT_UNIQUE_ID_CACHE_MANAGER + ", " + + "added the entry : " + entry + " for the key : " + key + " successfully"); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Error while getting the cache : " + TENANT_UNIQUE_ID_CACHE + " which is under " + + TENANT_UNIQUE_ID_CACHE_MANAGER); + } + } + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + /** * Retrieves a cache entry. * From 9aef45eacaaf9fd39de58dc4a6da14a7690c3ae4 Mon Sep 17 00:00:00 2001 From: Dinitha Wijewardhana Date: Fri, 20 Mar 2026 19:57:51 +0530 Subject: [PATCH 2/2] Address reviewer suggestions --- .../core/jdbc/dao/JDBCResourceDAO.java | 1 + .../core/common/AbstractUserStoreManager.java | 58 +++++++++++++++---- .../user/core/common/UserRolesCache.java | 15 ++--- .../user/core/common/UserUniqueIDManger.java | 4 +- .../ldap/ReadOnlyLDAPUserStoreManager.java | 1 + .../UniqueIDReadOnlyLDAPUserStoreManager.java | 4 +- .../user/core/tenant/JDBCTenantManager.java | 4 +- .../user/core/tenant/TenantDomainCache.java | 15 ++--- 8 files changed, 70 insertions(+), 32 deletions(-) diff --git a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java index 3bc5b473c95..9aaa1846ff5 100644 --- a/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java +++ b/core/org.wso2.carbon.registry.core/src/main/java/org/wso2/carbon/registry/core/jdbc/dao/JDBCResourceDAO.java @@ -2211,6 +2211,7 @@ public String getPathFromId(int pathId) throws RegistryException { * */ public String getPathFromIdOnRead(int pathId) throws RegistryException { + try { return JDBCPathCache.getPathCache() .getPathOnRead(JDBCDatabaseTransaction.getConnection(), pathId); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java index 9cef42b17d8..8778a932d52 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java @@ -11263,8 +11263,8 @@ public String[] getUserList(Condition condition, String domain, String profileNa if (((AbstractUserStoreManager) secManager).isUniqueUserIdEnabled()) { UniqueIDPaginatedSearchResult users = ((AbstractUserStoreManager) secManager).doGetUserListWithID(condition, profileName, limit, offset, sortBy, sortOrder); - addUsersToUserIdCache(users.getUsers()); - addUsersToUserNameCache(users.getUsers()); + addUsersToUserIdCacheOnRead(users.getUsers()); + addUsersToUserNameCacheOnRead(users.getUsers()); filteredUsers = users.getUsers().stream().map(User::getUsername).toArray(String[]::new); } else { PaginatedSearchResult users = ((AbstractUserStoreManager) secManager).doGetUserList(condition, @@ -13910,8 +13910,8 @@ public String getUserIDFromUserName(String userName) throws UserStoreException { log.debug("User is not available in cache or database."); return null; } - addToUserIDCache(userID, userName, userStore); - addToUserNameCache(userID, userName, userStore); + addToUserIDCacheOnRead(userID, userName, userStore); + addToUserNameCacheOnRead(userID, userName, userStore); return userID; } @@ -13920,8 +13920,8 @@ public String getUserIDFromUserName(String userName) throws UserStoreException { userStore.getDomainName(), null); if (claims != null && claims.size() == 1) { userID = claims.get(USER_ID_CLAIM_URI); - addToUserIDCache(userID, userName, userStore); - addToUserNameCache(userID, userName, userStore); + addToUserIDCacheOnRead(userID, userName, userStore); + addToUserNameCacheOnRead(userID, userName, userStore); return userID; } } @@ -14014,8 +14014,8 @@ private String getUserNameFromCurrentUserStore(String userID, UserStore userStor } return null; } - addToUserNameCache(userID, userName, userStore); - addToUserIDCache(userID, userName, userStore); + addToUserNameCacheOnRead(userID, userName, userStore); + addToUserIDCacheOnRead(userID, userName, userStore); } return UserCoreUtil.addDomainToName(userName, userStore.getDomainName()); } @@ -14055,6 +14055,13 @@ private String getFromUserIDCache(String userName, UserStore userStore) { private void addToUserIDCache(String userID, String userName, UserStore userStore) { + UserIdResolverCache.getInstance() + .addToCache(UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), userID, + RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); + } + + private void addToUserIDCacheOnRead(String userID, String userName, UserStore userStore) { + UserIdResolverCache.getInstance() .addToCacheOnRead(UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), userID, RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); @@ -14062,6 +14069,13 @@ private void addToUserIDCache(String userID, String userName, UserStore userStor private void addToUserNameCache(String userID, String userName, UserStore userStore) { + UserIdResolverCache.getInstance() + .addToCache(userID, UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), + RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); + } + + private void addToUserNameCacheOnRead(String userID, String userName, UserStore userStore) { + UserIdResolverCache.getInstance() .addToCacheOnRead(userID, UserCoreUtil.addDomainToName(userName, userStore.getDomainName()), RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); @@ -14082,6 +14096,16 @@ private void clearUserIDResolverCache(String userID, String userName, UserStore private void addUsersToUserIdCache(List userList) { + UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); + for (User user : userList) { + userIdResolverCacheInstance.addToCache( + UserCoreUtil.addDomainToName(user.getUsername(), user.getUserStoreDomain()), user.getUserID(), + RESOLVE_USER_ID_FROM_USER_NAME_CACHE_NAME, tenantId); + } + } + + private void addUsersToUserIdCacheOnRead(List userList) { + UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); for (User user : userList) { userIdResolverCacheInstance.addToCacheOnRead( @@ -14092,6 +14116,16 @@ private void addUsersToUserIdCache(List userList) { private void addUsersToUserNameCache(List userList) { + UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); + for (User user : userList) { + userIdResolverCacheInstance.addToCache( + user.getUserID(), UserCoreUtil.addDomainToName(user.getUsername(), user.getUserStoreDomain()), + RESOLVE_USER_NAME_FROM_USER_ID_CACHE_NAME, tenantId); + } + } + + private void addUsersToUserNameCacheOnRead(List userList) { + UserIdResolverCache userIdResolverCacheInstance = UserIdResolverCache.getInstance(); for (User user : userList) { userIdResolverCacheInstance.addToCacheOnRead( @@ -17210,8 +17244,8 @@ private List getFilteredUsers(Condition condition, String profileName, int if (isUniqueUserIdEnabled(secManager)) { UniqueIDPaginatedSearchResult users = ((AbstractUserStoreManager) secManager) .doGetUserListWithID(condition, profileName, limit, offset, sortBy, sortOrder); - addUsersToUserIdCache(users.getUsers()); - addUsersToUserNameCache(users.getUsers()); + addUsersToUserIdCacheOnRead(users.getUsers()); + addUsersToUserNameCacheOnRead(users.getUsers()); filteredUsers = users.getUsers(); } else { PaginatedSearchResult users = ((AbstractUserStoreManager) secManager) @@ -18468,8 +18502,8 @@ public List getUserListOfGroup(String groupID, int limit, int offset, Stri UniqueIDPaginatedSearchResult users = this.doGetUserListWithID(condition, UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME, resolveUserListLimit(limit), offset, sortBy, sortOrder); - addUsersToUserIdCache(users.getUsers()); - addUsersToUserNameCache(users.getUsers()); + addUsersToUserIdCacheOnRead(users.getUsers()); + addUsersToUserNameCacheOnRead(users.getUsers()); filteredUsers = users.getUsers(); } else { PaginatedSearchResult users = this.doGetUserList(condition, UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME, diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java index 4652fcda1ac..68ed70b9182 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserRolesCache.java @@ -18,7 +18,13 @@ */ package org.wso2.carbon.user.core.common; -import org.apache.commons.lang.StringUtils; +import java.util.concurrent.TimeUnit; + +import javax.cache.Cache; +import javax.cache.CacheConfiguration; +import javax.cache.CacheManager; +import javax.cache.Caching; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.caching.impl.CachingConstants; @@ -29,12 +35,6 @@ import org.wso2.carbon.user.core.internal.UserStoreMgtDSComponent; import org.wso2.carbon.user.core.util.UserCoreUtil; -import javax.cache.Cache; -import javax.cache.CacheConfiguration; -import javax.cache.CacheManager; -import javax.cache.Caching; -import java.util.concurrent.TimeUnit; - public class UserRolesCache { private static final String USER_ROLES_CACHE_MANAGER = "USER_ROLES_CACHE_MANAGER"; @@ -135,6 +135,7 @@ public void addToCache(String serverId, int tenantId, String userName, String[] * */ public void addToCacheOnRead(String serverId, int tenantId, String userName, String[] userRoleList) { + try { PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java index 9c6465b9b0c..eff823afe96 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/UserUniqueIDManger.java @@ -106,8 +106,8 @@ public User getUser(String uniqueId, AbstractUserStoreManager userStoreManager, return null; } userName = usernames[0]; - addToUserNameCache(uniqueId, userName); - addToUserIDCache(uniqueId, userName); + addToUserNameCacheOnRead(uniqueId, userName); + addToUserIDCacheOnRead(uniqueId, userName); } User user = new User(); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java index ba4a0328a97..25272b8945c 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/ReadOnlyLDAPUserStoreManager.java @@ -4675,6 +4675,7 @@ protected void putToUserCache(String name, LdapName value) { * @param value the LDAP name (DN) */ protected void putToUserCacheOnRead(String name, LdapName value) { + try { startTenantFlow(); Cache userDnCache = createOrGetUserDnCache(); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java index 9cbb9c0235b..dcde45e9873 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/ldap/UniqueIDReadOnlyLDAPUserStoreManager.java @@ -1529,8 +1529,8 @@ public List doGetUserListFromPropertiesWithID(String property, String va if (StringUtils.equals(property, realmConfig.getUserStoreProperty(LDAPConstants.USER_NAME_ATTRIBUTE))) { putToUserCache(value, new LdapName(sr.getNameInNamespace())); - addToUserNameCache(propertyValue, value, getMyDomainName()); - addToUserIDCache(propertyValue, value, getMyDomainName()); + addToUserNameCacheOnRead(propertyValue, value, getMyDomainName()); + addToUserIDCacheOnRead(propertyValue, value, getMyDomainName()); } } } diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java index f2d950c5bc9..96c4d72ec3c 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/JDBCTenantManager.java @@ -649,7 +649,7 @@ public String getDomain(int tenantId) throws UserStoreException { } tenantDomainNameValidation(tenantDomain); tenantDomainCache.addToCacheOnRead(tenantIdKey, new TenantDomainEntry(tenantDomain)); - tenantIdCache.addToCache(new TenantDomainKey(tenantDomain), new TenantIdEntry(tenantId)); + tenantIdCache.addToCacheOnRead(new TenantDomainKey(tenantDomain), new TenantIdEntry(tenantId)); } if (tenantDomain != null) { @@ -751,7 +751,7 @@ public int getTenantId(String tenantDomain) throws UserStoreException { } tenantDomainNameValidation(tenantDomain); tenantIdCache.addToCacheOnRead(tenantDomainKey, new TenantIdEntry(tenantId)); - tenantDomainCache.addToCache(new TenantIdKey(tenantId), new TenantDomainEntry(tenantDomain)); + tenantDomainCache.addToCacheOnRead(new TenantIdKey(tenantId), new TenantDomainEntry(tenantDomain)); } } catch (SQLException e) { DatabaseUtil.rollBack(dbConnection); diff --git a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java index 2290dc6ea27..1b436b35875 100644 --- a/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java +++ b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/tenant/TenantDomainCache.java @@ -22,15 +22,15 @@ * Date: Oct 1, 2010 Time: 2:36:37 PM */ +import javax.cache.Cache; +import javax.cache.CacheManager; +import javax.cache.Caching; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; -import javax.cache.Cache; -import javax.cache.CacheManager; -import javax.cache.Caching; - /** * This is the tenant cache. */ @@ -103,11 +103,12 @@ public void addToCacheOnRead(TenantIdKey key, TenantDomainEntry entry) { Cache cache = getTenantDomainCache(); if (cache != null) { cache.putOnRead(key, entry); - log.debug(TENANT_DOMAIN_CACHE + " which is under " + TENANT_DOMAIN_CACHE_MANAGER + ", added the entry : " + entry - + " for the key : " + key + " successfully"); + log.debug(TENANT_DOMAIN_CACHE + " which is under " + TENANT_DOMAIN_CACHE_MANAGER + + ", added the entry : " + entry + " for the key : " + key + " successfully"); } else { if (log.isDebugEnabled()) { - log.debug("Error while getting the cache : " + TENANT_DOMAIN_CACHE + " which is under " + TENANT_DOMAIN_CACHE_MANAGER); + log.debug("Error while getting the cache : " + TENANT_DOMAIN_CACHE + + " which is under " + TENANT_DOMAIN_CACHE_MANAGER); } } } finally {