1146773Ssam/* 2146773Ssam * CDDL HEADER START 3146773Ssam * 4146773Ssam * The contents of this file are subject to the terms of the 5146773Ssam * Common Development and Distribution License (the "License"). 6146773Ssam * You may not use this file except in compliance with the License. 7146773Ssam * 8146773Ssam * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9146773Ssam * or http://www.opensolaris.org/os/licensing. 10146773Ssam * See the License for the specific language governing permissions 11146773Ssam * and limitations under the License. 12146773Ssam * 13146773Ssam * When distributing Covered Code, include this CDDL HEADER in each 14146773Ssam * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15146773Ssam * If applicable, add the following below this CDDL HEADER, with the 16146773Ssam * fields enclosed by brackets "[]" replaced with your own identifying 17146773Ssam * information: Portions Copyright [yyyy] [name of copyright owner] 18146773Ssam * 19146773Ssam * CDDL HEADER END 20146773Ssam */ 21146773Ssam 22146773Ssam/* 23190207Srpaulo * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24146773Ssam * Use is subject to license terms. 25146773Ssam * 26146773Ssam * ident "%Z%%M% %I% %E% SMI" 27146773Ssam */ 28146773Ssamimport java.util.*; 29146773Ssamimport java.util.concurrent.atomic.*; 30146773Ssamimport org.opensolaris.os.dtrace.*; 31146773Ssam 32146773Ssam/** 33146773Ssam * Regression test for 6521523 aggregation drops can hang the Java 34146773Ssam * DTrace API. 35146773Ssam */ 36214478Srpaulopublic class TestDrop { 37146773Ssam static final String PROGRAM = 38146773Ssam "fbt:genunix::entry { @[execname, pid] = count(); }"; 39146773Ssam 40146773Ssam static AtomicLong consumerThreadID = new AtomicLong(); 41146773Ssam static AtomicLong getAggregateThreadID = new AtomicLong(); 42146773Ssam static AtomicBoolean done = new AtomicBoolean(); 43146773Ssam static int seconds; 44146773Ssam 45146773Ssam private static void 46146773Ssam startTimer() 47146773Ssam { 48146773Ssam if (seconds <= 0) { 49146773Ssam return; 50146773Ssam } 51146773Ssam 52146773Ssam final Timer timer = new Timer(); 53146773Ssam timer.schedule(new TimerTask() { 54146773Ssam public void run() { 55146773Ssam done.set(true); 56214478Srpaulo timer.cancel(); 57146773Ssam } 58146773Ssam }, seconds * 1000L); 59146773Ssam } 60146773Ssam 61146773Ssam private static void 62146773Ssam sampleAggregate(Consumer consumer) throws DTraceException 63146773Ssam { 64146773Ssam while (consumer.isRunning() && !done.get()) { 65146773Ssam try { 66146773Ssam Thread.currentThread().sleep(50); 67146773Ssam } catch (InterruptedException e) { 68146773Ssam } 69146773Ssam 70146773Ssam consumer.getAggregate(Collections. <String> emptySet()); 71146773Ssam } 72146773Ssam } 73146773Ssam 74146773Ssam private static void 75146773Ssam startAggregateThread(final Consumer consumer) 76146773Ssam { 77146773Ssam Runnable aggregateSampler = new Runnable() { 78146773Ssam public void run() { 79146773Ssam Thread t = Thread.currentThread(); 80146773Ssam getAggregateThreadID.set(t.getId()); 81146773Ssam Throwable x = null; 82146773Ssam try { 83146773Ssam sampleAggregate(consumer); 84146773Ssam } catch (Throwable e) { 85146773Ssam x = e; 86146773Ssam } 87146773Ssam 88146773Ssam if (Thread.holdsLock(LocalConsumer.class)) { 89146773Ssam if (x != null) { 90146773Ssam x.printStackTrace(); 91146773Ssam } 92146773Ssam System.out.println("Lock held"); 93146773Ssam System.exit(1); 94146773Ssam } else { 95146773Ssam System.out.println("Lock released"); 96146773Ssam consumer.close(); // blocks if lock held 97146773Ssam } 98146773Ssam } 99146773Ssam }; 100146773Ssam 101214478Srpaulo Thread t = new Thread(aggregateSampler, "Aggregate Sampler"); 102146773Ssam t.start(); 103146773Ssam } 104146773Ssam 105146773Ssam static void 106146773Ssam usage() 107146773Ssam { 108162017Ssam System.err.println("usage: java TestDrop [ seconds ]"); 109146773Ssam System.exit(2); 110235530Sdelphij } 111146773Ssam 112146773Ssam public static void 113146773Ssam main(String[] args) 114146773Ssam { 115162017Ssam if (args.length == 1) { 116146773Ssam try { 117146773Ssam seconds = Integer.parseInt(args[0]); 118146773Ssam } catch (NumberFormatException e) { 119146773Ssam usage(); 120146773Ssam } 121 } else if (args.length > 1) { 122 usage(); 123 } 124 125 final Consumer consumer = new LocalConsumer() { 126 protected Thread createThread() { 127 Runnable worker = new Runnable() { 128 public void run() { 129 Thread t = Thread.currentThread(); 130 consumerThreadID.set(t.getId()); 131 work(); 132 } 133 }; 134 Thread t = new Thread(worker); 135 return t; 136 } 137 }; 138 139 consumer.addConsumerListener(new ConsumerAdapter() { 140 public void consumerStarted(ConsumerEvent e) { 141 startAggregateThread(consumer); 142 startTimer(); 143 } 144 public void dataDropped(DropEvent e) throws ConsumerException { 145 Thread t = Thread.currentThread(); 146 if (t.getId() == getAggregateThreadID.get()) { 147 Drop drop = e.getDrop(); 148 throw new ConsumerException(drop.getDefaultMessage(), 149 drop); 150 } 151 } 152 }); 153 154 try { 155 consumer.open(); 156 consumer.setOption(Option.aggsize, Option.kb(1)); 157 consumer.setOption(Option.aggrate, Option.millis(101)); 158 consumer.compile(PROGRAM); 159 consumer.enable(); 160 consumer.go(new ExceptionHandler() { 161 public void handleException(Throwable e) { 162 e.printStackTrace(); 163 } 164 }); 165 } catch (DTraceException e) { 166 e.printStackTrace(); 167 } 168 } 169} 170