org.apache.cassandra.service.ActiveRepairService Java Examples

The following examples show how to use org.apache.cassandra.service.ActiveRepairService. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: JmxProxyImpl.java    From cassandra-reaper with Apache License 2.0 6 votes vote down vote up
/**
 * Handles notifications from the old repair API (forceRepairAsync)
 */
private void processOldApiNotification(Notification notification) {
  try {
    int[] data = (int[]) notification.getUserData();
    // get the repair sequence number
    int repairNo = data[0];
    // get the repair status
    ActiveRepairService.Status status = ActiveRepairService.Status.values()[data[1]];
    // this is some text message like "Starting repair...", "Finished repair...", etc.
    String message = notification.getMessage();
    // let the handler process the even
    if (repairStatusHandlers.containsKey(repairNo)) {
      LOG.debug("Handling notification {} with repair handler {}", notification, repairStatusHandlers.get(repairNo));

      repairStatusHandlers
          .get(repairNo)
          .handle(repairNo, Optional.of(status), Optional.empty(), message, this);
    }
  } catch (RuntimeException e) {
    LOG.error("Error while processing JMX notification", e);
  }
}
 
Example #2
Source File: SSTableExportTest.java    From stratio-cassandra with Apache License 2.0 6 votes vote down vote up
@Test
public void testAsciiKeyValidator() throws IOException, ParseException
{
    File tempSS = tempSSTableFile("Keyspace1", "AsciiKeys");
    ColumnFamily cfamily = ArrayBackedSortedColumns.factory.create("Keyspace1", "AsciiKeys");
    SSTableWriter writer = new SSTableWriter(tempSS.getPath(), 2, ActiveRepairService.UNREPAIRED_SSTABLE);

    // Add a row
    cfamily.addColumn(column("column", "value", 1L));
    writer.append(Util.dk("key", AsciiType.instance), cfamily);

    SSTableReader reader = writer.closeAndOpenReader();
    // Export to JSON and verify
    File tempJson = File.createTempFile("CFWithAsciiKeys", ".json");
    SSTableExport.export(reader,
                         new PrintStream(tempJson.getPath()),
                         new String[0],
                         CFMetaData.sparseCFMetaData("Keyspace1", "AsciiKeys", BytesType.instance));

    JSONArray json = (JSONArray)JSONValue.parseWithException(new FileReader(tempJson));
    assertEquals(1, json.size());

    JSONObject row = (JSONObject)json.get(0);
    // check row key
    assertEquals("key", row.get("key"));
}
 
Example #3
Source File: StreamingRepairTask.java    From stratio-cassandra with Apache License 2.0 6 votes vote down vote up
private void initiateStreaming()
{
    long repairedAt = ActiveRepairService.UNREPAIRED_SSTABLE;
    InetAddress dest = request.dst;
    InetAddress preferred = SystemKeyspace.getPreferredIP(dest);
    if (desc.parentSessionId != null && ActiveRepairService.instance.getParentRepairSession(desc.parentSessionId) != null)
        repairedAt = ActiveRepairService.instance.getParentRepairSession(desc.parentSessionId).repairedAt;
    logger.info(String.format("[streaming task #%s] Performing streaming repair of %d ranges with %s", desc.sessionId, request.ranges.size(), request.dst));
    StreamResultFuture op = new StreamPlan("Repair", repairedAt, 1)
                                .flushBeforeTransfer(true)
                                // request ranges from the remote node
                                .requestRanges(dest, preferred, desc.keyspace, request.ranges, desc.columnFamily)
                                // send ranges to the remote node
                                .transferRanges(dest, preferred, desc.keyspace, request.ranges, desc.columnFamily)
                                .execute();
    op.addEventListener(this);
}
 
Example #4
Source File: MetadataCollector.java    From stratio-cassandra with Apache License 2.0 6 votes vote down vote up
public static StatsMetadata defaultStatsMetadata()
{
    return new StatsMetadata(defaultRowSizeHistogram(),
                             defaultColumnCountHistogram(),
                             ReplayPosition.NONE,
                             Long.MIN_VALUE,
                             Long.MAX_VALUE,
                             Integer.MAX_VALUE,
                             NO_COMPRESSION_RATIO,
                             defaultTombstoneDropTimeHistogram(),
                             0,
                             Collections.<ByteBuffer>emptyList(),
                             Collections.<ByteBuffer>emptyList(),
                             true,
                             ActiveRepairService.UNREPAIRED_SSTABLE);
}
 
Example #5
Source File: StreamSession.java    From stratio-cassandra with Apache License 2.0 6 votes vote down vote up
/**
 * Set up transfer for specific keyspace/ranges/CFs
 *
 * Used in repair - a streamed sstable in repair will be marked with the given repairedAt time
 *
 * @param keyspace Transfer keyspace
 * @param ranges Transfer ranges
 * @param columnFamilies Transfer ColumnFamilies
 * @param flushTables flush tables?
 * @param repairedAt the time the repair started.
 */
public void addTransferRanges(String keyspace, Collection<Range<Token>> ranges, Collection<String> columnFamilies, boolean flushTables, long repairedAt)
{
    Collection<ColumnFamilyStore> stores = getColumnFamilyStores(keyspace, columnFamilies);
    if (flushTables)
        flushSSTables(stores);

    List<Range<Token>> normalizedRanges = Range.normalize(ranges);
    List<SSTableStreamingSections> sections = getSSTableSectionsForRanges(normalizedRanges, stores, repairedAt, repairedAt != ActiveRepairService.UNREPAIRED_SSTABLE);
    try
    {
        addTransferFiles(sections);
    }
    finally
    {
        for (SSTableStreamingSections release : sections)
            release.ref.release();
    }
}
 
Example #6
Source File: AbstractSSTableSimpleWriter.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
protected SSTableWriter getWriter()
{
    return new SSTableWriter(
        makeFilename(directory, metadata.ksName, metadata.cfName),
        0, // We don't care about the bloom filter
        ActiveRepairService.UNREPAIRED_SSTABLE,
        metadata,
        DatabaseDescriptor.getPartitioner(),
        new MetadataCollector(metadata.comparator));
}
 
Example #7
Source File: SSTableUtils.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
public SSTableReader write(int expectedSize, Appender appender) throws IOException
{
    File datafile = (dest == null) ? tempSSTableFile(ksname, cfname, generation) : new File(dest.filenameFor(Component.DATA));
    SSTableWriter writer = new SSTableWriter(datafile.getAbsolutePath(), expectedSize, ActiveRepairService.UNREPAIRED_SSTABLE);
    while (appender.append(writer)) { /* pass */ }
    SSTableReader reader = writer.closeAndOpenReader();
    // mark all components for removal
    if (cleanup)
        for (Component component : reader.components)
            new File(reader.descriptor.filenameFor(component)).deleteOnExit();
    return reader;
}
 
Example #8
Source File: SSTableExportTest.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
/**
 * Tests CASSANDRA-6892 (key aliases being used improperly for validation)
 */
@Test
public void testColumnNameEqualToDefaultKeyAlias() throws IOException, ParseException
{
    File tempSS = tempSSTableFile("Keyspace1", "UUIDKeys");
    ColumnFamily cfamily = ArrayBackedSortedColumns.factory.create("Keyspace1", "UUIDKeys");
    SSTableWriter writer = new SSTableWriter(tempSS.getPath(), 2, ActiveRepairService.UNREPAIRED_SSTABLE);

    // Add a row
    cfamily.addColumn(column(CFMetaData.DEFAULT_KEY_ALIAS, "not a uuid", 1L));
    writer.append(Util.dk(ByteBufferUtil.bytes(UUIDGen.getTimeUUID())), cfamily);

    SSTableReader reader = writer.closeAndOpenReader();
    // Export to JSON and verify
    File tempJson = File.createTempFile("CFWithColumnNameEqualToDefaultKeyAlias", ".json");
    SSTableExport.export(reader, new PrintStream(tempJson.getPath()), new String[0],
            CFMetaData.sparseCFMetaData("Keyspace1", "UUIDKeys", BytesType.instance));

    JSONArray json = (JSONArray)JSONValue.parseWithException(new FileReader(tempJson));
    assertEquals(1, json.size());

    JSONObject row = (JSONObject)json.get(0);
    JSONArray cols = (JSONArray) row.get("cells");
    assertEquals(1, cols.size());

    // check column name and value
    JSONArray col = (JSONArray) cols.get(0);
    assertEquals(CFMetaData.DEFAULT_KEY_ALIAS, ByteBufferUtil.string(hexToBytes((String) col.get(0))));
    assertEquals("not a uuid", ByteBufferUtil.string(hexToBytes((String) col.get(1))));
}
 
Example #9
Source File: LeveledCompactionStrategyTest.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
@Test
public void testValidationMultipleSSTablePerLevel() throws Exception
{
    byte [] b = new byte[100 * 1024];
    new Random().nextBytes(b);
    ByteBuffer value = ByteBuffer.wrap(b); // 100 KB value, make it easy to have multiple files

    // Enough data to have a level 1 and 2
    int rows = 20;
    int columns = 10;

    // Adds enough data to trigger multiple sstable per level
    for (int r = 0; r < rows; r++)
    {
        DecoratedKey key = Util.dk(String.valueOf(r));
        Mutation rm = new Mutation(ksname, key.getKey());
        for (int c = 0; c < columns; c++)
        {
            rm.add(cfname, Util.cellname("column" + c), value, 0);
        }
        rm.apply();
        cfs.forceBlockingFlush();
    }

    waitForLeveling(cfs);
    WrappingCompactionStrategy strategy = (WrappingCompactionStrategy) cfs.getCompactionStrategy();
    // Checking we're not completely bad at math
    assertTrue(strategy.getSSTableCountPerLevel()[1] > 0);
    assertTrue(strategy.getSSTableCountPerLevel()[2] > 0);

    Range<Token> range = new Range<>(Util.token(""), Util.token(""));
    int gcBefore = keyspace.getColumnFamilyStore(cfname).gcBefore(System.currentTimeMillis());
    UUID parentRepSession = UUID.randomUUID();
    ActiveRepairService.instance.registerParentRepairSession(parentRepSession, Arrays.asList(cfs), Arrays.asList(range));
    RepairJobDesc desc = new RepairJobDesc(parentRepSession, UUID.randomUUID(), ksname, cfname, range);
    Validator validator = new Validator(desc, FBUtilities.getBroadcastAddress(), gcBefore);
    CompactionManager.instance.submitValidation(cfs, validator).get();
}
 
Example #10
Source File: DifferencerTest.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
@Test
public void testDifference() throws Throwable
{
    Range<Token> range = new Range<>(partirioner.getMinimumToken(), partirioner.getRandomToken());
    UUID parentRepairSession = UUID.randomUUID();
    Keyspace keyspace = Keyspace.open("Keyspace1");
    ColumnFamilyStore cfs = keyspace.getColumnFamilyStore("Standard1");

    ActiveRepairService.instance.registerParentRepairSession(parentRepairSession, Arrays.asList(cfs), Arrays.asList(range));

    RepairJobDesc desc = new RepairJobDesc(parentRepairSession, UUID.randomUUID(), "Keyspace1", "Standard1", range);

    MerkleTree tree1 = createInitialTree(desc);
    MerkleTree tree2 = createInitialTree(desc);

    // change a range in one of the trees
    Token token = partirioner.midpoint(range.left, range.right);
    tree1.invalidate(token);
    MerkleTree.TreeRange changed = tree1.get(token);
    changed.hash("non-empty hash!".getBytes());

    Set<Range<Token>> interesting = new HashSet<>();
    interesting.add(changed);

    // difference the trees
    // note: we reuse the same endpoint which is bogus in theory but fine here
    TreeResponse r1 = new TreeResponse(InetAddress.getByName("127.0.0.1"), tree1);
    TreeResponse r2 = new TreeResponse(InetAddress.getByName("127.0.0.2"), tree2);
    Differencer diff = new Differencer(desc, r1, r2);
    diff.run();

    // ensure that the changed range was recorded
    assertEquals("Wrong differing ranges", interesting, new HashSet<>(diff.differences));
}
 
Example #11
Source File: StreamSession.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
private List<SSTableStreamingSections> getSSTableSectionsForRanges(Collection<Range<Token>> ranges, Collection<ColumnFamilyStore> stores, long overriddenRepairedAt, boolean isIncremental)
{
    Refs<SSTableReader> refs = new Refs<>();
    try
    {
        for (ColumnFamilyStore cfStore : stores)
        {
            List<AbstractBounds<RowPosition>> rowBoundsList = new ArrayList<>(ranges.size());
            for (Range<Token> range : ranges)
                rowBoundsList.add(range.toRowBounds());
            refs.addAll(cfStore.selectAndReference(cfStore.viewFilter(rowBoundsList, !isIncremental)).refs);
        }

        List<SSTableStreamingSections> sections = new ArrayList<>(refs.size());
        for (SSTableReader sstable : refs)
        {
            long repairedAt = overriddenRepairedAt;
            if (overriddenRepairedAt == ActiveRepairService.UNREPAIRED_SSTABLE)
                repairedAt = sstable.getSSTableMetadata().repairedAt;
            sections.add(new SSTableStreamingSections(sstable, refs.get(sstable),
                                                      sstable.getPositionsForRanges(ranges),
                                                      sstable.estimatedKeysForRanges(ranges),
                                                      repairedAt));
        }
        return sections;
    }
    catch (Throwable t)
    {
        refs.release();
        throw t;
    }
}
 
Example #12
Source File: Compact.java    From sstable-tools with Apache License 2.0 5 votes vote down vote up
public void run() {
    try {
        Descriptor desc = new Descriptor(SSTableFormat.Type.BIG.info.getLatestVersion(),
                new File("."),
                "keyspace",
                "table",
                0,
                SSTableFormat.Type.BIG,
                Component.digestFor(BigFormat.latestVersion.uncompressedChecksumType()));

        SSTableTxnWriter out = SSTableTxnWriter.create(metadata,
                desc,
                0,
                ActiveRepairService.UNREPAIRED_SSTABLE,
                0,
                SerializationHeader.make(metadata, sstables),
                Collections.emptySet());

        System.out.println("Merging " + sstables.size() + " sstables to " + desc.filenameFor(Component.DATA));

        UnfilteredPartitionIterator merged =
                UnfilteredPartitionIterators.mergeLazily(
                        sstables.stream()
                                .map(SSTableReader::getScanner)
                                .collect(Collectors.toList()),
                        FBUtilities.nowInSeconds());
        while (merged.hasNext()) {
            out.append(merged.next());
        }
        out.finish(false);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
 
Example #13
Source File: CompactionTask.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
private long getMinRepairedAt(Set<SSTableReader> actuallyCompact)
{
    long minRepairedAt= Long.MAX_VALUE;
    for (SSTableReader sstable : actuallyCompact)
        minRepairedAt = Math.min(minRepairedAt, sstable.getSSTableMetadata().repairedAt);
    if (minRepairedAt == Long.MAX_VALUE)
        return ActiveRepairService.UNREPAIRED_SSTABLE;
    return minRepairedAt;
}
 
Example #14
Source File: Memtable.java    From stratio-cassandra with Apache License 2.0 5 votes vote down vote up
public SSTableWriter createFlushWriter(String filename) throws ExecutionException, InterruptedException
{
    MetadataCollector sstableMetadataCollector = new MetadataCollector(cfs.metadata.comparator).replayPosition(context);
    return new SSTableWriter(filename,
                             rows.size(),
                             ActiveRepairService.UNREPAIRED_SSTABLE,
                             cfs.metadata,
                             cfs.partitioner,
                             sstableMetadataCollector);
}
 
Example #15
Source File: TestObjectFactory.java    From cassandra-mesos-deprecated with Apache License 2.0 4 votes vote down vote up
public void emitRepairNotification(final ActiveRepairService.Status status) {
    final Notification notification = new Notification("repair", this, ++sequence, System.currentTimeMillis(), "hello world");
    notification.setUserData(new int[]{commandSeq, status.ordinal()});
    emitNotification(notification);
}
 
Example #16
Source File: SSTableRepairedAtSetter.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
/**
 * @param args a list of sstables whose metadata we are changing
 */
public static void main(final String[] args) throws IOException
{
    PrintStream out = System.out;
    if (args.length == 0)
    {
        out.println("This command should be run with Cassandra stopped!");
        out.println("Usage: sstablerepairedset [--is-repaired | --is-unrepaired] [-f <sstable-list> | <sstables>]");
        System.exit(1);
    }

    if (args.length < 3 || !args[0].equals("--really-set") || (!args[1].equals("--is-repaired") && !args[1].equals("--is-unrepaired")))
    {
        out.println("This command should be run with Cassandra stopped, otherwise you will get very strange behavior");
        out.println("Verify that Cassandra is not running and then execute the command like this:");
        out.println("Usage: sstablerepairedset --really-set [--is-repaired | --is-unrepaired] [-f <sstable-list> | <sstables>]");
        System.exit(1);
    }

    boolean setIsRepaired = args[1].equals("--is-repaired");

    List<String> fileNames;
    if (args[2].equals("-f"))
    {
        fileNames = Files.readAllLines(Paths.get(args[3]), Charset.defaultCharset());
    }
    else
    {
        fileNames = Arrays.asList(args).subList(2, args.length);
    }

    for (String fname: fileNames)
    {
        Descriptor descriptor = Descriptor.fromFilename(fname);
        if (descriptor.version.hasRepairedAt)
        {
            if (setIsRepaired)
            {
                FileTime f = Files.getLastModifiedTime(new File(descriptor.filenameFor(Component.DATA)).toPath());
                descriptor.getMetadataSerializer().mutateRepairedAt(descriptor, f.toMillis());
            }
            else
            {
                descriptor.getMetadataSerializer().mutateRepairedAt(descriptor, ActiveRepairService.UNREPAIRED_SSTABLE);
            }
        }
        else
        {
            System.err.println("SSTable " + fname + " does not have repaired property, run upgradesstables");
        }
    }
}
 
Example #17
Source File: NodeRepairJob.java    From cassandra-mesos-deprecated with Apache License 2.0 4 votes vote down vote up
@Override
public void handleNotification(final Notification notification, final Object handback) {
    if (!"repair".equals(notification.getType())) {
        return;
    }

    final int[] result = (int[]) notification.getUserData();
    final int repairCommandNo = result[0];
    final ActiveRepairService.Status status = ActiveRepairService.Status.values()[result[1]];

    final String keyspace = commandToKeyspace.get(repairCommandNo);

    switch (status) {
        case STARTED:
            LOGGER.info("Received STARTED notification about repair for keyspace {} with cmd#{}, timetamp={}, message={}",
                    keyspace, repairCommandNo, notification.getTimeStamp(), notification.getMessage());
            keyspaceStarted();
            break;
        case SESSION_SUCCESS:
            LOGGER.debug("Received SESSION_SUCCESS notification about repair for keyspace {} with cmd#{}, timetamp={}, message={}",
                    keyspace, repairCommandNo, notification.getTimeStamp(), notification.getMessage());
            break;
        case SESSION_FAILED:
            LOGGER.warn("Received SESSION_FAILED notification about repair for keyspace {} with cmd#{}, timetamp={}, message={}",
                    keyspace, repairCommandNo, notification.getTimeStamp(), notification.getMessage());
            break;
        case FINISHED:
            LOGGER.info("Received FINISHED notification about repair for keyspace {} with cmd#{}, timetamp={}, message={}",
                    keyspace, repairCommandNo, notification.getTimeStamp(), notification.getMessage());

            keyspaceFinished(status.name(), keyspace);

            startNextKeyspace();

            break;
    }

    // TODO also allow StorageServiceMBean.forceTerminateAllRepairSessions

    /*
    TODO handle these, too !!!

    else if (JMXConnectionNotification.NOTIFS_LOST.equals(notification.getType()))
    {
        String message = String.format("[%s] Lost notification. You should check server log for repair status of keyspace %s",
                                       format.format(notification.getTimeStamp()),
                                       keyspace);
        out.println(message);
    }
    else if (JMXConnectionNotification.FAILED.equals(notification.getType())
             || JMXConnectionNotification.CLOSED.equals(notification.getType()))
    {
        String message = String.format("JMX connection closed. You should check server log for repair status of keyspace %s"
                                       + "(Subsequent keyspaces are not going to be repaired).",
                                       keyspace);
        error = new IOException(message);
        condition.signalAll();
    }

     */
}
 
Example #18
Source File: SegmentRunner.java    From cassandra-reaper with Apache License 2.0 4 votes vote down vote up
/**
 * Called when there is an event coming either from JMX or this runner regarding on-going repairs.
 *
 * @param repairNo repair sequence number, obtained when triggering a repair
 * @param status new status of the repair
 * @param message additional information about the repair
 */
@Override
public void handle(
    int repairNo,
    Optional<ActiveRepairService.Status> status,
    Optional<ProgressEventType> progress,
    String message,
    JmxProxy jmxProxy) {

  final RepairSegment segment = context.storage.getRepairSegment(repairRunner.getRepairRunId(), segmentId).get();
  Thread.currentThread().setName(clusterName + ":" + segment.getRunId() + ":" + segmentId);
  LOG.debug(
      "handle called for repairCommandId {}, outcome {} / {} and message: {}",
      repairNo,
      status,
      progress,
      message);

  Preconditions.checkArgument(
      repairNo == this.repairNo,
      "Handler for command id %s not handling message %s with number %s",
      this.repairNo, (status.isPresent() ? status.get() : progress.get()), repairNo);

  boolean failOutsideSynchronizedBlock = false;
  // DO NOT ADD EXTERNAL CALLS INSIDE THIS SYNCHRONIZED BLOCK (JMX PROXY ETC)
  synchronized (condition) {
    RepairSegment currentSegment = context.storage.getRepairSegment(repairRunner.getRepairRunId(), segmentId).get();

    Preconditions.checkState(
        RepairSegment.State.NOT_STARTED != currentSegment.getState() || successOrFailedNotified.get(),
        "received " + (status.isPresent() ? status.get() : progress.get()) + " on unstarted segment " + segmentId);

    // See status explanations at: https://wiki.apache.org/cassandra/RepairAsyncAPI
    // Old repair API – up to Cassandra-2.1.x
    if (status.isPresent()) {
      failOutsideSynchronizedBlock = handleJmxNotificationForCassandra21(
          status,
          currentSegment,
          repairNo,
          failOutsideSynchronizedBlock,
          progress,
          jmxProxy);
    }
    // New repair API – Cassandra-2.2 onwards
    if (progress.isPresent()) {
      failOutsideSynchronizedBlock = handleJmxNotificationForCassandra22(
          progress,
          currentSegment,
          repairNo,
          failOutsideSynchronizedBlock,
          jmxProxy);
    }
  }

  if (failOutsideSynchronizedBlock) {
    if (takeLead() || renewLead()) {
      try {
        postponeCurrentSegment();
        tryClearSnapshots(message);
      } finally {
        // if someone else does hold the lease, ie renewLead(..) was true,
        // then their writes to repair_run table and any call to releaseLead(..) will throw an exception
        try {
          releaseLead();
        } catch (AssertionError ignore) { }
      }
    }
  }
}
 
Example #19
Source File: RepairSession.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
public void runMayThrow() throws Exception
{
    logger.info(String.format("[repair #%s] new session: will sync %s on range %s for %s.%s", getId(), repairedNodes(), range, keyspace, Arrays.toString(cfnames)));

    if (endpoints.isEmpty())
    {
        differencingDone.signalAll();
        logger.info(String.format("[repair #%s] No neighbors to repair with on range %s: session completed", getId(), range));
        return;
    }

    // Checking all nodes are live
    for (InetAddress endpoint : endpoints)
    {
        if (!FailureDetector.instance.isAlive(endpoint))
        {
            String message = String.format("Cannot proceed on repair because a neighbor (%s) is dead: session failed", endpoint);
            differencingDone.signalAll();
            logger.error("[repair #{}] {}", getId(), message);
            throw new IOException(message);
        }
    }

    ActiveRepairService.instance.addToActiveSessions(this);
    try
    {
        // Create and queue a RepairJob for each column family
        for (String cfname : cfnames)
        {
            RepairJob job = new RepairJob(this, parentRepairSession, id, keyspace, cfname, range, parallelismDegree, taskExecutor);
            jobs.offer(job);
        }
        logger.debug("Sending tree requests to endpoints {}", endpoints);
        jobs.peek().sendTreeRequests(endpoints);

        // block whatever thread started this session until all requests have been returned:
        // if this thread dies, the session will still complete in the background
        completed.await();

        if (exception == null)
        {
            logger.info(String.format("[repair #%s] session completed successfully", getId()));
        }
        else
        {
            logger.error(String.format("[repair #%s] session completed with the following error", getId()), exception);
            throw exception;
        }
    }
    catch (InterruptedException e)
    {
        throw new RuntimeException("Interrupted while waiting for repair.");
    }
    finally
    {
        // mark this session as terminated
        terminate();

        ActiveRepairService.instance.removeFromActiveSessions(this);

        // If we've reached here in an exception state without completing Merkle Tree sync, we'll still be registered
        // with the FailureDetector.
        if (fdUnregistered.compareAndSet(false, true))
            FailureDetector.instance.unregisterFailureDetectionEventListener(this);
    }
}
 
Example #20
Source File: SSTableExportTest.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
@Test
public void testExportColumnsWithMetadata() throws IOException, ParseException
{
    File tempSS = tempSSTableFile("Keyspace1", "Standard1");
    ColumnFamily cfamily = ArrayBackedSortedColumns.factory.create("Keyspace1", "Standard1");
    SSTableWriter writer = new SSTableWriter(tempSS.getPath(), 2, ActiveRepairService.UNREPAIRED_SSTABLE);

    // Add rowA
    cfamily.addColumn(Util.cellname("colName"), ByteBufferUtil.bytes("val"), System.currentTimeMillis());
    cfamily.addColumn(Util.cellname("colName1"), ByteBufferUtil.bytes("val1"), System.currentTimeMillis());
    cfamily.delete(new DeletionInfo(0, 0));
    writer.append(Util.dk("rowA"), cfamily);

    SSTableReader reader = writer.closeAndOpenReader();
    // Export to JSON and verify
    File tempJson = File.createTempFile("CFWithDeletionInfo", ".json");
    SSTableExport.export(reader, new PrintStream(tempJson.getPath()), new String[0],
            CFMetaData.sparseCFMetaData("Keyspace1", "Counter1", BytesType.instance));

    JSONArray json = (JSONArray)JSONValue.parseWithException(new FileReader(tempJson));
    assertEquals("unexpected number of rows", 1, json.size());

    JSONObject row = (JSONObject)json.get(0);
    assertEquals("unexpected number of keys", 3, row.keySet().size());
    assertEquals("unexpected row key",asHex("rowA"),row.get("key"));

    // check that the row key is there and present
    String rowKey = (String) row.get("key");
    assertNotNull("expecing key to be present", rowKey);
    assertEquals("key did not match", ByteBufferUtil.bytes("rowA"), hexToBytes(rowKey));

    // check that there is metadata and that it contains deletionInfo
    JSONObject meta = (JSONObject) row.get("metadata");
    assertNotNull("expecing metadata to be present", meta);

    assertEquals("unexpected number of metadata entries", 1, meta.keySet().size());

    JSONObject serializedDeletionInfo = (JSONObject) meta.get("deletionInfo");
    assertNotNull("expecing deletionInfo to be present", serializedDeletionInfo);

    assertEquals(
            "unexpected serialization format for topLevelDeletion",
            "{\"markedForDeleteAt\":0,\"localDeletionTime\":0}",
            serializedDeletionInfo.toJSONString());

    // check the colums are what we put in
    JSONArray cols = (JSONArray) row.get("cells");
    assertNotNull("expecing columns to be present", cols);
    assertEquals("expecting two columns", 2, cols.size());

    JSONArray col1 = (JSONArray) cols.get(0);
    assertEquals("column name did not match", ByteBufferUtil.bytes("colName"), hexToBytes((String) col1.get(0)));
    assertEquals("column value did not match", ByteBufferUtil.bytes("val"), hexToBytes((String) col1.get(1)));

    JSONArray col2 = (JSONArray) cols.get(1);
    assertEquals("column name did not match", ByteBufferUtil.bytes("colName1"), hexToBytes((String) col2.get(0)));
    assertEquals("column value did not match", ByteBufferUtil.bytes("val1"), hexToBytes((String) col2.get(1)));
}
 
Example #21
Source File: ColumnFamilyStoreTest.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
@Test
public void testRemoveUnfinishedCompactionLeftovers() throws Throwable
{
    String ks = "Keyspace1";
    String cf = "Standard3"; // should be empty

    final CFMetaData cfmeta = Schema.instance.getCFMetaData(ks, cf);
    Directories dir = new Directories(cfmeta);
    ByteBuffer key = bytes("key");

    // 1st sstable
    SSTableSimpleWriter writer = new SSTableSimpleWriter(dir.getDirectoryForNewSSTables(), cfmeta, StorageService.getPartitioner());
    writer.newRow(key);
    writer.addColumn(bytes("col"), bytes("val"), 1);
    writer.close();

    Map<Descriptor, Set<Component>> sstables = dir.sstableLister().list();
    assertEquals(1, sstables.size());

    Map.Entry<Descriptor, Set<Component>> sstableToOpen = sstables.entrySet().iterator().next();
    final SSTableReader sstable1 = SSTableReader.open(sstableToOpen.getKey());

    // simulate incomplete compaction
    writer = new SSTableSimpleWriter(dir.getDirectoryForNewSSTables(),
                                     cfmeta, StorageService.getPartitioner())
    {
        protected SSTableWriter getWriter()
        {
            MetadataCollector collector = new MetadataCollector(cfmeta.comparator);
            collector.addAncestor(sstable1.descriptor.generation); // add ancestor from previously written sstable
            return new SSTableWriter(makeFilename(directory, metadata.ksName, metadata.cfName),
                                     0,
                                     ActiveRepairService.UNREPAIRED_SSTABLE,
                                     metadata,
                                     StorageService.getPartitioner(),
                                     collector);
        }
    };
    writer.newRow(key);
    writer.addColumn(bytes("col"), bytes("val"), 1);
    writer.close();

    // should have 2 sstables now
    sstables = dir.sstableLister().list();
    assertEquals(2, sstables.size());

    SSTableReader sstable2 = SSTableReader.open(sstable1.descriptor);
    UUID compactionTaskID = SystemKeyspace.startCompaction(
            Keyspace.open(ks).getColumnFamilyStore(cf),
            Collections.singleton(sstable2));

    Map<Integer, UUID> unfinishedCompaction = new HashMap<>();
    unfinishedCompaction.put(sstable1.descriptor.generation, compactionTaskID);
    ColumnFamilyStore.removeUnfinishedCompactionLeftovers(cfmeta, unfinishedCompaction);

    // 2nd sstable should be removed (only 1st sstable exists in set of size 1)
    sstables = dir.sstableLister().list();
    assertEquals(1, sstables.size());
    assertTrue(sstables.containsKey(sstable1.descriptor));

    Map<Pair<String, String>, Map<Integer, UUID>> unfinished = SystemKeyspace.getUnfinishedCompactions();
    assertTrue(unfinished.isEmpty());
    sstable1.selfRef().release();
    sstable2.selfRef().release();
}
 
Example #22
Source File: SSTableLoader.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
protected Collection<SSTableReader> openSSTables(final Map<InetAddress, Collection<Range<Token>>> ranges)
{
    outputHandler.output("Opening sstables and calculating sections to stream");

    directory.list(new FilenameFilter()
    {
        public boolean accept(File dir, String name)
        {
            if (new File(dir, name).isDirectory())
                return false;
            Pair<Descriptor, Component> p = SSTable.tryComponentFromFilename(dir, name);
            Descriptor desc = p == null ? null : p.left;
            if (p == null || !p.right.equals(Component.DATA) || desc.type.isTemporary)
                return false;

            if (!new File(desc.filenameFor(Component.PRIMARY_INDEX)).exists())
            {
                outputHandler.output(String.format("Skipping file %s because index is missing", name));
                return false;
            }

            CFMetaData metadata = client.getCFMetaData(keyspace, desc.cfname);
            if (metadata == null)
            {
                outputHandler.output(String.format("Skipping file %s: column family %s.%s doesn't exist", name, keyspace, desc.cfname));
                return false;
            }

            Set<Component> components = new HashSet<>();
            components.add(Component.DATA);
            components.add(Component.PRIMARY_INDEX);
            if (new File(desc.filenameFor(Component.SUMMARY)).exists())
                components.add(Component.SUMMARY);
            if (new File(desc.filenameFor(Component.COMPRESSION_INFO)).exists())
                components.add(Component.COMPRESSION_INFO);
            if (new File(desc.filenameFor(Component.STATS)).exists())
                components.add(Component.STATS);

            try
            {
                // To conserve memory, open SSTableReaders without bloom filters and discard
                // the index summary after calculating the file sections to stream and the estimated
                // number of keys for each endpoint. See CASSANDRA-5555 for details.
                SSTableReader sstable = SSTableReader.openForBatch(desc, components, metadata, client.getPartitioner());
                sstables.add(sstable);

                // calculate the sstable sections to stream as well as the estimated number of
                // keys per host
                for (Map.Entry<InetAddress, Collection<Range<Token>>> entry : ranges.entrySet())
                {
                    InetAddress endpoint = entry.getKey();
                    Collection<Range<Token>> tokenRanges = entry.getValue();

                    List<Pair<Long, Long>> sstableSections = sstable.getPositionsForRanges(tokenRanges);
                    long estimatedKeys = sstable.estimatedKeysForRanges(tokenRanges);
                    Ref ref = sstable.tryRef();
                    if (ref == null)
                        throw new IllegalStateException("Could not acquire ref for "+sstable);
                    StreamSession.SSTableStreamingSections details = new StreamSession.SSTableStreamingSections(sstable, ref, sstableSections, estimatedKeys, ActiveRepairService.UNREPAIRED_SSTABLE);
                    streamingDetails.put(endpoint, details);
                }

                // to conserve heap space when bulk loading
                sstable.releaseSummary();
            }
            catch (IOException e)
            {
                outputHandler.output(String.format("Skipping file %s, error opening it: %s", name, e.getMessage()));
            }
            return false;
        }
    });
    return sstables;
}
 
Example #23
Source File: CompactionManager.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
/**
 * Splits up an sstable into two new sstables. The first of the new tables will store repaired ranges, the second
 * will store the non-repaired ranges. Once anticompation is completed, the original sstable is marked as compacted
 * and subsequently deleted.
 * @param cfs
 * @param repairedSSTables
 * @param ranges Repaired ranges to be placed into one of the new sstables. The repaired table will be tracked via
 * the {@link org.apache.cassandra.io.sstable.metadata.StatsMetadata#repairedAt} field.
 */
private Collection<SSTableReader> doAntiCompaction(ColumnFamilyStore cfs, Collection<Range<Token>> ranges, Collection<SSTableReader> repairedSSTables, long repairedAt)
{
    List<SSTableReader> anticompactedSSTables = new ArrayList<>();
    int repairedKeyCount = 0;
    int unrepairedKeyCount = 0;
    logger.info("Performing anticompaction on {} sstables", repairedSSTables.size());
    // iterate over sstables to check if the repaired / unrepaired ranges intersect them.
    for (SSTableReader sstable : repairedSSTables)
    {
        // check that compaction hasn't stolen any sstables used in previous repair sessions
        // if we need to skip the anticompaction, it will be carried out by the next repair
        if (!new File(sstable.getFilename()).exists())
        {
            logger.info("Skipping anticompaction for {}, required sstable was compacted and is no longer available.", sstable);
            continue;
        }

        logger.info("Anticompacting {}", sstable);
        Set<SSTableReader> sstableAsSet = new HashSet<>();
        sstableAsSet.add(sstable);

        File destination = cfs.directories.getWriteableLocationAsFile(cfs.getExpectedCompactedFileSize(sstableAsSet, OperationType.ANTICOMPACTION));
        SSTableRewriter repairedSSTableWriter = new SSTableRewriter(cfs, sstableAsSet, sstable.maxDataAge, false);
        SSTableRewriter unRepairedSSTableWriter = new SSTableRewriter(cfs, sstableAsSet, sstable.maxDataAge, false);

        try (AbstractCompactionStrategy.ScannerList scanners = cfs.getCompactionStrategy().getScanners(new HashSet<>(Collections.singleton(sstable)));
             CompactionController controller = new CompactionController(cfs, sstableAsSet, CFMetaData.DEFAULT_GC_GRACE_SECONDS))
        {
            int expectedBloomFilterSize = Math.max(cfs.metadata.getMinIndexInterval(), (int)sstable.estimatedKeys());
            repairedSSTableWriter.switchWriter(CompactionManager.createWriter(cfs, destination, expectedBloomFilterSize, repairedAt, sstable));
            unRepairedSSTableWriter.switchWriter(CompactionManager.createWriter(cfs, destination, expectedBloomFilterSize, ActiveRepairService.UNREPAIRED_SSTABLE, sstable));

            CompactionIterable ci = new CompactionIterable(OperationType.ANTICOMPACTION, scanners.scanners, controller);
            Iterator<AbstractCompactedRow> iter = ci.iterator();
            metrics.beginCompaction(ci);
            try
            {
                while (iter.hasNext())
                {
                    AbstractCompactedRow row = iter.next();
                    // if current range from sstable is repaired, save it into the new repaired sstable
                    if (Range.isInRanges(row.key.getToken(), ranges))
                    {
                        repairedSSTableWriter.append(row);
                        repairedKeyCount++;
                    }
                    // otherwise save into the new 'non-repaired' table
                    else
                    {
                        unRepairedSSTableWriter.append(row);
                        unrepairedKeyCount++;
                    }
                }
            }
            finally
            {
                metrics.finishCompaction(ci);
            }
            anticompactedSSTables.addAll(repairedSSTableWriter.finish(repairedAt));
            anticompactedSSTables.addAll(unRepairedSSTableWriter.finish(ActiveRepairService.UNREPAIRED_SSTABLE));
            cfs.getDataTracker().markCompactedSSTablesReplaced(sstableAsSet, anticompactedSSTables, OperationType.ANTICOMPACTION);
        }
        catch (Throwable e)
        {
            JVMStabilityInspector.inspectThrowable(e);
            logger.error("Error anticompacting " + sstable, e);
            repairedSSTableWriter.abort();
            unRepairedSSTableWriter.abort();
        }
    }
    String format = "Repaired {} keys of {} for {}/{}";
    logger.debug(format, repairedKeyCount, (repairedKeyCount + unrepairedKeyCount), cfs.keyspace, cfs.getColumnFamilyName());
    String format2 = "Anticompaction completed successfully, anticompacted from {} to {} sstable(s).";
    logger.info(format2, repairedSSTables.size(), anticompactedSSTables.size());

    return anticompactedSSTables;
}
 
Example #24
Source File: LegacyMetadataSerializer.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
/**
 * Legacy serializer deserialize all components no matter what types are specified.
 */
@Override
public Map<MetadataType, MetadataComponent> deserialize(Descriptor descriptor, EnumSet<MetadataType> types) throws IOException
{
    Map<MetadataType, MetadataComponent> components = Maps.newHashMap();

    File statsFile = new File(descriptor.filenameFor(Component.STATS));
    if (!statsFile.exists() && types.contains(MetadataType.STATS))
    {
        components.put(MetadataType.STATS, MetadataCollector.defaultStatsMetadata());
    }
    else
    {
        try (DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(statsFile))))
        {
            EstimatedHistogram rowSizes = EstimatedHistogram.serializer.deserialize(in);
            EstimatedHistogram columnCounts = EstimatedHistogram.serializer.deserialize(in);
            ReplayPosition replayPosition = ReplayPosition.serializer.deserialize(in);
            long minTimestamp = in.readLong();
            long maxTimestamp = in.readLong();
            int maxLocalDeletionTime = in.readInt();
            double bloomFilterFPChance = in.readDouble();
            double compressionRatio = in.readDouble();
            String partitioner = in.readUTF();
            int nbAncestors = in.readInt();
            Set<Integer> ancestors = new HashSet<>(nbAncestors);
            for (int i = 0; i < nbAncestors; i++)
                ancestors.add(in.readInt());
            StreamingHistogram tombstoneHistogram = StreamingHistogram.serializer.deserialize(in);
            int sstableLevel = 0;
            if (in.available() > 0)
                sstableLevel = in.readInt();

            int colCount = in.readInt();
            List<ByteBuffer> minColumnNames = new ArrayList<>(colCount);
            for (int i = 0; i < colCount; i++)
                minColumnNames.add(ByteBufferUtil.readWithShortLength(in));

            colCount = in.readInt();
            List<ByteBuffer> maxColumnNames = new ArrayList<>(colCount);
            for (int i = 0; i < colCount; i++)
                maxColumnNames.add(ByteBufferUtil.readWithShortLength(in));

            if (types.contains(MetadataType.VALIDATION))
                components.put(MetadataType.VALIDATION,
                               new ValidationMetadata(partitioner, bloomFilterFPChance));
            if (types.contains(MetadataType.STATS))
                components.put(MetadataType.STATS,
                               new StatsMetadata(rowSizes,
                                                 columnCounts,
                                                 replayPosition,
                                                 minTimestamp,
                                                 maxTimestamp,
                                                 maxLocalDeletionTime,
                                                 compressionRatio,
                                                 tombstoneHistogram,
                                                 sstableLevel,
                                                 minColumnNames,
                                                 maxColumnNames,
                                                 true,
                                                 ActiveRepairService.UNREPAIRED_SSTABLE));
            if (types.contains(MetadataType.COMPACTION))
                components.put(MetadataType.COMPACTION,
                               new CompactionMetadata(ancestors, null));
        }
    }
    return components;
}
 
Example #25
Source File: SSTableReader.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
public boolean isRepaired()
{
    return sstableMetadata.repairedAt != ActiveRepairService.UNREPAIRED_SSTABLE;
}
 
Example #26
Source File: SSTableImport.java    From stratio-cassandra with Apache License 2.0 4 votes vote down vote up
private int importSorted(String jsonFile, ColumnFamily columnFamily, String ssTablePath,
        IPartitioner partitioner) throws IOException
{
    int importedKeys = 0; // already imported keys count
    long start = System.nanoTime();

    JsonParser parser = getParser(jsonFile);

    if (keyCountToImport == null)
    {
        keyCountToImport = 0;
        System.out.println("Counting keys to import, please wait... (NOTE: to skip this use -n <num_keys>)");

        parser.nextToken(); // START_ARRAY
        while (parser.nextToken() != null)
        {
            parser.skipChildren();
            if (parser.getCurrentToken() == JsonToken.END_ARRAY)
                break;

            keyCountToImport++;
        }
    }

    System.out.printf("Importing %s keys...%n", keyCountToImport);

    parser = getParser(jsonFile); // renewing parser
    SSTableWriter writer = new SSTableWriter(ssTablePath, keyCountToImport, ActiveRepairService.UNREPAIRED_SSTABLE);

    int lineNumber = 1;
    DecoratedKey prevStoredKey = null;

    parser.nextToken(); // START_ARRAY
    while (parser.nextToken() != null)
    {
        String key = parser.getCurrentName();
        Map<?, ?> row = parser.readValueAs(new TypeReference<Map<?, ?>>(){});
        DecoratedKey currentKey = partitioner.decorateKey(getKeyValidator(columnFamily).fromString((String) row.get("key")));

        if (row.containsKey("metadata"))
            parseMeta((Map<?, ?>) row.get("metadata"), columnFamily, null);

        addColumnsToCF((List<?>) row.get("cells"), columnFamily);

        if (prevStoredKey != null && prevStoredKey.compareTo(currentKey) != -1)
        {
            System.err
                    .printf("Line %d: Key %s is greater than previous, collection is not sorted properly. Aborting import. You might need to delete SSTables manually.%n",
                            lineNumber, key);
            return -1;
        }

        // saving decorated key
        writer.append(currentKey, columnFamily);
        columnFamily.clear();

        prevStoredKey = currentKey;
        importedKeys++;
        lineNumber++;

        long current = System.nanoTime();

        if (TimeUnit.NANOSECONDS.toSeconds(current - start) >= 5) // 5 secs.
        {
            System.out.printf("Currently imported %d keys.%n", importedKeys);
            start = current;
        }

        if (keyCountToImport == importedKeys)
            break;

    }

    writer.closeAndOpenReader();

    return importedKeys;
}
 
Example #27
Source File: RepairStatusHandler.java    From cassandra-reaper with Apache License 2.0 3 votes vote down vote up
/**
 * Handle an event representing a change in the state of a running repair.
 *
 * <p>Implementation of this method is intended to persist the repair state change in Reaper's
 * state.
 *
 * @param repairNumber repair sequence number, obtained when triggering a repair
 * @param status new status of the repair (old API)
 * @param progress new status of the repair (new API)
 * @param message additional information about the repair
 */
void handle(
    int repairNumber,
    Optional<ActiveRepairService.Status> status,
    Optional<ProgressEventType> progress,
    String message,
    JmxProxy jmxProxy);
 
Example #28
Source File: StreamPlan.java    From stratio-cassandra with Apache License 2.0 2 votes vote down vote up
/**
 * Start building stream plan.
 *
 * @param description Stream type that describes this StreamPlan
 */
public StreamPlan(String description)
{
    this(description, ActiveRepairService.UNREPAIRED_SSTABLE, 1);
}