14ae67516Stomee /*
24ae67516Stomee  * CDDL HEADER START
34ae67516Stomee  *
44ae67516Stomee  * The contents of this file are subject to the terms of the
54ae67516Stomee  * Common Development and Distribution License (the "License").
64ae67516Stomee  * You may not use this file except in compliance with the License.
74ae67516Stomee  *
84ae67516Stomee  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94ae67516Stomee  * or http://www.opensolaris.org/os/licensing.
104ae67516Stomee  * See the License for the specific language governing permissions
114ae67516Stomee  * and limitations under the License.
124ae67516Stomee  *
134ae67516Stomee  * When distributing Covered Code, include this CDDL HEADER in each
144ae67516Stomee  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154ae67516Stomee  * If applicable, add the following below this CDDL HEADER, with the
164ae67516Stomee  * fields enclosed by brackets "[]" replaced with your own identifying
174ae67516Stomee  * information: Portions Copyright [yyyy] [name of copyright owner]
184ae67516Stomee  *
194ae67516Stomee  * CDDL HEADER END
204ae67516Stomee  */
214ae67516Stomee 
224ae67516Stomee /*
234ae67516Stomee  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
244ae67516Stomee  * Use is subject to license terms.
254ae67516Stomee  */
264ae67516Stomee import java.util.*;
274ae67516Stomee import java.util.concurrent.atomic.*;
284ae67516Stomee import org.opensolaris.os.dtrace.*;
294ae67516Stomee 
304ae67516Stomee /**
314ae67516Stomee  * Regression test for 6521523 aggregation drops can hang the Java
324ae67516Stomee  * DTrace API.
334ae67516Stomee  */
344ae67516Stomee public class TestDrop {
354ae67516Stomee     static final String PROGRAM =
364ae67516Stomee 	    "fbt:genunix::entry { @[execname, pid] = count(); }";
374ae67516Stomee 
384ae67516Stomee     static AtomicLong consumerThreadID = new AtomicLong();
394ae67516Stomee     static AtomicLong getAggregateThreadID = new AtomicLong();
404ae67516Stomee     static AtomicBoolean done = new AtomicBoolean();
414ae67516Stomee     static int seconds;
424ae67516Stomee 
434ae67516Stomee     private static void
startTimer()444ae67516Stomee     startTimer()
454ae67516Stomee     {
464ae67516Stomee 	if (seconds <= 0) {
474ae67516Stomee 	    return;
484ae67516Stomee 	}
494ae67516Stomee 
504ae67516Stomee 	final Timer timer = new Timer();
514ae67516Stomee 	timer.schedule(new TimerTask() {
524ae67516Stomee 	    public void run() {
534ae67516Stomee 		done.set(true);
544ae67516Stomee 		timer.cancel();
554ae67516Stomee 	    }
564ae67516Stomee 	}, seconds * 1000L);
574ae67516Stomee     }
584ae67516Stomee 
594ae67516Stomee     private static void
sampleAggregate(Consumer consumer)604ae67516Stomee     sampleAggregate(Consumer consumer) throws DTraceException
614ae67516Stomee     {
624ae67516Stomee 	while (consumer.isRunning() && !done.get()) {
634ae67516Stomee 	    try {
64*4d0eb50eSRichard PALO 		Thread.sleep(50);
654ae67516Stomee 	    } catch (InterruptedException e) {
664ae67516Stomee 	    }
674ae67516Stomee 
684ae67516Stomee 	    consumer.getAggregate(Collections. <String> emptySet());
694ae67516Stomee 	}
704ae67516Stomee     }
714ae67516Stomee 
724ae67516Stomee     private static void
startAggregateThread(final Consumer consumer)734ae67516Stomee     startAggregateThread(final Consumer consumer)
744ae67516Stomee     {
754ae67516Stomee 	Runnable aggregateSampler = new Runnable() {
764ae67516Stomee 	    public void run() {
774ae67516Stomee 		Thread t = Thread.currentThread();
784ae67516Stomee 		getAggregateThreadID.set(t.getId());
794ae67516Stomee 		Throwable x = null;
804ae67516Stomee 		try {
814ae67516Stomee 		    sampleAggregate(consumer);
824ae67516Stomee 		} catch (Throwable e) {
834ae67516Stomee 		    x = e;
844ae67516Stomee 		}
854ae67516Stomee 
864ae67516Stomee 		if (Thread.holdsLock(LocalConsumer.class)) {
874ae67516Stomee 		    if (x != null) {
884ae67516Stomee 			x.printStackTrace();
894ae67516Stomee 		    }
904ae67516Stomee 		    System.out.println("Lock held");
914ae67516Stomee 		    System.exit(1);
924ae67516Stomee 		} else {
934ae67516Stomee 		    System.out.println("Lock released");
944ae67516Stomee 		    consumer.close(); // blocks if lock held
954ae67516Stomee 		}
964ae67516Stomee 	    }
974ae67516Stomee 	};
984ae67516Stomee 
994ae67516Stomee 	Thread t = new Thread(aggregateSampler, "Aggregate Sampler");
1004ae67516Stomee 	t.start();
1014ae67516Stomee     }
1024ae67516Stomee 
1034ae67516Stomee     static void
usage()1044ae67516Stomee     usage()
1054ae67516Stomee     {
1064ae67516Stomee 	System.err.println("usage: java TestDrop [ seconds ]");
1074ae67516Stomee 	System.exit(2);
1084ae67516Stomee     }
1094ae67516Stomee 
1104ae67516Stomee     public static void
main(String[] args)1114ae67516Stomee     main(String[] args)
1124ae67516Stomee     {
1134ae67516Stomee 	if (args.length == 1) {
1144ae67516Stomee 	    try {
1154ae67516Stomee 		seconds = Integer.parseInt(args[0]);
1164ae67516Stomee 	    } catch (NumberFormatException e) {
1174ae67516Stomee 		usage();
1184ae67516Stomee 	    }
1194ae67516Stomee 	} else if (args.length > 1) {
1204ae67516Stomee 	    usage();
1214ae67516Stomee 	}
1224ae67516Stomee 
1234ae67516Stomee 	final Consumer consumer = new LocalConsumer() {
1244ae67516Stomee 	    protected Thread createThread() {
1254ae67516Stomee 		Runnable worker = new Runnable() {
1264ae67516Stomee 		    public void run() {
1274ae67516Stomee 			Thread t = Thread.currentThread();
1284ae67516Stomee 			consumerThreadID.set(t.getId());
1294ae67516Stomee 			work();
1304ae67516Stomee 		    }
1314ae67516Stomee 		};
1324ae67516Stomee 		Thread t = new Thread(worker);
1334ae67516Stomee 		return t;
1344ae67516Stomee 	    }
1354ae67516Stomee 	};
1364ae67516Stomee 
1374ae67516Stomee 	consumer.addConsumerListener(new ConsumerAdapter() {
1384ae67516Stomee 	    public void consumerStarted(ConsumerEvent e) {
1394ae67516Stomee 		startAggregateThread(consumer);
1404ae67516Stomee 		startTimer();
1414ae67516Stomee 	    }
1424ae67516Stomee 	    public void dataDropped(DropEvent e) throws ConsumerException {
1434ae67516Stomee 		Thread t = Thread.currentThread();
1444ae67516Stomee 		if (t.getId() == getAggregateThreadID.get()) {
1454ae67516Stomee 		    Drop drop = e.getDrop();
1464ae67516Stomee 		    throw new ConsumerException(drop.getDefaultMessage(),
1474ae67516Stomee 			    drop);
1484ae67516Stomee 		}
1494ae67516Stomee 	    }
1504ae67516Stomee 	});
1514ae67516Stomee 
1524ae67516Stomee 	try {
1534ae67516Stomee 	    consumer.open();
1544ae67516Stomee 	    consumer.setOption(Option.aggsize, Option.kb(1));
1554ae67516Stomee 	    consumer.setOption(Option.aggrate, Option.millis(101));
1564ae67516Stomee 	    consumer.compile(PROGRAM);
1574ae67516Stomee 	    consumer.enable();
1584ae67516Stomee 	    consumer.go(new ExceptionHandler() {
1594ae67516Stomee 		public void handleException(Throwable e) {
1604ae67516Stomee 		    e.printStackTrace();
1614ae67516Stomee 		}
1624ae67516Stomee 	    });
1634ae67516Stomee 	} catch (DTraceException e) {
1644ae67516Stomee 	    e.printStackTrace();
1654ae67516Stomee 	}
1664ae67516Stomee     }
1674ae67516Stomee }
168