use of groovy.lang.Binding in project groovity by disney.
the class Groovity method startClass.
protected void startClass(Class<?> clz) {
if (clz != null) {
final GroovityClassLoader gcl = (GroovityClassLoader) clz.getClassLoader();
Class<?>[] cls = gcl.getLoadedClasses();
for (Class<?> cl : cls) {
Method m = null;
try {
m = cl.getDeclaredMethod(START);
} catch (Throwable e) {
}
if (m != null) {
try {
if (Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0) {
LinkedHashMap<String, Object> variables = new LinkedHashMap<>();
Binding binding = new Binding(variables);
if (bindingDecorator != null) {
bindingDecorator.decorateRecursive(variables);
}
ScriptHelper.THREAD_BINDING.set(binding);
try {
m.invoke(null);
} finally {
ScriptHelper.THREAD_BINDING.remove();
}
log.info("Started " + cl);
}
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof Error) {
throw (Error) t;
}
log.log(Level.SEVERE, "Error starting " + cl, t);
} catch (Exception e) {
log.log(Level.SEVERE, "Error starting " + cl, e);
}
}
}
}
}
use of groovy.lang.Binding in project groovity by disney.
the class Groovity method initClass.
protected void initClass(Class<?> clz) {
if (clz != null) {
final GroovityClassLoader gcl = (GroovityClassLoader) clz.getClassLoader();
gcl.init(traits);
// here is where we call upon our Configurator
if (configurator != null) {
try {
gcl.configure(configurator);
} catch (Exception e) {
log.log(Level.SEVERE, "Error configuring " + clz.getName(), e);
}
}
// Now let's register the ArgsBindingVisitor with the classloader
try {
java.lang.reflect.Field argsField = clz.getDeclaredField(ARGS);
if (Modifier.isStatic(argsField.getModifiers())) {
argsField.setAccessible(true);
Object argsValue = argsField.get(null);
if (argsValue != null && argsValue instanceof Map) {
@SuppressWarnings("unchecked") Map<String, Object> av = (Map<String, Object>) argsValue;
gcl.setArgsResolver(new ArgsResolver(av, getSourcePath(clz)));
}
}
} catch (NoSuchFieldException e) {
} catch (Exception e) {
log.log(Level.SEVERE, "Error intializing script arguments for " + clz.getName(), e);
}
Class<?>[] cls = gcl.getLoadedClasses();
for (Class<?> cl : cls) {
try {
// inject GroovityScriptFactory
java.lang.reflect.Field factoryField = cl.getDeclaredField(GROOVITY_SCRIPT_HELPER_FIELD);
factoryField.setAccessible(true);
factoryField.set(null, gcl.getScriptHelper());
} catch (Throwable e) {
}
Method m = null;
try {
m = cl.getDeclaredMethod(INIT);
} catch (Throwable e) {
}
if (m != null) {
try {
if (Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0) {
LinkedHashMap<String, Object> variables = new LinkedHashMap<>();
Binding binding = new Binding(variables);
if (bindingDecorator != null) {
bindingDecorator.decorateRecursive(variables);
}
ScriptHelper.THREAD_BINDING.set(binding);
try {
m.invoke(null);
} finally {
ScriptHelper.THREAD_BINDING.remove();
}
log.info("Initialized " + cl);
}
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof Error) {
throw (Error) t;
}
log.log(Level.SEVERE, "Error initing " + cl, t);
} catch (Exception e) {
log.log(Level.SEVERE, "Error initing " + cl, e);
}
}
}
}
}
use of groovy.lang.Binding in project groovity by disney.
the class Async method tag.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object tag(Map attributes, final Closure body) throws Exception {
final Integer timeoutSeconds = resolve(attributes, TIMEOUT, Integer.class);
final ScriptHelper scriptHelper = getScriptHelper(body);
final Binding binding = scriptHelper.getBinding();
final Map variables = binding.getVariables();
final AwaitContext asyncContext = AwaitContext.get(variables);
DeadlockFreeExecutor createdThreadPool = null;
// make a copy of current binding for async
final Map asyncVariables = asyncCopy(variables);
if (asyncContext == null || !asyncVariables.containsKey(Async.EXECUTOR_BINDING)) {
Integer numThreads = resolve(attributes, POOL, Integer.class);
if (numThreads != null) {
createdThreadPool = new DeadlockFreeExecutor(interruptFactory, numThreads);
asyncVariables.put(EXECUTOR_BINDING, createdThreadPool);
}
}
final DeadlockFreeExecutor asyncPool = createdThreadPool != null ? createdThreadPool : ((asyncContext != null) ? getExecutor(asyncVariables) : sharedThreadPool);
final boolean shutdownPool = createdThreadPool != null;
final CharArrayWriter out = new CharArrayWriter();
asyncVariables.put(OUT, out);
if (asyncContext != null) {
// signal a boundary for sequencing async output
asyncContext.signalAsync(variables, out);
}
final Execution parentStack = asyncContext != null ? asyncContext.getWaitingExecution() : null;
String scriptPath = scriptHelper.getClassLoader().getScriptName();
final long timeoutTime = timeoutSeconds == null ? -1 : System.currentTimeMillis() + (timeoutSeconds * 1000);
final Callable<Object> bodyRunner = new Callable<Object>() {
@Override
public Object call() throws Exception {
Binding asyncBinding = new Binding(asyncVariables);
Binding oldThreadBinding = ScriptHelper.THREAD_BINDING.get();
ScriptHelper.THREAD_BINDING.set(asyncBinding);
final Execution restoreStack = parentStack != null ? GroovityStatistics.registerStack(parentStack) : null;
try {
Closure asyncBody;
if (body.getThisObject() instanceof Class) {
// if the parent script is not available it is a special case (static) and we may share the context
asyncBody = body;
asyncBody.setDelegate(asyncBinding);
asyncBody.setResolveStrategy(Closure.DELEGATE_FIRST);
} else {
Script asyncInstance = scriptHelper.load(scriptPath);
asyncBody = body.rehydrate(asyncInstance, asyncInstance, asyncInstance);
}
if (timeoutTime > 0) {
// use an interrupt to enforce the timeout
long startTime = System.currentTimeMillis();
if (startTime > timeoutTime) {
throw new InterruptedException();
}
final ScheduledFuture<?> interrupt = interruptFactory.scheduleInterrupt(timeoutTime - startTime);
try {
return asyncBody.call();
} finally {
interrupt.cancel(true);
}
}
return asyncBody.call();
} catch (Throwable e) {
if (asyncContext == null) {
// with no known waiters this exception could get lost, let's log it
log.log(Level.SEVERE, "Error in async", e);
}
throw e;
} finally {
if (oldThreadBinding == null) {
ScriptHelper.THREAD_BINDING.remove();
} else {
ScriptHelper.THREAD_BINDING.set(oldThreadBinding);
}
if (parentStack != null) {
GroovityStatistics.registerStack(restoreStack);
}
if (shutdownPool) {
sharedThreadPool.submit(new Runnable() {
@Override
public void run() {
asyncPool.shutdown();
try {
if (!asyncPool.awaitTermination(60, TimeUnit.SECONDS)) {
asyncPool.shutdownNow();
asyncPool.awaitTermination(60, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
asyncPool.shutdownNow();
}
}
});
}
}
}
};
Future<Object> future = asyncPool.submit(bodyRunner);
if (asyncContext != null) {
asyncContext.add(future);
}
String var = resolve(attributes, VAR, String.class);
if (var != null && var.length() > 0) {
variables.put(var, future);
}
return future;
}
use of groovy.lang.Binding in project groovity by disney.
the class Cache method get.
public Map<Object, Object> get(Iterable<Object> keys, int refresh, int ttl) {
Map<Object, CacheValue> found = new LinkedHashMap<Object, CacheValue>();
Map<Object, CompletableFuture<CacheValue>> loadKeys = null;
for (Object key : keys) {
found.put(key, null);
}
long tooOld = ttl > 0 ? Caches.currentCacheTime - ttl : 0;
long toRefresh = refresh > 0 ? Caches.currentCacheTime - refresh : 0;
// step 1, load from valueStore
getValueStore().getAll(found);
int hits = 0, misses = 0;
// step 2, expire TTL
for (Entry<Object, CacheValue> entry : found.entrySet()) {
CacheValue cv = entry.getValue();
if (cv != null) {
if (cv.getCreated() < tooOld) {
// expired, force sync load
entry.setValue(null);
getValueStore().remove(entry.getKey(), cv);
} else {
if (cv.getCreated() < toRefresh && cv.pendingRefresh.compareAndSet(false, true)) {
// past refresh date, offer for async refresh
refreshQueue.offer(entry.getKey());
}
hits++;
continue;
}
}
// no value, load it
if (loadKeys == null) {
loadKeys = new LinkedHashMap<>();
}
loadKeys.put(entry.getKey(), null);
misses++;
}
// step 3, synchronous loading
if (loadKeys != null) {
Map<Object, Object> myLoadKeys = null;
Map<Object, CompletableFuture<CacheValue>> myLoadFutures = null;
try {
for (Entry<Object, CompletableFuture<CacheValue>> entry : loadKeys.entrySet()) {
final Object key = entry.getKey();
CompletableFuture<CacheValue> keyFuture = syncLoadMap.get(key);
if (keyFuture == null) {
keyFuture = new CompletableFuture<>();
CompletableFuture<CacheValue> oldFuture = syncLoadMap.putIfAbsent(key, keyFuture);
if (oldFuture == null) {
if (myLoadKeys == null) {
myLoadKeys = new LinkedHashMap<>();
myLoadFutures = new LinkedHashMap<>();
}
// we are good to load on this thread
myLoadKeys.put(key, null);
myLoadFutures.put(key, keyFuture);
// System.out.println("Will load key "+key+" on thread "+Thread.currentThread().getName());
entry.setValue(keyFuture);
} else {
// another thread beat us
// System.out.println("Will belatedly await "+key+" on thread "+Thread.currentThread().getName());
entry.setValue(oldFuture);
}
} else {
// another thread is loading
// System.out.println("Will await key "+key+" on thread "+Thread.currentThread().getName());
entry.setValue(keyFuture);
}
}
if (myLoadKeys != null) {
LinkedHashMap<String, Object> variables = new LinkedHashMap<>();
Binding safeBinding = new Binding(variables);
if (bindingDecorator != null) {
bindingDecorator.decorateRecursive(variables);
}
safeBinding.setVariable(MAP, myLoadKeys);
final Binding oldBinding = ScriptHelper.THREAD_BINDING.get();
ScriptHelper.THREAD_BINDING.set(safeBinding);
try {
@SuppressWarnings("rawtypes") Closure closure = getCacheLoader().rehydrate(getScriptHelper(), safeBinding, getScriptHelper());
closure.call(myLoadKeys);
// System.out.println("Cache sync loaded "+myLoadKeys.size());
for (Entry<Object, Object> lentry : myLoadKeys.entrySet()) {
Object val = lentry.getValue();
if (val instanceof Future) {
// auto-resolve futures
@SuppressWarnings("unchecked") Future<Object> fv = ((Future<Object>) lentry.getValue());
val = fv.get();
}
// instantiate CacheValue
CacheValue cv = new CacheValue(val);
getValueStore().put(lentry.getKey(), cv);
myLoadFutures.get(lentry.getKey()).complete(cv);
// found.put(lentry.getKey(),cv);
}
} catch (Exception e) {
for (CompletableFuture<CacheValue> future : myLoadFutures.values()) {
future.completeExceptionally(e);
}
throw new RuntimeException("Could not load value for " + loadKeys + ": " + e.getClass().getName() + ": " + e.getMessage(), e);
} finally {
if (oldBinding == null) {
ScriptHelper.THREAD_BINDING.remove();
} else {
ScriptHelper.THREAD_BINDING.set(oldBinding);
}
}
}
for (Entry<Object, CompletableFuture<CacheValue>> entry : loadKeys.entrySet()) {
found.put(entry.getKey(), entry.getValue().get());
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} finally {
if (myLoadFutures != null) {
for (Entry<Object, CompletableFuture<CacheValue>> entry : myLoadFutures.entrySet()) {
syncLoadMap.remove(entry.getKey(), entry.getValue());
}
}
}
}
// step 4, produce return map with clones as needed and nulls ommitted
Map<Object, Object> rval = new LinkedHashMap<>();
for (Entry<Object, CacheValue> entry : found.entrySet()) {
CacheValue cv;
Object v;
if (((cv = entry.getValue()) != null) && ((v = cv.getValue()) != null)) {
rval.put(entry.getKey(), v);
}
;
}
manager.update(hits, misses);
return rval;
}
use of groovy.lang.Binding in project groovity by disney.
the class Cache method init.
public void init() {
manager = new CacheManager(this);
valueStore.init();
refreshFuture = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
if (!refreshQueue.isEmpty()) {
final HashSet<Object> refreshSet = new HashSet<>(getBatchSize() * 2);
// draining to a set should weed out the duplicates
refreshQueue.drainTo(refreshSet);
if (!refreshSet.isEmpty()) {
scheduler.execute(new Runnable() {
@SuppressWarnings("rawtypes")
public void run() {
List<Object> keys = new ArrayList<>(refreshSet);
Map<Object, Object> valueMap = new HashMap<Object, Object>(keys.size() * 2);
LinkedHashMap<String, Object> variables = new LinkedHashMap<>();
Binding safeBinding = new Binding(variables);
if (bindingDecorator != null) {
bindingDecorator.decorateRecursive(variables);
}
safeBinding.setVariable(MAP, valueMap);
final Binding oldBinding = ScriptHelper.THREAD_BINDING.get();
ScriptHelper.THREAD_BINDING.set(safeBinding);
try {
Closure closure = getCacheLoader().rehydrate(getScriptHelper(), safeBinding, getScriptHelper());
// split up the work into batches
int numBatches = (int) Math.ceil(keys.size() / (double) getBatchSize());
for (int b = 0; b < numBatches; b++) {
valueMap.clear();
for (int i = (b * getBatchSize()); i < (b + 1) * getBatchSize() && i < keys.size(); i++) {
valueMap.put(keys.get(i), null);
}
closure.call(valueMap);
for (Entry<Object, Object> lentry : valueMap.entrySet()) {
Object val = lentry.getValue();
if (val instanceof Future) {
// auto-resolve futures
val = ((Future) lentry.getValue()).get();
}
// instantiate CacheValue
CacheValue cv = new CacheValue(val);
getValueStore().put(lentry.getKey(), cv);
}
}
// log.info("Cache async refreshed "+valueMap.size());
} catch (Exception e) {
log.log(Level.SEVERE, "Cache refresh error with " + valueMap, e);
} finally {
if (oldBinding == null) {
ScriptHelper.THREAD_BINDING.remove();
} else {
ScriptHelper.THREAD_BINDING.set(oldBinding);
}
}
}
});
}
}
} catch (Throwable th) {
log.log(Level.SEVERE, "Error refreshing caches", th);
}
}
}, 1000, 1000, TimeUnit.MILLISECONDS);
}
Aggregations