org.elassandra.SnapshotTests.java Source code

Java tutorial

Introduction

Here is the source code for org.elassandra.SnapshotTests.java

Source

/*
 * Copyright (c) 2017 Strapdata (http://www.strapdata.com)
 * Contains some code from Elasticsearch (http://www.elastic.co)
 * 
 * Licensed 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.elassandra;

import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.service.StorageService;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.junit.Test;

/**
 * Elassandra snapshot tests.
 * @author vroyer
 *
 */
//mvn test -Pdev -pl om.strapdata.elasticsearch:elasticsearch -Dtests.seed=622A2B0618CE4676 -Dtests.class=org.elassandra.SnapshotTests -Des.logger.level=ERROR -Dtests.assertion.disabled=false -Dtests.security.manager=false -Dtests.heap.size=1024m -Dtests.locale=ro-RO -Dtests.timezone=America/Toronto
public class SnapshotTests extends ESSingleNodeTestCase {

    // SSTable snapshotDir = data/data/<keyspace>/<table>/snapshots/<snapshot_name>/
    public void restoreSSTable(String dataLocation, String keyspaceName, String cfName, UUID cfId,
            String snapshotName) throws IOException {
        String id = cfId.toString().replaceAll("\\-", "");
        Path sourceDir = PathUtils
                .get(dataLocation + "/" + keyspaceName + "/" + cfName + "-" + id + "/snapshots/" + snapshotName);
        Path targetDir = PathUtils.get(dataLocation + "/" + keyspaceName + "/" + cfName + "-" + id + "/");
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir, "{*.db}")) {
            for (Path dbFile : stream)
                Files.delete(dbFile);
        }
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
            for (Path f : stream)
                Files.copy(f, PathUtils.get(targetDir.toString(), f.getFileName().toString()),
                        StandardCopyOption.COPY_ATTRIBUTES);
        }
    }

    // lucene snapshotDir = data/<cluster_name>/nodes/0/snapshots/<index_name>/<snapshot_name>
    public void restoreLucenceFiles(String dataLocation, String indexName, String snapshot) throws IOException {
        Path sourceDir = PathUtils.get(dataLocation + "/" + DatabaseDescriptor.getClusterName()
                + "/nodes/0/snapshots/" + indexName + "/" + snapshot + "/");
        Path targetDir = PathUtils.get(dataLocation + "/" + DatabaseDescriptor.getClusterName()
                + "/nodes/0/indices/" + indexName + "/0/index/");
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(targetDir, "{_*.*,segments*}")) {
            for (Path segmentFile : stream)
                Files.delete(segmentFile);
        }
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir, "{_*.*,segments*}")) {
            for (Path f : stream)
                Files.copy(f, PathUtils.get(targetDir.toString(), f.getFileName().toString()),
                        StandardCopyOption.COPY_ATTRIBUTES);
        }
    }

    @Test
    public void basicSnapshotTest() throws Exception {
        process(ConsistencyLevel.ONE,
                String.format(Locale.ROOT,
                        "CREATE KEYSPACE ks WITH replication = {'class': 'NetworkTopologyStrategy', '%s': '1'}",
                        DatabaseDescriptor.getLocalDataCenter()));
        process(ConsistencyLevel.ONE, "CREATE TABLE ks.t1 ( name text, age int, primary key (name))");

        XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("t1")
                .field("discover", ".*").endObject().endObject();
        createIndex("ks", Settings.builder().put("index.snapshot_with_sstable", true).build(), "t1", mapping);
        ensureGreen("ks");

        for (long i = 0; i < 1000; i++)
            process(ConsistencyLevel.ONE,
                    String.format(Locale.ROOT, "INSERT INTO ks.t1 (name, age) VALUES ('name%d', %d)", i, i));
        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(1000L));

        // take snaphot
        StorageService.instance.takeSnapshot("snap1", "ks");

        // drop all
        process(ConsistencyLevel.ONE, "TRUNCATE ks.t1");
        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(0L));

        // close index and restore SSTable+Lucene files
        assertAcked(client().admin().indices().prepareClose("ks").get());

        String dataLocation = DatabaseDescriptor.getAllDataFileLocations()[0];
        restoreSSTable(dataLocation, "ks", "t1", Schema.instance.getCFMetaData("ks", "t1").cfId, "snap1");
        restoreLucenceFiles(dataLocation, "ks", "snap1");

        // refresh SSTables and repopen index
        StorageService.instance.loadNewSSTables("ks", "t1");
        assertAcked(client().admin().indices().prepareOpen("ks").get());
        ensureGreen("ks");

        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(1000L));
    }

    @Test
    //mvn test -Pdev -pl com.strapdata.elasticsearch:elasticsearch -Dtests.seed=622A2B0618CE4676 -Dtests.class=org.elassandra.SnapshotTests -Dtests.method="onDropSnapshotTest" -Des.logger.level=ERROR -Dtests.assertion.disabled=false -Dtests.security.manager=false -Dtests.heap.size=1024m -Dtests.locale=ro-RO -Dtests.timezone=America/Toronto
    public void onDropSnapshotTest() throws Exception {
        process(ConsistencyLevel.ONE,
                String.format(Locale.ROOT,
                        "CREATE KEYSPACE ks WITH replication = {'class': 'NetworkTopologyStrategy', '%s': '1'}",
                        DatabaseDescriptor.getLocalDataCenter()));
        process(ConsistencyLevel.ONE, "CREATE TABLE ks.t1 ( name text, age int, primary key (name))");

        XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("t1")
                .field("discover", ".*").endObject().endObject();
        createIndex("ks", Settings.builder().put("index.snapshot_with_sstable", true).build(), "t1", mapping);
        ensureGreen("ks");

        for (long i = 0; i < 1000; i++)
            process(ConsistencyLevel.ONE,
                    String.format(Locale.ROOT, "INSERT INTO ks.t1 (name, age) VALUES ('name%d', %d)", i, i));
        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(1000L));

        UUID cfId = Schema.instance.getCFMetaData("ks", "t1").cfId;
        String id = cfId.toString().replaceAll("\\-", "");

        if (!DatabaseDescriptor.isAutoSnapshot())
            StorageService.instance.takeTableSnapshot("ks", "t1", Long.toString(new Date().getTime()));

        // drop index + keyspace (C* snapshot before drop => flush before snapshot => ES flush before delete)
        assertAcked(client().admin().indices().prepareDelete("ks").get());

        // recreate schema and mapping
        process(ConsistencyLevel.ONE,
                String.format(Locale.ROOT,
                        "CREATE KEYSPACE ks WITH replication = {'class': 'NetworkTopologyStrategy', '%s': '1'}",
                        DatabaseDescriptor.getLocalDataCenter()));
        process(ConsistencyLevel.ONE, "CREATE TABLE ks.t1 ( name text, age int, primary key (name))");
        createIndex("ks", Settings.builder().put("index.snapshot_with_sstable", true).build(), "t1", mapping);
        ensureGreen("ks");
        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(0L));

        // close index and restore SSTable+Lucene files
        assertAcked(client().admin().indices().prepareClose("ks").get());

        String dataLocation = DatabaseDescriptor.getAllDataFileLocations()[0];
        DirectoryStream<Path> stream = Files
                .newDirectoryStream(PathUtils.get(dataLocation + "/ks/t1-" + id + "/snapshots/"));
        Path snapshot = stream.iterator().next();
        String snap = snapshot.getFileName().toString();
        System.out.println("snapshot name=" + snap);
        stream.close();

        restoreSSTable(dataLocation, "ks", "t1", cfId, snap);
        restoreLucenceFiles(dataLocation, "ks", snap);

        // refresh SSTables and repopen index
        StorageService.instance.loadNewSSTables("ks", "t1");
        assertAcked(client().admin().indices().prepareOpen("ks").get());
        ensureGreen("ks");

        assertThat(
                client().prepareSearch().setIndices("ks").setTypes("t1")
                        .setQuery(QueryBuilders.queryStringQuery("*:*")).get().getHits().getTotalHits(),
                equalTo(1000L));
    }
}