package org.openntf.domino.tests.ntf;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import lotus.domino.Database;
import lotus.domino.DateRange;
import lotus.domino.DateTime;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.DxlExporter;
import lotus.domino.Item;
import lotus.domino.Name;
import lotus.domino.NoteCollection;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;
/*
* @author NTF
* This runnable class is designed to test the behavior of the lotus.domino API with regard to recycling objects.
* If we fail to recycle the date objects and run multiple threads, we get crashes.
* If we fail to recycle non-date objects and run multiple threads, we get Backend Out of Memory Handles messages
*
*/
public class NotesRunner implements Runnable {
private static Method getCppMethod;
@SuppressWarnings("unused")
private static int bitMode;
private static Field cpp_field;
private static Field wr_field;
private static ThreadLocal<Long> sessionid = new ThreadLocal<Long>() {
/* (non-Javadoc)
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected Long initialValue() {
return 0L;
}
/* (non-Javadoc)
* @see java.lang.ThreadLocal#set(java.lang.Object)
*/
@Override
public void set(final Long value) {
super.set(value);
System.out.println("Session id: " + value);
}
};
private static ThreadLocal<Long> minid = new ThreadLocal<Long>() {
/* (non-Javadoc)
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected Long initialValue() {
return Long.MAX_VALUE;
}
@Override
public void set(final Long value) {
if (value < super.get()) {
// System.out.println("New Min is " + value);
super.set(value);
if (sessionid.get() > 0) {
long delta = (value - sessionid.get()) >> 3; //difference divided by 8 (is a negative number)
// if (delta > 8192l) {
System.out.println(Thread.currentThread().getName() + " is New min: " + value + " session diff: " + delta
+ " session: " + sessionid.get());
// }
} else {
System.out.println("Setting up session id as min");
}
}
};
};
private static ThreadLocal<Long> maxid = new ThreadLocal<Long>() {
/* (non-Javadoc)
* @see java.lang.ThreadLocal#initialValue()
*/
@Override
protected Long initialValue() {
return 0L;
}
@Override
public void set(final Long value) {
// if (value % 8 != 0) {
// System.out.println("Encountered a cppid that's not a multiple of 8!");
// }
if (value > super.get()) {
super.set(value);
if (sessionid.get() > 0) {
long delta = (value - sessionid.get()) >> 3; //difference divided by 8
if (delta > 8192l) {
System.out.println(Thread.currentThread().getName() + " is New max: " + value + " session diff: " + delta
+ " session: " + sessionid.get());
}
} else {
System.out.println("Setting up session id as max");
}
}
};
};
static {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
String bitModeRaw = System.getProperty("com.ibm.vm.bitmode");
try {
int mode = Integer.valueOf(bitModeRaw);
System.out.println("Set bitmode to " + mode);
} catch (Exception e) {
e.printStackTrace();
}
getCppMethod = lotus.domino.local.NotesBase.class.getDeclaredMethod("GetCppObj", (Class<?>[]) null);
getCppMethod.setAccessible(true);
wr_field = lotus.domino.local.NotesBase.class.getDeclaredField("weakObject");
wr_field.setAccessible(true);
Class<?> clazz = wr_field.getType();
cpp_field = clazz.getDeclaredField("cpp_object");
cpp_field.setAccessible(true);
return null;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public static long getLotusId(final lotus.domino.Base base) {
try {
Object o = wr_field.get(base);
long result = (Long) cpp_field.get(o);
maxid.set(result);
minid.set(result);
return result;
} catch (Exception e) {
return 0L;
}
}
public static void incinerate(final lotus.domino.Base base) {
try {
base.recycle();
} catch (NotesException e) {
}
}
@SuppressWarnings("unused")
private static Map<Long, Byte> idMap = new ConcurrentHashMap<Long, Byte>();
public static void main(final String[] args) throws InterruptedException {
try {
// Properties props = System.getProperties();
// for (Object key : props.keySet()) {
// Object value = props.get(key);
// System.out.println(String.valueOf(key) + " : " + String.valueOf(value));
// }
NotesThread.sinitThread();
for (int i = 0; i < 1; i++) {
NotesRunner run = new NotesRunner();
NotesThread nt = new NotesThread(run, "Thread " + i);
nt.start();
Thread.sleep(500);
}
} finally {
NotesThread.stermThread();
}
}
public NotesRunner() {
}
public void run1(final Session session) throws NotesException {
Long sessId = getLotusId(session);
sessionid.set(sessId);
Database db = session.getDatabase("", "names.nsf");
System.out.println("Db id:" + getLotusId(db));
Name name = null;
int i = 0;
try {
for (i = 0; i <= 100000; i++) {
name = session.createName(UUID.randomUUID().toString());
getLotusId(name);
DateTime dt = session.createDateTime(new Date());
getLotusId(dt);
DateTime end = session.createDateTime(new Date());
getLotusId(end);
DateRange dr = session.createDateRange(dt, end);
getLotusId(dr);
Document doc = db.createDocument();
getLotusId(doc);
Item i1 = doc.replaceItemValue("Foo", dr);
getLotusId(i1);
Item i2 = doc.replaceItemValue("Bar", dr.getText());
getLotusId(i2);
Item i3 = doc.replaceItemValue("Blah", dr.getStartDateTime().getLocalTime());
getLotusId(i3);
lotus.domino.ColorObject color = session.createColorObject();
getLotusId(color);
color.setRGB(128, 128, 128);
Item i4 = doc.replaceItemValue("color", color.getNotesColor());
getLotusId(i4);
i1.recycle();
i2.recycle();
i3.recycle();
i4.recycle();
DateTime create = doc.getCreated();
getLotusId(create);
@SuppressWarnings("unused")
String lc = create.getLocalTime();
// if (i % 10000 == 0) {
// System.out.println(Thread.currentThread().getName() + " Name " + i + " is " + name.getCommon() + " "
// + "Local time is " + lc + " " + dr.getText());
// }
dr.recycle();
doc.recycle();
dt.recycle();
end.recycle();
create.recycle();
color.recycle();
name.recycle();
}
} catch (Throwable t) {
t.printStackTrace();
System.out.println("Exception at loop point " + i);
}
}
public void run2(final Session session) throws NotesException {
Database db = session.getDatabase("", "log.nsf");
Document doc = db.createDocument();
Item names = doc.replaceItemValue("Names", "CN=Nathan T Freeman/O=REDPILL");
names.setAuthors(true);
doc.replaceItemValue("form", "test");
doc.save(true);
String nid = doc.getNoteID();
doc.recycle();
doc = db.getDocumentByID(nid);
Vector<Double> numbers = new Vector<Double>();
numbers.add(new Double(1));
numbers.add(new Double(2));
doc.replaceItemValue("Names", numbers);
doc.save(true);
doc.recycle();
doc = db.getDocumentByID(nid);
names = doc.getFirstItem("Names");
System.out.println("Names is " + names.getType() + " with " + names.isNames() + " and " + names.isAuthors() + " and value "
+ names.getText());
doc.recycle();
db.recycle();
}
public void run4(final Session session) throws NotesException {
Database db = session.getDatabase("", "events4.nsf");
NoteCollection cacheNC = db.createNoteCollection(false);
cacheNC.setSelectDocuments(true);
cacheNC.buildCollection();
cacheNC.recycle();
DocumentCollection cacheDc = db.getAllDocuments();
Document cacheDoc = cacheDc.getFirstDocument();
cacheDoc.recycle();
cacheDc.recycle();
db.recycle();
db = session.getDatabase("", "events4.nsf");
DocumentCollection dc = db.getAllDocuments();
Document doc = dc.getFirstDocument();
Document nextDoc = null;
int dcCount = dc.getCount();
int j = 0;
String[] dcUnids = new String[dcCount];
long dcStart = System.nanoTime();
while (doc != null) {
nextDoc = dc.getNextDocument(doc);
dcUnids[j++] = doc.getUniversalID();
doc.recycle();
doc = nextDoc;
}
System.out.println("DocumentCollection strategy got UNIDs for " + dcCount + " docs in " + (System.nanoTime() - dcStart) / 1000
+ "us");
dc.recycle();
db.recycle();
db = session.getDatabase("", "events4.nsf");
NoteCollection nc3 = db.createNoteCollection(false);
nc3.setSelectDocuments(true);
nc3.buildCollection();
int nc3Count = nc3.getCount();
String[] nc3Unids = new String[nc3Count];
int[] nids = nc3.getNoteIDs();
int k = 0;
long nc3Start = System.nanoTime();
for (int id : nids) {
nc3Unids[k++] = nc3.getUNID(Integer.toHexString(id));
}
System.out.println("NoteCollection strategy ints got UNIDs for " + nc3Count + " notes in " + (System.nanoTime() - nc3Start) / 1000
+ "us");
nc3.recycle();
db.recycle();
db = session.getDatabase("", "events4.nsf");
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.buildCollection();
int ncCount = nc.getCount();
String[] ncUnids = new String[ncCount];
String nid = nc.getFirstNoteID();
long ncStart = System.nanoTime();
for (int i = 0; i < ncCount; i++) {
ncUnids[i] = nc.getUNID(nid);
nid = nc.getNextNoteID(nid);
}
System.out.println("NoteCollection strategy first/next got UNIDs for " + ncCount + " notes in " + (System.nanoTime() - ncStart)
/ 1000 + "us");
nc.recycle();
db.recycle();
db = session.getDatabase("", "events4.nsf");
NoteCollection nc2 = db.createNoteCollection(false);
nc2.setSelectDocuments(true);
nc2.buildCollection();
int nc2Count = nc2.getCount();
String[] nc2Unids = new String[nc2Count];
nid = nc2.getFirstNoteID();
long nc2Start = System.nanoTime();
for (int i = 0; i < nc2Count; i++) {
Document nc2doc = db.getDocumentByID(nid);
nc2Unids[i] = nc2doc.getUniversalID();
nc2doc.recycle();
nid = nc2.getNextNoteID(nid);
}
System.out.println("NoteCollection strategy doc got UNIDs for " + nc2Count + " notes in " + (System.nanoTime() - nc2Start) / 1000
+ "us");
nc2.recycle();
db.recycle();
}
public void run3(final Session session) throws NotesException {
Database db = session.getDatabase("", "index.ntf");
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectIcon(true);
nc.setSelectAcl(true);
nc.selectAllDesignElements(true);
nc.buildCollection();
DxlExporter export = session.createDxlExporter();
export.setForceNoteFormat(true);
export.setRichTextOption(DxlExporter.DXLRICHTEXTOPTION_RAW);
String dxl = export.exportDxl(nc);
nc.recycle();
export.recycle();
db.recycle();
try {
PrintWriter out = new PrintWriter("c:\\data\\index.dxl");
out.println(dxl);
out.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void run() {
try {
System.out.println("Starting NotesRunner");
Session session = NotesFactory.createSession();
run4(session);
session.recycle();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println("FINI!");
}
}