Skip to content

Commit

Permalink
AdminCache - trywith, logging, synchronization
Browse files Browse the repository at this point in the history
- however synchronization here still doesn't guarantee anything, usages
  are not atomic

Signed-off-by: David Matějček <david.matejcek@omnifish.ee>
  • Loading branch information
dmatej committed Dec 7, 2022
1 parent 7197b90 commit a7e8523
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation
* Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -91,12 +91,6 @@ public static Logger getLogger() {
@LogMessageInfo(message = "Error searching for a default admin user", cause = "An unexpected exception occurred wihle searching for the default admin user.", action = "Check the server logs and contact Oracle support", publish = true, level = "WARNING")
public final static String mAdminUserSearchError = LOGMSG_PREFIX + "-00015";

@LogMessageInfo(message = "Cannot read admin cache file for {0}", cause = "An error occured while reading the admin command model cache file.", action = "Check the server logs and contact Oracle support", publish = true, level = "WARNING")
public final static String mCannotReadCache = LOGMSG_PREFIX + "-00016";

@LogMessageInfo(message = "Cannot write data to cache file for {0}", cause = "An error occured while writing the admin command model cache file.", action = "Check the server logs and contact Oracle support", publish = true, level = "WARNING")
public final static String mCannotWriteCache = LOGMSG_PREFIX + "-00017";

@LogMessageInfo(message = "Unexpected exception from command event listener.", cause = "An error occured while calling registered listener.", action = "Check the server logs and contact Oracle support", publish = true, level = "WARNING")
public final static String mExceptionFromEventListener = LOGMSG_PREFIX + "-00018";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
* Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand All @@ -25,7 +26,7 @@
import java.util.logging.Logger;

/**
* {@link AdminCahce} based on file system.<br/>
* {@link AdminCache} based on file system.<br/>
* <i>Singleton</i>
*
* @author mmares
Expand All @@ -35,15 +36,16 @@ public class AdminCacheFileStore implements AdminCache {
private static final String DEFAULT_FILENAME = "#default#.cache";
private static final AdminCacheFileStore instance = new AdminCacheFileStore();

private static final Logger logger = AdminLoggerInfo.getLogger();
private static final Logger LOG = AdminLoggerInfo.getLogger();

private AdminCacheUtils adminCahceUtils = AdminCacheUtils.getInstance();
private final AdminCacheUtils adminCahceUtils = AdminCacheUtils.getInstance();

private AdminCacheFileStore() {
}

@Override
public <A> A get(String key, Class<A> clazz) {
LOG.log(Level.FINEST, "get(key={0}, clazz={1})", new Object[] {key, clazz});
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Attribute key must be unempty.");
}
Expand All @@ -54,27 +56,14 @@ public <A> A get(String key, Class<A> clazz) {
if (provider == null) {
return null;
}
// @todo Java SE 7 - use try with resources
InputStream is = null;
try {
is = getInputStream(key);
try (InputStream is = getInputStream(key)) {
return (A) provider.toInstance(is, clazz);
} catch (FileNotFoundException ex) {
return null;
} catch (IOException ex) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, AdminLoggerInfo.mCannotReadCache, new Object[] { key });
}
LOG.log(Level.WARNING, "Cannot read admin cache file for " + key, ex);
return null;
} finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
}
}
}

}

private InputStream getInputStream(String key) throws IOException {
Expand All @@ -94,8 +83,9 @@ private File getCacheFile(String key) throws IOException {
if (idx > 0) {
dir = new File(dir, key.substring(0, idx));

if (!FileUtils.mkdirsMaybe(dir))
if (!FileUtils.mkdirsMaybe(dir)) {
throw new IOException("Can't create directory: " + dir);
}
key = key.substring(idx + 1);
if (key.isEmpty()) {
key = DEFAULT_FILENAME;
Expand All @@ -106,6 +96,7 @@ private File getCacheFile(String key) throws IOException {

@Override
public synchronized void put(String key, Object data) {
LOG.log(Level.FINEST, "put(key, data={0})", new Object[] {key, data});
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Attribute key must be unempty.");
}
Expand All @@ -122,34 +113,29 @@ public synchronized void put(String key, Object data) {
File cacheFile;
try {
cacheFile = getCacheFile(key);
} catch (IOException ex) {
} catch (IOException e) {
LOG.log(Level.WARNING, "Cannot write data to cache file for " + key, e);
return;
}
// @todo Java SE 7 - use try with resources
OutputStream os = null;

final File tempFile;
try {
File tempFile = File.createTempFile("temp", "cache", cacheFile.getParentFile());
os = new BufferedOutputStream(new FileOutputStream(tempFile));
tempFile = File.createTempFile("temp", "cache", cacheFile.getParentFile());
} catch (IOException e) {
LOG.log(Level.WARNING, "Cannot create a temp file for future cache file " + cacheFile, e);
return;
}
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(tempFile))) {
provider.writeToStream(data, os);
os.close();

if (!FileUtils.deleteFileMaybe(cacheFile) || !tempFile.renameTo(cacheFile)) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, AdminLoggerInfo.mCannotWriteCache, new Object[] { cacheFile.getPath() });
}
if (!FileUtils.deleteFileMaybe(tempFile)) {
logger.log(Level.FINE, "can't delete file: {0}", tempFile);
}

}
} catch (IOException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, AdminLoggerInfo.mCannotWriteCache, new Object[] { cacheFile.getPath() });
}
} finally {
try {
os.close();
} catch (Exception ex) {
LOG.log(Level.WARNING, "Cannot write data to temp file " + tempFile, e);
return;
}

if (!FileUtils.deleteFileMaybe(cacheFile) || !tempFile.renameTo(cacheFile)) {
LOG.log(Level.WARNING, "Cannot delete or rename to cache file " + cacheFile);
if (!FileUtils.deleteFileMaybe(tempFile)) {
LOG.log(Level.FINE, "Can't delete file {0}", tempFile);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.sun.enterprise.admin.util.cache;

import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.HashMap;
Expand All @@ -29,67 +31,23 @@
* @author mmares
*/
public class AdminCacheWeakReference implements AdminCache {
private static final Logger LOG = System.getLogger(AdminCacheWeakReference.class.getName());

private final static class CachedItem {

private WeakReference item;
private long updated = -1;
private Date lastUpdateInStore;

private CachedItem(final Object item) {
setItem(item);
}

private CachedItem(final Object item, final Date lastUpdateInStore) {
setItem(item);
this.lastUpdateInStore = lastUpdateInStore;
}

private CachedItem(final Date lastUpdateInStore) {
this.lastUpdateInStore = lastUpdateInStore;
}

public Object getItem() {
if (item == null) {
return null;
} else {
return item.get();
}
}

public void setItem(Object item) {
if (item == null) {
this.item = null;
} else {
this.item = new WeakReference(item);
}
this.updated = System.currentTimeMillis();
}

public Date getLastUpdateInStore() {
return lastUpdateInStore;
}

public void setLastUpdateInStore(Date lastUpdateInStore) {
this.lastUpdateInStore = lastUpdateInStore;
}
private static final AdminCacheWeakReference instance = new AdminCacheWeakReference();

public long getUpdated() {
return updated;
}
private final AdminCacheFileStore fileCache = AdminCacheFileStore.getInstance();
private final Map<String, CachedItem> cache = new HashMap<>();

public static AdminCacheWeakReference getInstance() {
return instance;
}

private static final AdminCacheWeakReference instance = new AdminCacheWeakReference();

private AdminCacheFileStore fileCache = AdminCacheFileStore.getInstance();
private final Map<String, CachedItem> cache = new HashMap<String, CachedItem>();

private AdminCacheWeakReference() {
}

@Override
public <A> A get(final String key, final Class<A> clazz) {
public synchronized <A> A get(final String key, final Class<A> clazz) {
LOG.log(Level.DEBUG, "get(key={0}, clazz={1})", key, clazz);
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Attribute key must be unempty.");
}
Expand Down Expand Up @@ -120,30 +78,32 @@ public <A> A get(final String key, final Class<A> clazz) {
}

@Override
public void put(final String key, final Object data) {
public synchronized void put(final String key, final Object data) {
LOG.log(Level.DEBUG, "put(key={0}, data={1})", key, data);
fileCache.put(key, data);
cache.put(key, new CachedItem(data, new Date()));
}

@Override
public boolean contains(final String key) {
public synchronized boolean contains(final String key) {
LOG.log(Level.TRACE, "contains(key={0})", key);
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Attribute key must be unempty.");
}
CachedItem item = cache.get(key);
if (item != null) {
return true;
} else {
boolean result = fileCache.contains(key);
if (result) {
cache.put(key, new CachedItem(null));
}
return result;
}
boolean result = fileCache.contains(key);
if (result) {
cache.put(key, new CachedItem(null));
}
return result;
}

@Override
public Date lastUpdated(String key) {
public synchronized Date lastUpdated(String key) {
LOG.log(Level.TRACE, "lastUpdated(key={0})", key);
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Attribute key must be unempty.");
}
Expand All @@ -157,16 +117,61 @@ public Date lastUpdated(String key) {
cache.put(key, new CachedItem(result));
} else {
if (item.updated != -1 && item.updated < result.getTime()) {
item.setItem(null); //Cleare it because it was changed after load
// Clear it because it was changed after load
item.setItem(null);
}
item.lastUpdateInStore = result;
}
}
return result;
}

public static AdminCacheWeakReference getInstance() {
return instance;
}
private static final class CachedItem {

private WeakReference<?> item;
private long updated = -1;
private Date lastUpdateInStore;

private CachedItem(final Object item) {
setItem(item);
}

private CachedItem(final Object item, final Date lastUpdateInStore) {
setItem(item);
this.lastUpdateInStore = lastUpdateInStore;
}

private CachedItem(final Date lastUpdateInStore) {
this.lastUpdateInStore = lastUpdateInStore;
}

public Object getItem() {
if (item == null) {
return null;
}
return item.get();
}

public void setItem(Object item) {
if (item == null) {
this.item = null;
} else {
this.item = new WeakReference<>(item);
}
this.updated = System.currentTimeMillis();
}

public Date getLastUpdateInStore() {
return lastUpdateInStore;
}

public void setLastUpdateInStore(Date lastUpdateInStore) {
this.lastUpdateInStore = lastUpdateInStore;
}

public long getUpdated() {
return updated;
}

}
}

0 comments on commit a7e8523

Please sign in to comment.