| /* | 
 |  * 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(); | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 | } |