org.elasticsearch.qa.die_with_dignity.DieWithDignityIT.java Source code

Java tutorial

Introduction

Here is the source code for org.elasticsearch.qa.die_with_dignity.DieWithDignityIT.java

Source

/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.qa.die_with_dignity;

import org.apache.http.ConnectionClosedException;
import org.apache.lucene.util.Constants;
import org.elasticsearch.client.Request;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.hamcrest.Matcher;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.List;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.either;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.hasToString;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;

public class DieWithDignityIT extends ESRestTestCase {

    public void testDieWithDignity() throws Exception {
        // deleting the PID file prevents stopping the cluster from failing since it occurs if and only if the PID file exists
        final Path pidFile = PathUtils.get(System.getProperty("pidfile"));
        final List<String> pidFileLines = Files.readAllLines(pidFile);
        assertThat(pidFileLines, hasSize(1));
        final int pid = Integer.parseInt(pidFileLines.get(0));
        Files.delete(pidFile);
        IOException e = expectThrows(IOException.class,
                () -> client().performRequest(new Request("GET", "/_die_with_dignity")));
        Matcher<IOException> failureMatcher = instanceOf(ConnectionClosedException.class);
        if (Constants.WINDOWS) {
            /*
             * If the other side closes the connection while we're waiting to fill our buffer
             * we can get IOException with the message below. It seems to only come up on
             * Windows and it *feels* like it could be a ConnectionClosedException but
             * upstream does not consider this a bug:
             * https://issues.apache.org/jira/browse/HTTPASYNC-134
             *
             * So we catch it here and consider it "ok".
            */
            failureMatcher = either(failureMatcher).or(
                    hasToString(containsString("An existing connection was forcibly closed by the remote host")));
        }
        assertThat(e, failureMatcher);

        // the Elasticsearch process should die and disappear from the output of jps
        assertBusy(() -> {
            final String jpsPath = PathUtils.get(System.getProperty("runtime.java.home"), "bin/jps").toString();
            final Process process = new ProcessBuilder().command(jpsPath).start();
            assertThat(process.waitFor(), equalTo(0));
            try (InputStream is = process.getInputStream();
                    BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
                String line;
                while ((line = in.readLine()) != null) {
                    final int currentPid = Integer.parseInt(line.split("\\s+")[0]);
                    assertThat(line, pid, not(equalTo(currentPid)));
                }
            }
        });

        // parse the logs and ensure that Elasticsearch died with the expected cause
        final List<String> lines = Files.readAllLines(PathUtils.get(System.getProperty("log")));

        final Iterator<String> it = lines.iterator();

        boolean fatalErrorOnTheNetworkLayer = false;
        boolean fatalErrorInThreadExiting = false;

        while (it.hasNext() && (fatalErrorOnTheNetworkLayer == false || fatalErrorInThreadExiting == false)) {
            final String line = it.next();
            if (line.contains("fatal error on the network layer")) {
                fatalErrorOnTheNetworkLayer = true;
            } else if (line.matches(".*\\[ERROR\\]\\[o.e.b.ElasticsearchUncaughtExceptionHandler\\] \\[node-0\\]"
                    + " fatal error in thread \\[Thread-\\d+\\], exiting$")) {
                fatalErrorInThreadExiting = true;
                assertTrue(it.hasNext());
                assertThat(it.next(), equalTo("java.lang.OutOfMemoryError: die with dignity"));
            }
        }

        assertTrue(fatalErrorOnTheNetworkLayer);
        assertTrue(fatalErrorInThreadExiting);
    }

    @Override
    protected boolean preserveClusterUponCompletion() {
        // as the cluster is dead its state can not be wiped successfully so we have to bypass wiping the cluster
        return true;
    }

}