Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.torodb.backend.SharedWriteBackendTransactionImpl Maven / Gradle / Ivy
/*
* ToroDB
* Copyright © 2014 8Kdata Technology (www.8kdata.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package com.torodb.backend;
import com.google.common.base.Preconditions;
import com.torodb.backend.ErrorHandler.Context;
import com.torodb.core.TableRef;
import com.torodb.core.TableRefFactory;
import com.torodb.core.backend.MetaInfoKey;
import com.torodb.core.backend.SharedWriteBackendTransaction;
import com.torodb.core.d2r.DocPartData;
import com.torodb.core.d2r.IdentifierFactory;
import com.torodb.core.exceptions.user.UserException;
import com.torodb.core.transaction.RollbackException;
import com.torodb.core.transaction.metainf.MetaCollection;
import com.torodb.core.transaction.metainf.MetaDatabase;
import com.torodb.core.transaction.metainf.MetaDocPart;
import com.torodb.core.transaction.metainf.MetaDocPartIndexColumn;
import com.torodb.core.transaction.metainf.MetaField;
import com.torodb.core.transaction.metainf.MetaIdentifiedDocPartIndex;
import com.torodb.core.transaction.metainf.MetaIndex;
import com.torodb.core.transaction.metainf.MetaIndexField;
import com.torodb.core.transaction.metainf.MetaScalar;
import com.torodb.core.transaction.metainf.MutableMetaCollection;
import com.torodb.core.transaction.metainf.MutableMetaDocPart;
import com.torodb.core.transaction.metainf.MutableMetaDocPartIndex;
import com.torodb.kvdocument.values.KvValue;
import org.apache.logging.log4j.Logger;
import org.jooq.lambda.tuple.Tuple2;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class SharedWriteBackendTransactionImpl extends BackendTransactionImpl implements
SharedWriteBackendTransaction {
@SuppressWarnings("checkstyle:LineLength")
private static final Logger LOGGER
= BackendLoggerFactory.get(SharedWriteBackendTransactionImpl.class);
private final TableRefFactory tableRefFactory;
private final IdentifierFactory identifierFactory;
public SharedWriteBackendTransactionImpl(SqlInterface sqlInterface,
BackendConnectionImpl backendConnection,
TableRefFactory tableRefFactory,
IdentifierFactory identifierFactory) {
super(sqlInterface.getDbBackend().createWriteConnection(), sqlInterface, backendConnection);
this.identifierFactory = identifierFactory;
this.tableRefFactory = tableRefFactory;
}
IdentifierFactory getIdentifierFactory() {
return identifierFactory;
}
@Override
public void addDatabase(MetaDatabase db) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().addMetaDatabase(getDsl(), db);
getSqlInterface().getStructureInterface().createSchema(getDsl(), db.getIdentifier());
}
@Override
public void addCollection(MetaDatabase db, MetaCollection newCol) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().addMetaCollection(getDsl(), db, newCol);
TableRef rootTableRef = tableRefFactory.createRoot();
MetaDocPart newRootDocPart = newCol.getMetaDocPartByTableRef(rootTableRef);
if (newRootDocPart != null) {
getSqlInterface().getMetaDataWriteInterface().addMetaDocPart(getDsl(), db, newCol,
newRootDocPart);
getSqlInterface().getStructureInterface().createRootDocPartTable(getDsl(),
db.getIdentifier(), newRootDocPart.getIdentifier(), rootTableRef);
getSqlInterface().getStructureInterface().streamRootDocPartTableIndexesCreation(
db.getIdentifier(), newRootDocPart.getIdentifier(), rootTableRef)
.forEach(statement -> statement.apply(getDsl()));
}
}
@Override
public void dropCollection(MetaDatabase db, MetaCollection coll) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
dropMetaCollection(db, coll);
getSqlInterface().getStructureInterface().dropCollection(getDsl(), db.getIdentifier(), coll);
}
@Override
public void dropDatabase(MetaDatabase db) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
Iterator extends MetaCollection> metaCollectionIterator = db.streamMetaCollections()
.iterator();
while (metaCollectionIterator.hasNext()) {
MetaCollection metaCollection = metaCollectionIterator.next();
dropMetaCollection(db, metaCollection);
}
getSqlInterface().getMetaDataWriteInterface().deleteMetaDatabase(getDsl(), db);
getSqlInterface().getStructureInterface().dropDatabase(getDsl(), db);
}
protected void dropMetaCollection(MetaDatabase database, MetaCollection coll) {
getSqlInterface().getMetaDataWriteInterface().deleteMetaCollection(getDsl(), database, coll);
}
@Override
public void addDocPart(MetaDatabase db, MetaCollection col, MetaDocPart newDocPart) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().addMetaDocPart(getDsl(), db, col,
newDocPart);
TableRef tableRef = newDocPart.getTableRef();
if (tableRef.isRoot()) {
getSqlInterface().getStructureInterface().createRootDocPartTable(getDsl(), db.getIdentifier(),
newDocPart.getIdentifier(), tableRef);
getSqlInterface().getStructureInterface().streamRootDocPartTableIndexesCreation(db
.getIdentifier(), newDocPart.getIdentifier(), tableRef)
.forEach(consumer -> {
String index = consumer.apply(getDsl());
LOGGER.info("Created internal index {} for table {}", index,
newDocPart.getIdentifier());
});
} else {
getSqlInterface().getStructureInterface().createDocPartTable(getDsl(), db.getIdentifier(),
newDocPart.getIdentifier(), tableRef,
col.getMetaDocPartByTableRef(tableRef.getParent().get()).getIdentifier());
getSqlInterface().getStructureInterface()
.streamDocPartTableIndexesCreation(db.getIdentifier(), newDocPart.getIdentifier(),
tableRef,
col.getMetaDocPartByTableRef(tableRef.getParent().get()).getIdentifier())
.forEach(consumer -> {
String index = consumer.apply(getDsl());
LOGGER.info("Created internal index {} for table {}", index,
newDocPart.getIdentifier());
});
}
}
@Override
public void addField(MetaDatabase db, MetaCollection col, MutableMetaDocPart docPart,
MetaField newField) throws UserException {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().addMetaField(getDsl(), db, col, docPart,
newField);
getSqlInterface().getStructureInterface().addColumnToDocPartTable(getDsl(), db.getIdentifier(),
docPart.getIdentifier(), newField.getIdentifier(), getSqlInterface().getDataTypeProvider()
.getDataType(newField.getType()));
List>> missingIndexes = col.getMissingIndexesForNewField(docPart,
newField);
for (Tuple2> missingIndexEntry : missingIndexes) {
MetaIndex missingIndex = missingIndexEntry.v1();
List identifiers = missingIndexEntry.v2();
MutableMetaDocPartIndex docPartIndex = docPart
.getOrCreatePartialMutableDocPartIndexForMissingIndexAndNewField(
missingIndex, identifiers, newField);
if (missingIndex.isMatch(docPart, identifiers, docPartIndex)) {
List> columnList = new ArrayList<>(docPartIndex.size());
for (String identifier : identifiers) {
MetaDocPartIndexColumn docPartIndexColumn = docPartIndex
.getMetaDocPartIndexColumnByIdentifier(identifier);
columnList.add(new Tuple2<>(docPartIndexColumn.getIdentifier(), docPartIndexColumn
.getOrdering().isAscending()));
}
MetaIdentifiedDocPartIndex identifiedDocPartIndex = docPartIndex.immutableCopy(
identifierFactory.toIndexIdentifier(db, docPart.getIdentifier(), columnList));
getSqlInterface().getMetaDataWriteInterface()
.addMetaDocPartIndex(getDsl(), db, col, docPart, identifiedDocPartIndex);
for (String identifier : identifiers) {
MetaDocPartIndexColumn docPartIndexColumn = docPartIndex
.getMetaDocPartIndexColumnByIdentifier(identifier);
getSqlInterface().getMetaDataWriteInterface().addMetaDocPartIndexColumn(getDsl(), db, col,
docPart, identifiedDocPartIndex, docPartIndexColumn);
}
getSqlInterface().getStructureInterface().createIndex(getDsl(), identifiedDocPartIndex
.getIdentifier(), db.getIdentifier(),
docPart.getIdentifier(), columnList, docPartIndex.isUnique());
LOGGER.info("Created index {} for table {} associated to logical index {}.{}.{}",
identifiedDocPartIndex.getIdentifier(), docPart.getIdentifier(), db.getName(), col
.getName(), missingIndex.getName());
}
}
}
@Override
public void addScalar(MetaDatabase db, MetaCollection col, MetaDocPart docPart,
MetaScalar newScalar) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().addMetaScalar(getDsl(), db, col, docPart,
newScalar);
getSqlInterface().getStructureInterface().addColumnToDocPartTable(getDsl(), db.getIdentifier(),
docPart.getIdentifier(),
newScalar.getIdentifier(), getSqlInterface().getDataTypeProvider().getDataType(newScalar
.getType()));
}
@Override
public int consumeRids(MetaDatabase db, MetaCollection col, MetaDocPart docPart, int howMany) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
return getSqlInterface().getMetaDataWriteInterface().consumeRids(getDsl(), db, col, docPart,
howMany);
}
@Override
public void insert(MetaDatabase db, MetaCollection col, DocPartData data) throws UserException {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getWriteInterface().insertDocPartData(getDsl(), db.getIdentifier(), data);
}
@Override
public void deleteDids(MetaDatabase db, MetaCollection col, Collection dids) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
if (dids.isEmpty()) {
return;
}
getSqlInterface().getWriteInterface()
.deleteCollectionDocParts(getDsl(), db.getIdentifier(), col, dids);
}
@Override
public void createIndex(MetaDatabase db, MutableMetaCollection col, MetaIndex index) throws
UserException {
Preconditions.checkState(!isClosed(), "This transaction is closed");
Preconditions.checkArgument(!index.isUnique() || index.streamTableRefs().count() == 1,
"composed unique indexes on fields of different subdocuments are not supported yet");
getSqlInterface().getMetaDataWriteInterface().addMetaIndex(getDsl(), db, col, index);
Iterator extends MetaIndexField> indexFieldIterator = index.iteratorFields();
while (indexFieldIterator.hasNext()) {
MetaIndexField field = indexFieldIterator.next();
getSqlInterface().getMetaDataWriteInterface().addMetaIndexField(getDsl(), db, col, index,
field);
}
createMissingDocPartIndexes(db, col, index);
}
private void createIndex(MetaDatabase db, MetaCollection col, MetaIndex index,
MutableMetaDocPart docPart,
List identifiers) throws UserException {
MutableMetaDocPartIndex docPartIndex = docPart.addMetaDocPartIndex(index.isUnique());
Iterator extends MetaIndexField> indexFieldIterator = index.iteratorMetaIndexFieldByTableRef(
docPart.getTableRef());
int position = 0;
List> columnList = new ArrayList<>(identifiers.size());
for (String identifier : identifiers) {
MetaIndexField indexField = indexFieldIterator.next();
MetaDocPartIndexColumn docPartIndexColumn = docPartIndex.putMetaDocPartIndexColumn(position++,
identifier, indexField.getOrdering());
columnList.add(new Tuple2<>(docPartIndexColumn.getIdentifier(), docPartIndexColumn
.getOrdering().isAscending()));
}
MetaIdentifiedDocPartIndex identifiedDocPartIndex = docPartIndex.immutableCopy(identifierFactory
.toIndexIdentifier(db, docPart.getIdentifier(), columnList));
getSqlInterface().getMetaDataWriteInterface().addMetaDocPartIndex(getDsl(), db, col, docPart,
identifiedDocPartIndex);
for (String identifier : identifiers) {
MetaDocPartIndexColumn docPartIndexColumn = docPartIndex
.getMetaDocPartIndexColumnByIdentifier(identifier);
getSqlInterface().getMetaDataWriteInterface().addMetaDocPartIndexColumn(getDsl(), db, col,
docPart, identifiedDocPartIndex, docPartIndexColumn);
}
getSqlInterface().getStructureInterface().createIndex(
getDsl(), identifiedDocPartIndex.getIdentifier(), db.getIdentifier(), docPart
.getIdentifier(),
columnList, index.isUnique());
LOGGER.info("Created index {} for table {} associated to logical index {}.{}.{}",
identifiedDocPartIndex.getIdentifier(), docPart.getIdentifier(), db.getName(),
col.getName(), index.getName());
}
private void createMissingDocPartIndexes(MetaDatabase db, MutableMetaCollection col,
MetaIndex index) throws UserException {
Iterator tableRefIterator = index.streamTableRefs().iterator();
while (tableRefIterator.hasNext()) {
TableRef tableRef = tableRefIterator.next();
MutableMetaDocPart docPart = col.getMetaDocPartByTableRef(tableRef);
if (docPart != null && index.isCompatible(docPart)) {
Iterator> docPartIndexesFieldsIterator =
index.iteratorMetaDocPartIndexesIdentifiers(docPart);
while (docPartIndexesFieldsIterator.hasNext()) {
List identifiers = docPartIndexesFieldsIterator.next();
boolean containsExactDocPartIndex = docPart.streamIndexes()
.anyMatch(docPartIndex -> index.isMatch(docPart, identifiers, docPartIndex));
if (!containsExactDocPartIndex) {
createIndex(db, col, index, docPart, identifiers);
}
}
}
}
}
@Override
public void dropIndex(MetaDatabase db, MutableMetaCollection col, MetaIndex index) {
Preconditions.checkState(!isClosed(), "This transaction is closed");
getSqlInterface().getMetaDataWriteInterface().deleteMetaIndex(getDsl(), db, col, index);
Iterator tableRefIterator = index.streamTableRefs().iterator();
while (tableRefIterator.hasNext()) {
TableRef tableRef = tableRefIterator.next();
MutableMetaDocPart docPart = col.getMetaDocPartByTableRef(tableRef);
if (docPart != null) {
Iterator extends MetaIdentifiedDocPartIndex> docPartIndexesIterator =
docPart.streamIndexes().iterator();
while (docPartIndexesIterator.hasNext()) {
MetaIdentifiedDocPartIndex docPartIndex = docPartIndexesIterator.next();
if (index.isCompatible(docPart, docPartIndex)) {
boolean existsAnyOtherCompatibleIndex = col.streamContainedMetaIndexes()
.anyMatch(otherIndex -> otherIndex != index && otherIndex.isCompatible(docPart,
docPartIndex));
if (!existsAnyOtherCompatibleIndex) {
dropIndex(db, col, docPart, docPartIndex);
LOGGER.info("Dropped index {} for table {}", docPartIndex.getIdentifier(), docPart
.getIdentifier());
}
}
}
}
}
}
private void dropIndex(MetaDatabase db, MetaCollection col, MutableMetaDocPart docPart,
MetaIdentifiedDocPartIndex docPartIndex) {
docPart.removeMetaDocPartIndexByIdentifier(docPartIndex.getIdentifier());
getSqlInterface().getMetaDataWriteInterface().deleteMetaDocPartIndex(getDsl(), db, col, docPart,
docPartIndex);
getSqlInterface().getStructureInterface().dropIndex(
getDsl(), db.getIdentifier(), docPartIndex.getIdentifier());
}
@Override
public KvValue> writeMetaInfo(MetaInfoKey key, KvValue> newValue) {
return getBackendConnection().getMetaInfoHandler()
.writeMetaInfo(getDsl(), key, newValue);
}
@Override
public void commit() throws UserException, RollbackException {
Preconditions.checkState(!isClosed(), "This transaction is closed");
try {
getConnection().commit();
} catch (SQLException ex) {
getSqlInterface().getErrorHandler().handleUserException(Context.COMMIT, ex);
} finally {
getDsl().configuration().connectionProvider().release(getConnection());
}
}
}