wtorek, lutego 24, 2015

How to release unused XiNodes from BW process variables

BW accumulates variables across job lifetime. Very often intermediate variables in later steps are not needed any more, but still occupy memory. It is possible to clean them and make more memory for new jobs, globally reducing RAM requirement for whole BW instance.

package Libraries.Utils.ReleaseVariable;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.io.*;
import org.xml.sax.InputSource;

import com.tibco.xml.datamodel.XiNode;
import com.tibco.xml.datamodel.XiParserFactory;
import com.tibco.xml.xdata.xpath.Variable;
import com.tibco.xml.xdata.xpath.VariableList;
import com.tibco.pe.core.*;

public class ReleaseVariableJavaCode{

 public static JobPool getJobPool() {
  for (Field f : Engine.class.getDeclaredFields()) {
   if (f.getType().getName().endsWith("JobPool")) {
    f.setAccessible(true);
    try {
     return (JobPool) f.get(null);
    }
    catch (Throwable te) {
     throw new RuntimeException("Cannot access JobPool: "+te.getMessage(), te);
    }    
   }   
  }
  throw new RuntimeException("Cannot access JobPool");
 }

 public static long[] getJobIds() {
  try {
   return getJobPool().getJobIds();
  }
  catch (Throwable t) {
   throw new RuntimeException("Cannot access JobPool.getJobIds(): "+t.getMessage(), t);
  }
 }
 
 public static VariableList getJobVariables(long jid, int trackId) {
  try {
   Method getAttributes = Class.forName("com.tibco.pe.core.Job").getDeclaredMethod("getAttributes", new Class<?>[] { int.class });
   getAttributes.setAccessible(true);
   return (VariableList) getAttributes.invoke(getJobPool().findJob(jid), trackId);
  }
  catch (Throwable t) {
   throw new RuntimeException("Cannot access job variables: "+t.getMessage(), t);
  }
 }

 public int getTrackId(long jid) {
  try {
   Method getter = Class.forName("com.tibco.pe.core.Job").getDeclaredMethod("getTrackId", new Class<?>[0]);
   getter.setAccessible(true);
   return (int) getter.invoke(getJobPool().findJob(jid));
  }
  catch (Throwable t) {
   throw new RuntimeException("Cannot access job methods: "+t.getMessage(), t);
  }
 }

 public void nullifyXiNode(XiNode node) {
  while (node!=null && node.hasChildNodes())
   node.removeChild(node.getLastChild());
  if (callGC==1)
   System.gc();
 }

 public void prune(XiNode node, String[] tokens, int i) {
  //System.out.println("prune at level "+i+" of "+node);
  if (i==1)
   node = node.hasChildNodes() ? node.getFirstChild() : null; // root node
  while (node!=null) {
   //System.out.println("node name is "+(node.getName()!=null ? node.getName().getLocalName() : null));
   if (node.getName() != null && tokens[i].equals(node.getName().getLocalName())) {
    if (i == tokens.length-1) {
     //System.out.println("nullify");
     nullifyXiNode(  node );
    }
    else {
     XiNode nd = node.hasChildNodes() ? node.getFirstChild() : null;
     if (nd!=null) {
      prune(nd, tokens, i+1);      
     }
    }
   }
   node = node.hasNextSibling() ? node.getNextSibling() : null;
  }
 }
/****** START SET/GET METHOD, DO NOT MODIFY *****/
 protected long jobId = 0;
 protected String var = "";
 protected int callGC = 0;
 public long getjobId() {
  return jobId;
 }
 public void setjobId(long val) {
  jobId = val;
 }
 public String getvar() {
  return var;
 }
 public void setvar(String val) {
  var = val;
 }
 public int getcallGC() {
  return callGC;
 }
 public void setcallGC(int val) {
  callGC = val;
 }
/****** END SET/GET METHOD, DO NOT MODIFY *****/
 public ReleaseVariableJavaCode() {
 }
 public void invoke() throws Exception {
/* Available Variables: DO NOT MODIFY
 In  : long jobId
 In  : String var
 In  : int callGC
* Available Variables: DO NOT MODIFY *****/
String[] tokens = var.split("/");
int currentTrackId = getTrackId(jobId);

for (int iter=0; iter <= 4; iter++) {
    VariableList varList = getJobVariables(jobId, iter);
    Variable v = varList!=null && iter != currentTrackId ? varList.getVariable(tokens[0]) : null;

    if (v!=null) { 
      if (tokens.length == 1) {
          nullifyXiNode(  v.getValue() ); 
      }
      else if (tokens.length>1) {
  prune( v.getValue(), tokens, 1); 
      }
    }
}


}
}

0 komentarze: