check that job is not aborted before requsting another lock
pass shrinkTimer parameter
collect some stats
next free slot is an inaccessible field in each RecordType
automatically sort fields by size and align items in RecordType
no more debug fields in RecordType
skip checks for fields that do not have an intializer in RecordType
fix RecordManager serialization
diff --git a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/Generator.java b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/Generator.java
index 3925e02..4279304 100644
--- a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/Generator.java
+++ b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/Generator.java
@@ -102,10 +102,12 @@
} else if (line.contains("@METHODS@")) {
for (int i = 0; i < resource.size(); ++i) {
final Field field = resource.fields.get(i);
- field.appendMemoryManagerGetMethod(sb, indent, 1);
- sb.append('\n');
- field.appendMemoryManagerSetMethod(sb, indent, 1);
- sb.append('\n');
+ if (field.accessible) {
+ field.appendMemoryManagerGetMethod(sb, indent, 1);
+ sb.append('\n');
+ field.appendMemoryManagerSetMethod(sb, indent, 1);
+ sb.append('\n');
+ }
}
} else if (line.contains("@INIT_SLOT@")) {
for (int i = 0; i < resource.size(); ++i) {
@@ -152,10 +154,12 @@
if (line.contains("@METHODS@")) {
for (int i = 0; i < resource.size(); ++i) {
final Field field = resource.fields.get(i);
- field.appendArenaManagerGetMethod(sb, indent, 1);
- sb.append('\n');
- field.appendArenaManagerSetMethod(sb, indent, 1);
- sb.append('\n');
+ if (field.accessible) {
+ field.appendArenaManagerGetMethod(sb, indent, 1);
+ sb.append('\n');
+ field.appendArenaManagerSetMethod(sb, indent, 1);
+ sb.append('\n');
+ }
}
} else {
sb.append(line).append('\n');
diff --git a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordManagerGeneratorMojo.java b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordManagerGeneratorMojo.java
index 577d871..8b6b581 100644
--- a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordManagerGeneratorMojo.java
+++ b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordManagerGeneratorMojo.java
@@ -85,9 +85,9 @@
resource.addField("max mode", RecordType.Type.INT, "LockMode.NL");
resource.addField("dataset id", RecordType.Type.INT, null);
resource.addField("pk hash val", RecordType.Type.INT, null);
- resource.addField("alloc id", RecordType.Type.SHORT, null, true);
+ resource.addField("alloc id", RecordType.Type.SHORT, null);
- typeMap.put(resource.name, resource);
+ resource.addToMap(typeMap);
RecordType request = new RecordType("Request");
request.addField("resource id", RecordType.Type.GLOBAL, null);
@@ -96,18 +96,18 @@
request.addField("next job request", RecordType.Type.GLOBAL, null);
request.addField("next request", RecordType.Type.GLOBAL, null);
request.addField("lock mode", RecordType.Type.INT, null);
- request.addField("alloc id", RecordType.Type.SHORT, null, true);
+ request.addField("alloc id", RecordType.Type.SHORT, null);
- typeMap.put(request.name, request);
+ request.addToMap(typeMap);
RecordType job = new RecordType("Job");
job.addField("last holder", RecordType.Type.GLOBAL, "-1");
job.addField("last waiter", RecordType.Type.GLOBAL, "-1");
job.addField("last upgrader", RecordType.Type.GLOBAL, "-1");
job.addField("job id", RecordType.Type.INT, null);
- job.addField("alloc id", RecordType.Type.SHORT, null, true);
+ job.addField("alloc id", RecordType.Type.SHORT, null);
- typeMap.put(job.name, job);
+ job.addToMap(typeMap);
}
public void execute() throws MojoExecutionException, MojoFailureException {
diff --git a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordType.java b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordType.java
index 6a0d540..741311b 100644
--- a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordType.java
+++ b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/java/edu/uci/ics/asterix/recordmanagergenerator/RecordType.java
@@ -15,7 +15,11 @@
package edu.uci.ics.asterix.recordmanagergenerator;
+import java.security.AlgorithmConstraints;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
public class RecordType {
@@ -27,19 +31,19 @@
}
static class Field {
-
+
String name;
Type type;
String initial;
int offset;
- boolean debugField;
+ boolean accessible = true;
- Field(String name, Type type, String initial, int offset, boolean debugField) {
+ Field(String name, Type type, String initial, int offset, boolean accessible) {
this.name = name;
this.type = type;
this.initial = initial;
this.offset = offset;
- this.debugField = debugField;
+ this.accessible = accessible;
}
String methodName(String prefix) {
@@ -105,7 +109,7 @@
.append(' ')
.append(methodName("get"))
.append("(long slotNum) {\n");
- if (! debugField) {
+ if (initial != null) {
sb = indent(sb, indent, level + 1);
sb.append("if (TRACK_ALLOC) checkSlot(slotNum);\n");
}
@@ -129,7 +133,7 @@
.append("(long slotNum, ")
.append(javaType(type))
.append(" value) {\n");
- if (! debugField) {
+ if (initial != null) {
sb = indent(sb, indent, level + 1);
sb.append("if (TRACK_ALLOC) checkSlot(slotNum);\n");
}
@@ -163,7 +167,7 @@
}
StringBuilder appendChecks(StringBuilder sb, String indent, int level) {
- if (debugField) {
+ if (initial == null) {
return sb;
}
sb = indent(sb, indent, level);
@@ -204,6 +208,7 @@
String name;
ArrayList<Field> fields;
int totalSize;
+ boolean modifiable = true;
static StringBuilder indent(StringBuilder sb, String indent, int level) {
for (int i = 0; i < level; ++i) {
@@ -212,21 +217,51 @@
return sb;
}
- RecordType(String name) {
+ public RecordType(String name) {
this.name = name;
fields = new ArrayList<Field>();
- totalSize = 0;
+ addField("next free slot", Type.INT, "-1", false);
}
- void addField(String name, Type type, String initial) {
- addField(name, type, initial, false);
+ public void addToMap(Map<String, RecordType> map) {
+ modifiable = false;
+ calcOffsetsAndSize();
+ map.put(name, this);
+ }
+
+ public void addField(String name, Type type, String initial) {
+ addField(name, type, initial, true);
+ }
+
+ private void addField(String name, Type type, String initial, boolean accessible) {
+ if (! modifiable) {
+ throw new IllegalStateException("cannot modify type anmore");
+ }
+ fields.add(new Field(name, type, initial, -1, accessible));
}
- void addField(String name, Type type, String initial, boolean debugField) {
- fields.add(new Field(name, type, initial, totalSize, debugField));
- totalSize += size(type);
+ private void calcOffsetsAndSize() {
+ Collections.sort(fields, new Comparator<Field>() {
+ public int compare(Field left, Field right) {
+ return size(right.type) - size(left.type);
+ }
+ });
+ // sort fields by size and align the items
+ totalSize = 0;
+ int alignment = 0;
+ for (int i = 0; i < fields.size(); ++i) {
+ final Field field = fields.get(i);
+ assert field.offset == -1;
+ field.offset = totalSize;
+ final int size = size(field.type);
+ totalSize += size;
+ if (size > alignment) alignment = size;
+ }
+ if (totalSize % alignment != 0) {
+ totalSize = ((totalSize / alignment) + 1) * alignment;
+ }
}
-
+
int size() {
return fields.size();
}
@@ -310,7 +345,8 @@
sb.append("public static int ")
.append(field.offsetName())
.append(" = ")
- .append(field.offset).append(";\n");
+ .append(field.offset).append("; // size: ")
+ .append(size(field.type)).append("\n");
}
return sb;
}
@@ -342,6 +378,8 @@
sb.append("sb = ")
.append(appender(field.type))
.append("(sb, value);\n");
+ sb = indent(sb, indent, level + 1);
+ sb.append("sb.append(\" | \");\n");
sb = indent(sb, indent, level);
sb.append("}\n");
sb = indent(sb, indent, level);
diff --git a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/ArenaManager.java b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/ArenaManager.java
index 5d0a2d8..58f8972 100644
--- a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/ArenaManager.java
+++ b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/ArenaManager.java
@@ -25,11 +25,13 @@
public static final boolean TRACK_ALLOC = @DEBUG@;
private final int noArenas;
+ private final long txnShrinkTimer;
private ArrayList<@E@RecordManager> arenas;
private volatile int nextArena;
private ThreadLocal<LocalManager> local;
- public @E@ArenaManager() {
+ public @E@ArenaManager(long txnShrinkTimer) {
+ this.txnShrinkTimer = txnShrinkTimer;
noArenas = Runtime.getRuntime().availableProcessors() * 2;
arenas = new ArrayList<@E@RecordManager>(noArenas);
nextArena = 0;
@@ -68,7 +70,7 @@
public synchronized LocalManager getNext() {
if (nextArena >= arenas.size()) {
- arenas.add(new @E@RecordManager());
+ arenas.add(new @E@RecordManager(txnShrinkTimer));
}
@E@RecordManager mgr = arenas.get(nextArena);
LocalManager res = new LocalManager();
@@ -125,4 +127,13 @@
public String toString() {
return append(new StringBuilder()).toString();
}
+
+ public Stats addTo(Stats s) {
+ final int size = arenas.size();
+ s.arenas += size;
+ for (int i = 0; i < size; ++i) {
+ arenas.get(i).addTo(s);
+ }
+ return s;
+ }
}
diff --git a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/RecordManager.java b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/RecordManager.java
index e5ce5c1..01049d3 100644
--- a/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/RecordManager.java
+++ b/asterix-maven-plugins/record-manager-generator-maven-plugin/src/main/resources/RecordManager.java
@@ -23,23 +23,23 @@
public class @E@RecordManager {
- public static final int SHRINK_TIMER_THRESHOLD = 120000; //2min
public static final boolean TRACK_ALLOC = @DEBUG@;
static final int NO_SLOTS = 10;
- static final int NEXT_FREE_SLOT_OFFSET = 0;
@CONSTS@
+ private final long txnShrinkTimer;
+ private long shrinkTimer;
private ArrayList<Buffer> buffers;
private int current;
private int occupiedSlots;
- private long shrinkTimer;
private boolean isShrinkTimerOn;
int allocCounter;
- public @E@RecordManager() {
+ public @E@RecordManager(long txnShrinkTimer) {
+ this.txnShrinkTimer = txnShrinkTimer;
buffers = new ArrayList<Buffer>();
buffers.add(new Buffer());
current = 0;
@@ -106,7 +106,7 @@
if (size > 1 && size * NO_SLOTS / usedSlots >= 3) {
if (isShrinkTimerOn) {
- if (System.currentTimeMillis() - shrinkTimer >= SHRINK_TIMER_THRESHOLD) {
+ if (System.currentTimeMillis() - shrinkTimer >= txnShrinkTimer) {
isShrinkTimerOn = false;
return true;
}
@@ -190,6 +190,17 @@
return append(new StringBuilder()).toString();
}
+ public Stats addTo(Stats s) {
+ final int size = buffers.size();
+ s.buffers += size;
+ s.slots += size * NO_SLOTS;
+ s.size += size * NO_SLOTS * ITEM_SIZE;
+ for (int i = 0; i < size; ++i) {
+ buffers.get(i).addTo(s);
+ }
+ return s;
+ }
+
static class Buffer {
private ByteBuffer bb;
private int freeSlotNum;
@@ -254,11 +265,11 @@
}
public int getNextFreeSlot(int slotNum) {
- return bb.getInt(slotNum * ITEM_SIZE + NEXT_FREE_SLOT_OFFSET);
+ return bb.getInt(slotNum * ITEM_SIZE + NEXT_FREE_SLOT_OFF);
}
public void setNextFreeSlot(int slotNum, int nextFreeSlot) {
- bb.putInt(slotNum * ITEM_SIZE + NEXT_FREE_SLOT_OFFSET, nextFreeSlot);
+ bb.putInt(slotNum * ITEM_SIZE + NEXT_FREE_SLOT_OFF, nextFreeSlot);
}
StringBuilder append(StringBuilder sb) {
@@ -275,6 +286,12 @@
return append(new StringBuilder()).toString();
}
+ public void addTo(Stats s) {
+ if (isInitialized()) {
+ s.items += occupiedSlots;
+ }
+ }
+
private void checkSlot(int slotNum) {
if (! TRACK_ALLOC) {
return;
diff --git a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/ConcurrentLockManager.java b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/ConcurrentLockManager.java
index 18997e5..124b406 100644
--- a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/ConcurrentLockManager.java
+++ b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/ConcurrentLockManager.java
@@ -28,7 +28,6 @@
import edu.uci.ics.asterix.common.transactions.ILockManager;
import edu.uci.ics.asterix.common.transactions.ITransactionContext;
import edu.uci.ics.asterix.common.transactions.ITransactionManager;
-import edu.uci.ics.asterix.common.transactions.JobId;
import edu.uci.ics.asterix.transaction.management.service.transaction.TransactionManagementConstants.LockManagerConstants.LockMode;
import edu.uci.ics.asterix.transaction.management.service.transaction.TransactionSubsystem;
import edu.uci.ics.hyracks.api.lifecycle.ILifeCycleComponent;
@@ -77,9 +76,9 @@
final int lockManagerShrinkTimer = txnSubsystem.getTransactionProperties()
.getLockManagerShrinkTimer();
- resArenaMgr = new ResourceArenaManager();
- reqArenaMgr = new RequestArenaManager();
- jobArenaMgr = new JobArenaManager();
+ resArenaMgr = new ResourceArenaManager(lockManagerShrinkTimer);
+ reqArenaMgr = new RequestArenaManager(lockManagerShrinkTimer);
+ jobArenaMgr = new JobArenaManager(lockManagerShrinkTimer);
jobIdSlotMap = new ConcurrentHashMap<>();
}
@@ -107,6 +106,8 @@
group.getLatch();
try {
+ validateJob(txnContext);
+
// 1) Find the resource in the hash table
long resSlot = getResourceSlot(group, dsId, entityHashValue);
// 2) create a request entry
@@ -211,6 +212,8 @@
group.getLatch();
try {
+ validateJob(txnContext);
+
// 1) Find the resource in the hash table
long resSlot = getResourceSlot(group, dsId, entityHashValue);
// 2) create a request entry
@@ -338,6 +341,10 @@
holder = jobArenaMgr.getLastHolder(jobSlot);
}
jobArenaMgr.deallocate(jobSlot);
+
+ //System.out.println("jobArenaMgr " + jobArenaMgr.addTo(new Stats()).toString());
+ //System.out.println("resArenaMgr " + resArenaMgr.addTo(new Stats()).toString());
+ //System.out.println("reqArenaMgr " + reqArenaMgr.addTo(new Stats()).toString());
}
private long getJobSlot(int jobId) {
@@ -441,8 +448,8 @@
resArenaMgr.setLastHolder(resource, request);
synchronized (jobArenaMgr) {
- lastHolder = jobArenaMgr.getLastHolder(job);
- insertIntoJobQueue(request, lastHolder);
+ long lastJobHolder = jobArenaMgr.getLastHolder(job);
+ insertIntoJobQueue(request, lastJobHolder);
jobArenaMgr.setLastHolder(job, request);
}
}
@@ -796,7 +803,7 @@
@Override
public String prettyPrint() throws ACIDException {
StringBuilder s = new StringBuilder("\n########### LockManager Status #############\n");
- return s + "\n";
+ return append(s).toString() + "\n";
}
@Override
diff --git a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/Stats.java b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/Stats.java
new file mode 100644
index 0000000..ff2c92a
--- /dev/null
+++ b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/locking/Stats.java
@@ -0,0 +1,19 @@
+package edu.uci.ics.asterix.transaction.management.service.locking;
+
+public class Stats {
+ int arenas = 0;
+ int buffers = 0;
+ int slots = 0;
+ int items = 0;
+ int size = 0;
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{ arenas : ").append(arenas);
+ sb.append(", buffers : ").append(buffers);
+ sb.append(", slots : ").append(slots);
+ sb.append(", items : ").append(items);
+ sb.append(", size : ").append(size).append(" }");
+ return sb.toString();
+ }
+}