IdleResetSjavac.java revision 3356:b99518745035
1/*
2 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.sjavac.server;
27
28import com.sun.tools.javac.main.Main.Result;
29import com.sun.tools.sjavac.Log;
30
31import java.util.Timer;
32import java.util.TimerTask;
33
34/**
35 * An sjavac implementation that keeps track of idleness and shuts down the
36 * given Terminable upon idleness timeout.
37 *
38 * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last
39 * request is completed.
40 *
41 *  <p><b>This is NOT part of any supported API.
42 *  If you write code that depends on this, you do so at your own risk.
43 *  This code and its internal interfaces are subject to change or
44 *  deletion without notice.</b>
45 */
46public class IdleResetSjavac implements Sjavac {
47
48    private final Sjavac delegate;
49    private final Terminable toShutdown;
50    private final Timer idlenessTimer = new Timer();
51    private final long idleTimeout;
52    private int outstandingCalls = 0;
53
54    // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled
55    private TimerTask idlenessTimerTask;
56
57    public IdleResetSjavac(Sjavac delegate,
58                           Terminable toShutdown,
59                           long idleTimeout) {
60        this.delegate = delegate;
61        this.toShutdown = toShutdown;
62        this.idleTimeout = idleTimeout;
63        scheduleTimeout();
64    }
65
66    @Override
67    public Result compile(String[] args) {
68        startCall();
69        try {
70            return delegate.compile(args);
71        } finally {
72            endCall();
73        }
74    }
75
76    private synchronized void startCall() {
77        // Was there no outstanding calls before this call?
78        if (++outstandingCalls == 1) {
79            // Then the timer task must have been scheduled
80            if (idlenessTimerTask == null)
81                throw new IllegalStateException("Idle timeout already cancelled");
82            // Cancel timeout task
83            idlenessTimerTask.cancel();
84            idlenessTimerTask = null;
85        }
86    }
87
88    private synchronized void endCall() {
89        if (--outstandingCalls == 0) {
90            // No more outstanding calls. Schedule timeout.
91            scheduleTimeout();
92        }
93    }
94
95    private void scheduleTimeout() {
96        if (idlenessTimerTask != null)
97            throw new IllegalStateException("Idle timeout already scheduled");
98        idlenessTimerTask = new TimerTask() {
99            public void run() {
100                Log.setLogForCurrentThread(ServerMain.getErrorLog());
101                toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds.");
102            }
103        };
104        idlenessTimer.schedule(idlenessTimerTask, idleTimeout);
105    }
106
107    @Override
108    public void shutdown() {
109        idlenessTimer.cancel();
110        delegate.shutdown();
111    }
112
113}
114