blob: d0e5a423cdc97a07ca0cf4ef426f69eedfee3b30 [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.carbondata.core.metadata.schema.table;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.carbondata.common.exceptions.sql.NoSuchDataMapException;
import org.apache.carbondata.core.constants.CarbonCommonConstants;
import org.apache.carbondata.core.datastore.filesystem.CarbonFile;
import org.apache.carbondata.core.datastore.filesystem.CarbonFileFilter;
import org.apache.carbondata.core.datastore.impl.FileFactory;
import org.apache.carbondata.core.util.CarbonUtil;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
/**
* Stores datamap schema in disk as json format
*/
public class DiskBasedDMSchemaStorageProvider implements DataMapSchemaStorageProvider {
private String storePath;
private String mdtFilePath;
private long lastModifiedTime;
private Set<DataMapSchema> dataMapSchemas = new HashSet<>();
public DiskBasedDMSchemaStorageProvider(String storePath) {
this.storePath = CarbonUtil.checkAndAppendHDFSUrl(storePath);
this.mdtFilePath = storePath + CarbonCommonConstants.FILE_SEPARATOR + "datamap.mdtfile";
}
@Override
public void saveSchema(DataMapSchema dataMapSchema) throws IOException {
BufferedWriter brWriter = null;
DataOutputStream dataOutputStream = null;
Gson gsonObjectToWrite = new Gson();
String schemaPath = getSchemaPath(storePath, dataMapSchema.getDataMapName());
if (FileFactory.isFileExist(schemaPath)) {
throw new IOException(
"DataMap with name " + dataMapSchema.getDataMapName() + " already exists in storage");
}
// write the datamap shema in json format.
try {
FileFactory.mkdirs(storePath);
FileFactory.createNewFile(schemaPath);
dataOutputStream =
FileFactory.getDataOutputStream(schemaPath);
brWriter = new BufferedWriter(new OutputStreamWriter(dataOutputStream,
Charset.forName(CarbonCommonConstants.DEFAULT_CHARSET)));
String metadataInstance = gsonObjectToWrite.toJson(dataMapSchema);
brWriter.write(metadataInstance);
} finally {
if (null != brWriter) {
brWriter.flush();
}
dataMapSchemas.add(dataMapSchema);
CarbonUtil.closeStreams(dataOutputStream, brWriter);
checkAndReloadDataMapSchemas(true);
touchMDTFile();
}
}
@Override
public DataMapSchema retrieveSchema(String dataMapName)
throws IOException, NoSuchDataMapException {
checkAndReloadDataMapSchemas(true);
for (DataMapSchema dataMapSchema : dataMapSchemas) {
if (dataMapSchema.getDataMapName().equalsIgnoreCase(dataMapName)) {
return dataMapSchema;
}
}
throw new NoSuchDataMapException(dataMapName);
}
@Override
public List<DataMapSchema> retrieveSchemas(CarbonTable carbonTable) throws IOException {
checkAndReloadDataMapSchemas(false);
List<DataMapSchema> dataMapSchemas = new ArrayList<>();
for (DataMapSchema dataMapSchema : this.dataMapSchemas) {
List<RelationIdentifier> parentTables = dataMapSchema.getParentTables();
for (RelationIdentifier identifier : parentTables) {
if (StringUtils.isNotEmpty(identifier.getTableId())) {
if (identifier.getTableId().equalsIgnoreCase(carbonTable.getTableId())) {
dataMapSchemas.add(dataMapSchema);
break;
}
} else if (identifier.getTableName().equalsIgnoreCase(carbonTable.getTableName()) &&
identifier.getDatabaseName().equalsIgnoreCase(carbonTable.getDatabaseName())) {
dataMapSchemas.add(dataMapSchema);
break;
}
}
}
return dataMapSchemas;
}
@Override
public List<DataMapSchema> retrieveAllSchemas() throws IOException {
checkAndReloadDataMapSchemas(true);
return new ArrayList<>(dataMapSchemas);
}
private Set<DataMapSchema> retrieveAllSchemasInternal() throws IOException {
Set<DataMapSchema> dataMapSchemas = new HashSet<>();
CarbonFile carbonFile = FileFactory.getCarbonFile(storePath);
CarbonFile[] carbonFiles = carbonFile.listFiles(new CarbonFileFilter() {
@Override
public boolean accept(CarbonFile file) {
return file.getName().endsWith(".dmschema");
}
});
for (CarbonFile file :carbonFiles) {
Gson gsonObjectToRead = new Gson();
DataInputStream dataInputStream = null;
BufferedReader buffReader = null;
InputStreamReader inStream = null;
try {
String absolutePath = file.getAbsolutePath();
dataInputStream =
FileFactory.getDataInputStream(
absolutePath);
inStream = new InputStreamReader(dataInputStream,
Charset.forName(CarbonCommonConstants.DEFAULT_CHARSET));
buffReader = new BufferedReader(inStream);
dataMapSchemas.add(gsonObjectToRead.fromJson(buffReader, DataMapSchema.class));
} finally {
CarbonUtil.closeStreams(buffReader, inStream, dataInputStream);
}
}
return dataMapSchemas;
}
@Override
public void dropSchema(String dataMapName)
throws IOException {
String schemaPath = getSchemaPath(storePath, dataMapName);
if (!FileFactory.isFileExist(schemaPath)) {
throw new IOException("DataMap with name " + dataMapName + " does not exists in storage");
}
Iterator<DataMapSchema> iterator = dataMapSchemas.iterator();
while (iterator.hasNext()) {
DataMapSchema schema = iterator.next();
if (schema.getDataMapName().equalsIgnoreCase(dataMapName)) {
iterator.remove();
}
}
touchMDTFile();
if (!FileFactory.deleteFile(schemaPath)) {
throw new IOException("DataMap with name " + dataMapName + " cannot be deleted");
}
}
private void checkAndReloadDataMapSchemas(boolean touchFile) throws IOException {
if (FileFactory.isFileExist(mdtFilePath)) {
long lastModifiedTime = FileFactory.getCarbonFile(mdtFilePath).getLastModifiedTime();
if (this.lastModifiedTime != lastModifiedTime) {
dataMapSchemas = retrieveAllSchemasInternal();
touchMDTFile();
}
} else {
dataMapSchemas = retrieveAllSchemasInternal();
if (touchFile) {
touchMDTFile();
}
}
}
private void touchMDTFile() throws IOException {
if (!FileFactory.isFileExist(storePath)) {
FileFactory.createDirectoryAndSetPermission(
storePath,
new FsPermission(FsAction.ALL, FsAction.ALL, FsAction.ALL));
}
if (!FileFactory.isFileExist(mdtFilePath)) {
FileFactory.createNewFile(
mdtFilePath,
new FsPermission(FsAction.ALL, FsAction.ALL, FsAction.ALL));
}
long lastModifiedTime = System.currentTimeMillis();
FileFactory.getCarbonFile(mdtFilePath).setLastModifiedTime(lastModifiedTime);
this.lastModifiedTime = lastModifiedTime;
}
/**
* it returns the schema path for the datamap
* @param storePath
* @param dataMapName
* @return
*/
public static String getSchemaPath(String storePath, String dataMapName) {
String schemaPath = storePath + CarbonCommonConstants.FILE_SEPARATOR + dataMapName
+ ".dmschema";
return schemaPath;
}
}