public void run()

in bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/TGTRefreshThread.java [106:239]


    public void run() {
        LOG.info("TGT refresh thread started.");
        while (true) {
            // renewal thread's main loop. if it exits from here, thread will exit.
            KerberosTicket tgt = getTGT();
            long now = Time.currentWallTime();
            long nextRefresh;
            Date nextRefreshDate;
            if (tgt == null) {
                nextRefresh = now + MIN_TIME_BEFORE_RELOGIN;
                nextRefreshDate = new Date(nextRefresh);
                LOG.warn("No TGT found: will try again at {}", nextRefreshDate);
            } else {
                nextRefresh = getRefreshTime(tgt);
                long expiry = tgt.getEndTime().getTime();
                Date expiryDate = new Date(expiry);
                if ((container.isUsingTicketCache()) && (tgt.getEndTime().equals(tgt.getRenewTill()))) {
                    Object[] logPayload = {expiryDate, container.getPrincipal(), container.getPrincipal()};
                    LOG.error("The TGT cannot be renewed beyond the next expiry date: {}."
                        + "This process will not be able to authenticate new SASL connections after that "
                        + "time (for example, it will not be authenticate a new connection with a Bookie "
                        + ").  Ask your system administrator to either increase the "
                        + "'renew until' time by doing : 'modprinc -maxrenewlife {}' within "
                        + "kadmin, or instead, to generate a keytab for {}. Because the TGT's "
                        + "expiry cannot be further extended by refreshing, exiting refresh thread now.", logPayload);
                    return;
                }
                // determine how long to sleep from looking at ticket's expiry.
                // We should not allow the ticket to expire, but we should take into consideration
                // MIN_TIME_BEFORE_RELOGIN. Will not sleep less than MIN_TIME_BEFORE_RELOGIN, unless doing so
                // would cause ticket expiration.
                if ((nextRefresh > expiry) || ((now + MIN_TIME_BEFORE_RELOGIN) > expiry)) {
                    // expiry is before next scheduled refresh).
                    nextRefresh = now;
                } else {
                    if (nextRefresh < (now + MIN_TIME_BEFORE_RELOGIN)) {
                        // next scheduled refresh is sooner than (now + MIN_TIME_BEFORE_LOGIN).
                        Date until = new Date(nextRefresh);
                        Date newuntil = new Date(now + MIN_TIME_BEFORE_RELOGIN);
                        Object[] logPayload = {until, newuntil, MIN_TIME_BEFORE_RELOGIN / 1000};
                        LOG.warn("TGT refresh thread time adjusted from : {} to : {} since "
                            + "the former is sooner than the minimum refresh interval ("
                            + "{} seconds) from now.", logPayload);
                    }
                    nextRefresh = Math.max(nextRefresh, now + MIN_TIME_BEFORE_RELOGIN);
                }
                nextRefreshDate = new Date(nextRefresh);
                if (nextRefresh > expiry) {
                    Object[] logPayload = {nextRefreshDate, expiryDate};
                    LOG.error("next refresh: {} is later than expiry {}." + " This may indicate a clock skew problem."
                        + "Check that this host and the KDC's " + "hosts' clocks are in sync. Exiting refresh thread.",
                        logPayload);
                    return;
                }
            }
            if (now == nextRefresh) {
                LOG.info("refreshing now because expiry is before next scheduled refresh time.");
            } else if (now < nextRefresh) {
                Date until = new Date(nextRefresh);
                LOG.info("TGT refresh sleeping until: {}", until);
                try {
                    Thread.sleep(nextRefresh - now);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    LOG.warn("TGT renewal thread has been interrupted and will exit.");
                    break;
                }
            } else {
                LOG.error("nextRefresh:{} is in the past: exiting refresh thread. Check"
                    + " clock sync between this host and KDC - (KDC's clock is likely ahead of this host)."
                    + " Manual intervention will be required for this client to successfully authenticate."
                    + " Exiting refresh thread.", nextRefreshDate);
                break;
            }
            if (container.isUsingTicketCache()) {
                String cmd = container.getConfiguration().getString(SaslConstants.KINIT_COMMAND,
                        SaslConstants.KINIT_COMMAND_DEFAULT);
                String kinitArgs = "-R";
                int retry = 1;
                while (retry >= 0) {
                    try {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("running ticket cache refresh command: {} {}", cmd, kinitArgs);
                        }
                        Shell.execCommand(cmd, kinitArgs);
                        break;
                    } catch (Exception e) {
                        if (retry > 0) {
                            --retry;
                            // sleep for 10 seconds
                            try {
                                Thread.sleep(10 * 1000);
                            } catch (InterruptedException ie) {
                                Thread.currentThread().interrupt();
                                LOG.error("Interrupted while renewing TGT, exiting Login thread");
                                return;
                            }
                        } else {
                            Object[] logPayload = {cmd, kinitArgs, e.toString(), e};
                            LOG.warn("Could not renew TGT due to problem running shell command: '{}"
                                + " {}'; exception was:{}. Exiting refresh thread.", logPayload);
                            return;
                        }
                    }
                }
            }
            try {
                int retry = 1;
                while (retry >= 0) {
                    try {
                        reLogin();
                        break;
                    } catch (LoginException le) {
                        if (retry > 0) {
                            --retry;
                            // sleep for 10 seconds.
                            try {
                                Thread.sleep(10 * 1000);
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                                LOG.error("Interrupted during login retry after LoginException:", le);
                                throw le;
                            }
                        } else {
                            LOG.error("Could not refresh TGT for principal: {}.", container.getPrincipal(), le);
                        }
                    }
                }
            } catch (LoginException le) {
                LOG.error("Failed to refresh TGT: refresh thread exiting now.", le);
                break;
            }
        }
    }