IdleResetSjavac.java revision 2682:bbd0164f668d
190075Sobrien/*
2117395Skan * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3169689Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
418334Speter *
590075Sobrien * This code is free software; you can redistribute it and/or modify it
618334Speter * under the terms of the GNU General Public License version 2 only, as
790075Sobrien * published by the Free Software Foundation.  Oracle designates this
890075Sobrien * particular file as subject to the "Classpath" exception as provided
990075Sobrien * by Oracle in the LICENSE file that accompanied this code.
1090075Sobrien *
1118334Speter * This code is distributed in the hope that it will be useful, but WITHOUT
1290075Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1390075Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1490075Sobrien * version 2 for more details (a copy is included in the LICENSE file that
1590075Sobrien * accompanied this code).
1618334Speter *
1718334Speter * You should have received a copy of the GNU General Public License version
1890075Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
19169689Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20169689Skan *
2118334Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22169689Skan * or visit www.oracle.com if you need additional information or have any
23169689Skan * questions.
24169689Skan */
25169689Skanpackage com.sun.tools.sjavac.server;
26169689Skan
2718334Speterimport java.io.File;
28169689Skanimport java.net.URI;
29169689Skanimport java.util.List;
3050397Sobrienimport java.util.Set;
31132718Skanimport java.util.Timer;
32132718Skanimport java.util.TimerTask;
3318334Speter
3418334Speter/**
3590075Sobrien * An sjavac implementation that keeps track of idleness and shuts down the
36169689Skan * given Terminable upon idleness timeout.
37169689Skan *
38169689Skan * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last
39169689Skan * request is completed.
40169689Skan *
4118334Speter *  <p><b>This is NOT part of any supported API.
4290075Sobrien *  If you write code that depends on this, you do so at your own risk.
4318334Speter *  This code and its internal interfaces are subject to change or
4490075Sobrien *  deletion without notice.</b>
4518334Speter */
4690075Sobrienpublic class IdleResetSjavac implements Sjavac {
4718334Speter
4890075Sobrien    private final Sjavac delegate;
4990075Sobrien    private final Terminable toShutdown;
5090075Sobrien    private final Timer idlenessTimer = new Timer();
5190075Sobrien    private final long idleTimeout;
5290075Sobrien    private int outstandingCalls = 0;
5390075Sobrien
5418334Speter    // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled
5518334Speter    private TimerTask idlenessTimerTask;
5618334Speter
5718334Speter    public IdleResetSjavac(Sjavac delegate,
5890075Sobrien                            Terminable toShutdown,
5918334Speter                            long idleTimeout) {
6018334Speter        this.delegate = delegate;
6118334Speter        this.toShutdown = toShutdown;
6218334Speter        this.idleTimeout = idleTimeout;
6318334Speter        scheduleTimeout();
6418334Speter    }
6518334Speter
6618334Speter    @Override
6718334Speter    public SysInfo getSysInfo() {
6890075Sobrien        startCall();
6918334Speter        try {
7018334Speter            return delegate.getSysInfo();
7118334Speter        } finally {
7218334Speter            endCall();
7318334Speter        }
7418334Speter    }
7518334Speter
7618334Speter    @Override
7718334Speter    public CompilationResult compile(String protocolId,
7818334Speter                                     String invocationId,
7918334Speter                                     String[] args,
8018334Speter                                     List<File> explicitSources,
8118334Speter                                     Set<URI> sourcesToCompile,
8290075Sobrien                                     Set<URI> visibleSources) {
8390075Sobrien        startCall();
8418334Speter        try {
8518334Speter            return delegate.compile(protocolId,
8618334Speter                                    invocationId,
8718334Speter                                    args,
8818334Speter                                    explicitSources,
8918334Speter                                    sourcesToCompile,
9018334Speter                                    visibleSources);
9150397Sobrien        } finally {
9250397Sobrien            endCall();
93117395Skan        }
9490075Sobrien    }
9518334Speter
9618334Speter    private synchronized void startCall() {
9718334Speter        // Was there no outstanding calls before this call?
9818334Speter        if (++outstandingCalls == 1) {
9918334Speter            // Then the timer task must have been scheduled
10018334Speter            if (idlenessTimerTask == null)
10118334Speter                throw new IllegalStateException("Idle timeout already cancelled");
10218334Speter            // Cancel timeout task
10318334Speter            idlenessTimerTask.cancel();
104169689Skan            idlenessTimerTask = null;
10590075Sobrien        }
10618334Speter    }
10718334Speter
10818334Speter    private synchronized void endCall() {
10918334Speter        if (--outstandingCalls == 0) {
110132718Skan            // No more outstanding calls. Schedule timeout.
111132718Skan            scheduleTimeout();
112169689Skan        }
113132718Skan    }
114132718Skan
115132718Skan    private void scheduleTimeout() {
116132718Skan        if (idlenessTimerTask != null)
117132718Skan            throw new IllegalStateException("Idle timeout already scheduled");
118132718Skan        idlenessTimerTask = new TimerTask() {
119132718Skan            public void run() {
120132718Skan                toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds.");
121132718Skan            }
122169689Skan        };
123169689Skan        idlenessTimer.schedule(idlenessTimerTask, idleTimeout);
124169689Skan    }
125169689Skan
12618334Speter    @Override
12718334Speter    public void shutdown() {
12890075Sobrien        idlenessTimer.cancel();
12990075Sobrien        delegate.shutdown();
130169689Skan    }
131169689Skan
132169689Skan    @Override
133169689Skan    public String serverSettings() {
13490075Sobrien        return delegate.serverSettings();
13518334Speter    }
136169689Skan}
13790075Sobrien