![JAR search and dependency download from the Maven repository](/logo.png)
com.viaoa.object.OAObjectPropertyDelegate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oa-core Show documentation
Show all versions of oa-core Show documentation
Object Automation library
/* Copyright 1999 Vince Via [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.viaoa.object;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.viaoa.hub.Hub;
import com.viaoa.remote.multiplexer.OARemoteThreadDelegate;
import com.viaoa.sync.OASync;
import com.viaoa.util.OANotExist;
// 20140225 redone to simplify property locking using CAS
/**
* Manages OAObject.properties, which are used to store references
* (OAObjects, Hubs, OAObjectKey) and misc values.
* Stores as name/value in a flat object array, where even positions are property names and odd positions are the value, which can be null.
* This uses a flat array to make it as efficient as possible for the oaObject with as little overhead as possible.
*/
public class OAObjectPropertyDelegate {
private static Logger LOG = Logger.getLogger(OAObjectPropertyDelegate.class.getName());
/**
* @return true if prop is loaded, and does not need to be loaded from datasource, or from server (if this is client)
*/
public static boolean isPropertyLoaded(OAObject oaObj, String name) {
if (oaObj == null || name == null) return false;
Object[] props = oaObj.properties;
if (props == null) return false;
for (int i=0; i hmLock = new ConcurrentHashMap();
private static final ConcurrentHashMap hmLockedThread = new ConcurrentHashMap();
private static class PropertyLock {
final Thread thread;
boolean done;
boolean hasWait;
public PropertyLock(Thread thread) {
this.thread = thread;
}
}
public static boolean setPropertyLock(OAObject oaObj, String name) {
return _setPropertyLock(oaObj, name, true, false);
}
public static boolean attemptPropertyLock(OAObject oaObj, String name) {
return _setPropertyLock(oaObj, name, false, true);
}
private static boolean _setPropertyLock(final OAObject oaObj, final String name, final boolean bWaitIfNeeded, final boolean bCheckIfThisThread) {
if (oaObj == null || name == null) return false;
String key = OAObjectDelegate.getGuid(oaObj) + "." + name.toUpperCase();
PropertyLock lock;
final Thread threadThis = Thread.currentThread();
synchronized (oaObj) {
lock = hmLock.get(key);
if (lock == null) {
lock = new PropertyLock(threadThis);
hmLock.put(key, lock);
return true;
}
if (lock.thread == threadThis) return true;
}
hmLockedThread.put(threadThis, lock.thread);
try {
OARemoteThreadDelegate.startNextThread();
synchronized (lock) {
if (lock.thread == Thread.currentThread()) return bCheckIfThisThread;
if (!bWaitIfNeeded) return false;
long ms = 0;
for (int i=0; ;i++) {
if (i > 3) {
// see if the thread that thisThread is waiting on is waiting on another thread
Thread tx = hmLockedThread.get(lock.thread);
if (tx != null) {
if (OAObject.getDebugMode()) {
String s = oaObj.getObjectKey().toString();
s = "thread with lock is waiting on a lock, obj="+oaObj+", key="+s+", prop="+name+", this.Thread="+Thread.currentThread().getName()+", waiting on Thread="+lock.thread.getName()+" (see next stacktrace), will continue";
LOG.log(Level.WARNING, s, new Exception("fyi: avoiding deadlock, will continue"));
StackTraceElement[] stes = lock.thread.getStackTrace();
Exception ex = new Exception();
ex.setStackTrace(stes);
LOG.log(Level.WARNING, "... waiting on this Thread="+lock.thread.getName(), ex);
}
break;
}
if (ms == 0) ms = System.currentTimeMillis();
else if (System.currentTimeMillis() - ms > 60000) {
if (OAObject.getDebugMode()) {
String s = oaObj.getObjectKey().toString();
s = "wait time exceeded for lock, obj="+oaObj+", key="+s+", prop="+name+", this.Thread="+Thread.currentThread().getName()+", waiting on Thread="+lock.thread.getName()+" (see next stacktrace), will continue";
LOG.log(Level.WARNING, s, new Exception("fyi: wait time exceeded, will continue"));
StackTraceElement[] stes = lock.thread.getStackTrace();
Exception ex = new Exception();
ex.setStackTrace(stes);
LOG.log(Level.WARNING, "... waiting on this Thread="+lock.thread.getName(), ex);
}
return false; // bail out, ouch
}
}
if (lock.done) break;
lock.hasWait = true;
try {
lock.wait(100);
}
catch (Exception e) {
}
}
}
}
finally {
hmLockedThread.remove(threadThis);
}
return _setPropertyLock(oaObj, name, bWaitIfNeeded, bCheckIfThisThread); // create a new one
}
public static void releasePropertyLock(OAObject oaObj, String name) {
if (oaObj == null || name == null) return;
String key = OAObjectDelegate.getGuid(oaObj) + "." + name.toUpperCase();
PropertyLock lock;
synchronized (oaObj) {
lock = hmLock.remove(key);
}
if (lock != null) {
synchronized (lock) {
lock.done = true;
if (lock.hasWait) {
lock.notifyAll();
}
}
}
}
public static boolean isPropertyLocked(OAObject oaObj, String name) {
if (oaObj == null || name == null) return false;
String key = OAObjectKeyDelegate.getKey(oaObj).getGuid() + "." + name.toUpperCase();
return (hmLock.get(key) != null);
}
// 20141108 "flip" a hub property to/from a weakRef. Used by HubDelegate.setReferenceable
public static boolean setPropertyWeakRef(OAObject oaObj, String name, boolean bToWeakRef, Object value) {
if (name == null || oaObj == null || oaObj.properties == null) return false;
boolean b = false;
synchronized (oaObj) {
for (int i=0; i 0) {
Object objx = OAObjectPropertyDelegate.getProperty((OAObject) parent, liRev.getName(), true, false);
if (objx instanceof OANotExist) continue;
if (objx instanceof WeakReference) {
objx = ((WeakReference) objx).get();
}
if (!(objx instanceof Hub)) continue;
boolean b = OAObjectPropertyDelegate.setPropertyWeakRef((OAObject) parent, liRev.getName(), !bReferenceable, (Hub) objx);
if (!b) break; // already changed, dont need to continue
}
if (bReferenceable) {
if (cascade == null) cascade = new OACascade();
// 20191019
cascade.wasCascaded(obj, true);
// was: cascade.add(obj);
setReferenceable((OAObject)parent, bReferenceable, cascade);
}
}
}
public static void clearProperties(OAObject oaObj) {
if (oaObj != null) oaObj.properties = null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy