use of org.apache.sling.discovery.impl.cluster.voting.VotingHandler.VotingDetail in project sling by apache.
the class VotingHandlerTest method asyncVote.
private void asyncVote(final String debugInfo, final VotingHandler votingHandler, final List<VotingDetail> votingDetails, final Semaphore ready, final Semaphore go, final Semaphore done, final Set<Throwable> exceptions) throws Exception {
Runnable r = new Runnable() {
@Override
public void run() {
boolean released = false;
try {
logger.info("asyncVote[" + debugInfo + "] logging in...");
Map<VotingView, VotingDetail> result = null;
ResourceResolver rr = null;
int retries = 0;
while (true) {
try {
rr = factory.getServiceResourceResolver(null);
if (retries == 0) {
logger.info("asyncVote[" + debugInfo + "] marking ready...");
ready.release();
logger.info("asyncVote[" + debugInfo + "] waiting for go...");
go.acquire();
} else {
logger.info("asyncVote[" + debugInfo + "] not doing ready/go on retry.");
}
logger.info("asyncVote[" + debugInfo + "] analyzeVotings...");
result = votingHandler.analyzeVotings(rr);
break;
} catch (Exception e) {
logger.warn("asyncVote[" + debugInfo + "] Exception: " + e, e);
if (retries++ < 5) {
Thread.sleep(500);
logger.info("asyncVote[" + debugInfo + "] retrying after Exception...");
continue;
}
throw e;
} finally {
if (rr != null) {
rr.close();
}
}
}
logger.info("asyncVote[" + debugInfo + "] done, asserting results...");
assertNotNull(result);
votingDetails.addAll(result.values());
logger.info("asyncVote[" + debugInfo + "] marking done.");
done.release();
released = true;
} catch (RuntimeException re) {
// SLING-5244: make sure we're not silently running into an unchecked exception
logger.info("asyncVote[" + debugInfo + "] RuntimeException: " + re, re);
exceptions.add(re);
throw re;
} catch (Error er) {
// SLING-5244: make sure we're not silently running into an unchecked exception
logger.info("asyncVote[" + debugInfo + "] Error: " + er, er);
exceptions.add(er);
throw er;
} catch (Exception e) {
// SLING-5244: make sure we're not silently running into an unchecked exception
logger.info("asyncVote[" + debugInfo + "] Exception: " + e, e);
exceptions.add(e);
} finally {
// SLING-5244: make sure we're getting informed when this thread is done - be it normal or not
logger.info("asyncVote[" + debugInfo + "] finally [released=" + released + "]");
}
}
};
threadPool.execute(r);
}
use of org.apache.sling.discovery.impl.cluster.voting.VotingHandler.VotingDetail in project sling by apache.
the class VotingHandlerTest method doTestConcurrentVotes.
public void doTestConcurrentVotes(int votingsLoopCnt, int perVotingInnerLoopCnt, VotingHandler... votingHandler) throws Exception {
config.setHeartbeatInterval(999);
config.setHeartbeatTimeout(120);
for (VotingHandler handler : votingHandler) {
handler.activate(null);
}
int[] totals = new int[votingHandler.length];
List<Map<VotingDetail, Integer>> totalDetails = new LinkedList<Map<VotingDetail, Integer>>();
for (int i = 0; i < votingHandler.length; i++) {
HashMap<VotingDetail, Integer> d = new HashMap<VotingHandler.VotingDetail, Integer>();
totalDetails.add(d);
}
String[] slingIds = new String[votingHandler.length];
for (int k = 0; k < votingHandler.length; k++) {
slingIds[k] = (String) PrivateAccessor.getField(votingHandler[k], "slingId");
}
for (int i = 0; i < votingsLoopCnt; i++) {
// large voting loop
logger.info("testConcurrentVotes: loop i=" + i + ", votingHandler.cnt=" + votingHandler.length);
for (int k = 0; k < votingHandler.length; k++) {
heartbeat(slingIds[k]);
}
for (int k = 0; k < votingHandler.length; k++) {
String initiatorId = (String) PrivateAccessor.getField(votingHandler[k], "slingId");
VotingView voting = newVoting(initiatorId, slingIds);
assertNotNull(voting);
}
Semaphore ready = new Semaphore(0);
Semaphore go = new Semaphore(0);
Semaphore done = new Semaphore(0);
Set<Throwable> e = new ConcurrentHashSet<Throwable>();
boolean success = false;
List<List<VotingDetail>> detailList = new LinkedList<List<VotingDetail>>();
for (int k = 0; k < votingHandler.length; k++) {
detailList.add(new LinkedList<VotingHandler.VotingDetail>());
}
for (int j = 0; j < perVotingInnerLoopCnt; j++) {
logger.info("testConcurrentVotes: loop i=" + i + ", votingHandler.cnt=" + votingHandler.length + ", j=" + j);
for (int k = 0; k < votingHandler.length; k++) {
logger.info("testConcurrentVotes: <heartbeat for slingId,k=" + k + "> loop i=" + i + ", votingHandler.cnt=" + votingHandler.length + ", j=" + j);
heartbeat(slingIds[k]);
logger.info("testConcurrentVotes: <asyncVote for slingId,k=" + k + "> loop i=" + i + ", votingHandler.cnt=" + votingHandler.length + ", j=" + j);
asyncVote("k=" + k, votingHandler[k], detailList.get(k), ready, go, done, e);
}
assertTrue("threads were not ready within 30sec", ready.tryAcquire(votingHandler.length, 30, TimeUnit.SECONDS));
// both are now ready, so lets go
logger.info("testConcurrentVotes: GO loop i=" + i + ", votingHandler.cnt=" + votingHandler.length + ", j=" + j);
go.release(votingHandler.length);
assertTrue("threads were not done within 120sec", done.tryAcquire(votingHandler.length, 120, TimeUnit.SECONDS));
if (e.size() != 0) {
fail("Got exceptions: " + e.size() + ", first: " + e.iterator().next());
}
int promotionTotalCount = 0;
int noTotalCount = 0;
for (int k = 0; k < votingHandler.length; k++) {
int promotedCnt = count(detailList.get(k), VotingDetail.PROMOTED);
int noCnt = count(detailList.get(k), VotingDetail.VOTED_NO);
totals[k] += promotedCnt;
promotionTotalCount += promotedCnt;
noTotalCount += noCnt;
}
if (promotionTotalCount == 0) {
// should have 1 promotionTotalCount, if not, repeat
continue;
} else if (promotionTotalCount > 1) {
fail("more than 1 promoted views: " + promotionTotalCount);
} else if (noTotalCount < votingHandler.length - 1) {
// should have votingHandler.length-1 no votes, if not, repeat
continue;
} else {
// done
success = true;
break;
}
}
assertTrue("did not promote within " + perVotingInnerLoopCnt + " loops", success);
for (int k = 0; k < votingHandler.length; k++) {
add(detailList.get(k), totalDetails.get(k));
}
}
StringBuffer sb = new StringBuffer();
for (int k = 0; k < votingHandler.length; k++) {
sb.append(" - by slingId");
sb.append(k + 1);
sb.append(": ");
sb.append(totals[k]);
}
logger.info("testConcurrentVotes: promoted " + sb);
int totalPromotion = 0;
for (int k = 0; k < votingHandler.length; k++) {
for (Map.Entry<VotingDetail, Integer> anEntry : totalDetails.get(k).entrySet()) {
logger.info("testConcurrentVotes: slingId" + (k + 1) + ", detail=" + anEntry.getKey() + ", value=" + anEntry.getValue());
}
// SLING-5244 : cannot assume that we have '(votingHandler.length-1) * votingsLoopCnt'
// because: it can happen that a voting concludes within one j-loop above:
// that is the case when the instance that does not initiate the vote comes first, then
// the initiator - in that case the initiator finds an already completed vote - and it
// will then not do any no-votes ..
// so .. this check is a) not possible and b) just also not necessary, cos
// we already make sure that we at least get 'votingHandler.length-1' no votes in the j-loop
// and that is precise enough. so as unfortuante as it is, we can't make below assertion..
// unless we do more white-box-assertions into analyzeVotings, which is probably not helping
// test-stability either..
// Integer noVotes = totalDetails.get(k).get(VotingDetail.VOTED_NO);
// int expected = (votingHandler.length-1) * votingsLoopCnt;
// if (expected>0) {
// assertEquals(expected, (int)noVotes);
// }
final Map<VotingDetail, Integer> map = totalDetails.get(k);
final Integer i = map.get(VotingDetail.PROMOTED);
if (i != null) {
totalPromotion += i;
}
}
assertEquals(votingsLoopCnt, totalPromotion);
}
use of org.apache.sling.discovery.impl.cluster.voting.VotingHandler.VotingDetail in project sling by apache.
the class VotingHandlerTest method add.
private void add(List<VotingDetail> votingDetails, Map<VotingDetail, Integer> totals) {
for (VotingDetail d : votingDetails) {
Integer i = totals.get(d);
if (i == null) {
i = 0;
}
i++;
totals.put(d, i);
}
}
Aggregations