blob: 416a2b874ec42d836513abef411e40fa6f1479e2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.cassandra.db;
import org.apache.cassandra.index.Index;
import org.apache.cassandra.utils.concurrent.OpOrder;
public class ReadOrderGroup implements AutoCloseable
{
// For every reads
private final OpOrder.Group baseOp;
// For index reads
private final OpOrder.Group indexOp;
private final OpOrder.Group writeOp;
private ReadOrderGroup(OpOrder.Group baseOp, OpOrder.Group indexOp, OpOrder.Group writeOp)
{
this.baseOp = baseOp;
this.indexOp = indexOp;
this.writeOp = writeOp;
}
public OpOrder.Group baseReadOpOrderGroup()
{
return baseOp;
}
public OpOrder.Group indexReadOpOrderGroup()
{
return indexOp;
}
public OpOrder.Group writeOpOrderGroup()
{
return writeOp;
}
public static ReadOrderGroup emptyGroup()
{
return new ReadOrderGroup(null, null, null);
}
@SuppressWarnings("resource") // ops closed during group close
public static ReadOrderGroup forCommand(ReadCommand command)
{
ColumnFamilyStore baseCfs = Keyspace.openAndGetStore(command.metadata());
ColumnFamilyStore indexCfs = maybeGetIndexCfs(baseCfs, command);
if (indexCfs == null)
{
return new ReadOrderGroup(baseCfs.readOrdering.start(), null, null);
}
else
{
OpOrder.Group baseOp = null, indexOp = null, writeOp = null;
// OpOrder.start() shouldn't fail, but better safe than sorry.
try
{
baseOp = baseCfs.readOrdering.start();
indexOp = indexCfs.readOrdering.start();
// TODO: this should perhaps not open and maintain a writeOp for the full duration, but instead only *try* to delete stale entries, without blocking if there's no room
// as it stands, we open a writeOp and keep it open for the duration to ensure that should this CF get flushed to make room we don't block the reclamation of any room being made
writeOp = Keyspace.writeOrder.start();
return new ReadOrderGroup(baseOp, indexOp, writeOp);
}
catch (RuntimeException e)
{
// Note that must have writeOp == null since ReadOrderGroup ctor can't fail
assert writeOp == null;
try
{
if (baseOp != null)
baseOp.close();
}
finally
{
if (indexOp != null)
indexOp.close();
}
throw e;
}
}
}
private static ColumnFamilyStore maybeGetIndexCfs(ColumnFamilyStore baseCfs, ReadCommand command)
{
Index index = command.getIndex(baseCfs);
return index == null ? null : index.getBackingTable().orElse(null);
}
public void close()
{
try
{
if (baseOp != null)
baseOp.close();
}
finally
{
if (indexOp != null)
{
try
{
indexOp.close();
}
finally
{
writeOp.close();
}
}
}
}
}