/**
* 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.hadoop.zebra.types;
import java.io.IOException;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.permission.*;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.WritableUtils;
import org.apache.hadoop.zebra.tfile.Utils.Version;
import org.apache.hadoop.zebra.schema.Schema;
import org.apache.hadoop.zebra.parser.ParseException;
/**
* ColumnGroup Schema. This object is first written to a schema file when the
* ColumnGroup is initially created, and is used to communicate meta
* information among writers.
*/
public class CGSchema {
private Version version;
private boolean sorted;
private String comparator;
private Schema schema;
private String name = null;
private String compressor = "lzo";
private String serializer = "pig";
private String group = null;
private String owner = null;
private short perm = -1;
// tmp schema file name, used as a flag of unfinished CG
private final static String SCHEMA_FILE = ".schema";
// schema version, should be same as BasicTable's most of the time
private final static Version SCHEMA_VERSION =
new Version((short) 1, (short) 1);
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{Name = ");
sb.append(name);
sb.append("}\n");
sb.append("{Compressor = ");
sb.append(compressor);
sb.append("}\n");
sb.append("{Serializer = ");
sb.append(serializer);
sb.append("}\n");
sb.append(schema.toString());
return sb.toString();
}
public static Path makeFilePath(Path parent) {
return new Path(parent, SCHEMA_FILE);
}
public static CGSchema load(FileSystem fs, Path parent) throws IOException, ParseException {
if (!exists(fs, parent)) return null;
CGSchema ret = new CGSchema();
ret.read(fs, parent);
return ret;
}
public CGSchema() {
this.version = SCHEMA_VERSION;
}
public CGSchema(Schema schema, boolean sorted, String comparator) {
this.sorted = sorted;
this.comparator = (sorted) ? (comparator == null ? SortInfo.DEFAULT_COMPARATOR : comparator) : "";
this.schema = schema;
this.version = SCHEMA_VERSION;
}
public CGSchema(Schema schema, boolean sorted, String comparator, String name, String serializer, String compressor, String owner, String group, short perm) {
this(schema, sorted, comparator);
this.name = name;
this.serializer = serializer;
this.compressor = compressor;
this.group = group;
this.perm = perm;
}
@Override
public boolean equals(Object obj) {
CGSchema other = (CGSchema) obj;
return this.sorted == other.sorted
&& this.comparator.equals(other.comparator)
&& this.schema.equals(other.schema);
}
public static boolean exists(FileSystem fs, Path parent) {
try {
return fs.exists(makeFilePath(parent));
}
catch (IOException e) {
return false;
}
}
public static void drop(FileSystem fs, Path parent) throws IOException {
fs.delete(makeFilePath(parent), true);
}
public boolean isSorted() {
return sorted;
}
public String getComparator() {
return comparator;
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public String getSerializer() {
return serializer;
}
public String getCompressor() {
return compressor;
}
public String getGroup() {
return this.group;
}
public short getPerm() {
return this.perm;
}
public String getOwner() {
return this.owner;
}
public void create(FileSystem fs, Path parent) throws IOException {
fs.mkdirs(parent);
if(this.owner != null || this.group != null) {
fs.setOwner(parent, this.owner, this.group);
}
if(this.perm != -1) {
fs.setPermission(parent, new FsPermission((short) this.perm));
}
FSDataOutputStream outSchema = fs.create(makeFilePath(parent), false);
if(this.owner != null || this.group != null) {
fs.setOwner(makeFilePath(parent), owner, group);
}
if(this.perm != -1) {
fs.setPermission(makeFilePath(parent), new FsPermission((short) this.perm));
}
version.write(outSchema);
WritableUtils.writeString(outSchema, schema.toString());
WritableUtils.writeVInt(outSchema, sorted ? 1 : 0);
WritableUtils.writeString(outSchema, comparator);
WritableUtils.writeString(outSchema, this.getCompressor());
WritableUtils.writeString(outSchema, this.getSerializer());
WritableUtils.writeString(outSchema, this.getGroup());
WritableUtils.writeVInt(outSchema, this.getPerm());
WritableUtils.writeString(outSchema, name);
outSchema.close();
}
public void read(FileSystem fs, Path parent) throws IOException, ParseException {
FSDataInputStream in = fs.open(makeFilePath(parent));
version = new Version(in);
// verify compatibility against SCHEMA_VERSION
if (!version.compatibleWith(SCHEMA_VERSION)) {
new IOException("Incompatible versions, expecting: " + SCHEMA_VERSION
+ "; found in file: " + version);
}
name = parent.getName();
String s = WritableUtils.readString(in);
schema = new Schema(s);
sorted = WritableUtils.readVInt(in) == 1 ? true : false;
comparator = WritableUtils.readString(in);
// V2 table;
if(version.compareTo(SCHEMA_VERSION) >= 0) {
compressor = WritableUtils.readString(in);
serializer = WritableUtils.readString(in);
owner = null;
group = WritableUtils.readString(in);
perm = (short) WritableUtils.readVInt(in);
name = WritableUtils.readString(in);
}
in.close();
}
public Schema getSchema() {
return schema;
}
}