Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/com/amazon/ion/benchmark/CountingOutputStream.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.amazon.ion.benchmark;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class CountingOutputStream extends FilterOutputStream {
private long count;

/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param out the underlying output stream to be assigned to
* the field <tt>this.out</tt> for later use, or
* <code>null</code> if this instance is to be
* created without an underlying stream.
*/
public CountingOutputStream(OutputStream out) {
super(out);
}

/** Returns the number of bytes written. */
public long getCount() {
return count;
}

@Override
public void write(byte[] b, int off, int len) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll also need to override public void write(int b) throws IOException.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll also need to override public void write(int b) throws IOException.

Right! My bad :( thanks for reminding. It will be resolved in the next commit.

out.write(b, off, len);
this.count += len;
}

@Override
public void write(int b) throws IOException {
out.write(b);
this.count++;
}
}
584 changes: 584 additions & 0 deletions src/com/amazon/ion/benchmark/DataConstructor.java

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/com/amazon/ion/benchmark/GeneratorOptions.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.amazon.ion.benchmark;

import com.amazon.ionschema.Schema;

import java.util.List;
import java.util.Map;
Expand All @@ -19,8 +20,8 @@ public static void executeGenerator(Map<String, Object> optionsMap) throws Excep
String format = ((List<String>) optionsMap.get("--format")).get(0);
String path = optionsMap.get("<output_file>").toString();
String inputFilePath = optionsMap.get("--input-ion-schema").toString();
// Check whether the input schema file is valid.
IonSchemaUtilities.checkValidationOfSchema(inputFilePath);
ReadGeneralConstraints.readIonSchemaAndGenerate(size, inputFilePath, format, path);
// Check whether the input schema file is valid and get the loaded schema.
Schema schema = IonSchemaUtilities.loadSchemaDefinition(inputFilePath);
ReadGeneralConstraints.constructAndWriteIonData(size, schema, format, path);
}
}
19 changes: 13 additions & 6 deletions src/com/amazon/ion/benchmark/IonSchemaUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import com.amazon.ionschema.InvalidSchemaException;
import com.amazon.ionschema.IonSchemaSystem;
import com.amazon.ionschema.IonSchemaSystemBuilder;
import com.amazon.ionschema.Schema;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -52,18 +54,23 @@ public class IonSchemaUtilities {
private static final IonLoader LOADER = SYSTEM.newLoader();

/**
* Check the validation of input ion schema file and will throw InvalidSchemaException message when an invalid schema definition is encountered.
* Load schema definition and check the validation of input ion schema file.
* If an invalid schema definition is encountered, this method will throw InvalidSchemaException message.
* @param inputFile represents the file path of the ion schema file.
* @throws Exception if an error occur when creating FileInputStream.
* @return schema loaded from input ISL file.
*/
public static void checkValidationOfSchema(String inputFile) throws Exception {
public static Schema loadSchemaDefinition(String inputFile) {
// Build ion schema system from input ISL file.
IonSchemaSystem ISS = buildIonSchemaSystem(inputFile);
String schemaID = inputFile.substring(inputFile.lastIndexOf('/') + 1);
// Get the name of ISL file as schema ID.
String schemaID = Paths.get(inputFile).toFile().getName();
// If the input ISL file is not validated by ion schema kotlin, it will throw an error.
// If the input ISL file is valid, the loaded schema will be returned.
try {
ISS.loadSchema(schemaID);
return ISS.loadSchema(schemaID);
} catch (InvalidSchemaException e) {
System.out.println(e.getMessage());
throw new Exception("The provided ion schema file is not valid");
throw new IllegalStateException("The provided ion schema file is not valid");
}
}

Expand Down
85 changes: 58 additions & 27 deletions src/com/amazon/ion/benchmark/ReadGeneralConstraints.java
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
package com.amazon.ion.benchmark;

import com.amazon.ion.IonDatagram;
import com.amazon.ion.IonLoader;
import com.amazon.ion.IonReader;
import com.amazon.ion.IonStruct;
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonType;
import com.amazon.ion.IonValue;
import com.amazon.ion.IonWriter;
import com.amazon.ion.system.IonReaderBuilder;
import com.amazon.ion.benchmark.schema.ReparsedType;
import com.amazon.ion.system.IonBinaryWriterBuilder;
import com.amazon.ion.system.IonSystemBuilder;
import com.amazon.ion.system.IonTextWriterBuilder;
import com.amazon.ionschema.Schema;
import com.amazon.ionschema.Type;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
* Parse Ion Schema file and get the general constraints in the file then pass the constraints to the Ion data generator.
* Parse Ion Schema file and extract the type definition as ReparsedType object then pass the re-parsed type definition to the Ion data generator.
*/
public class ReadGeneralConstraints {
public static final IonSystem SYSTEM = IonSystemBuilder.standard().build();
public static final IonLoader LOADER = SYSTEM.newLoader();

/**
* Get general constraints of Ion Schema and call the relevant generator method based on the type.
* Getting the constructed data which is conformed with ISL and writing data to the output file.
* @param size is the size of the output file.
* @param path is the path of the Ion Schema file.
* @param schema an Ion Schema loaded by ion-schema-kotlin.
* @param format is the format of the generated file, select from set (ion_text | ion_binary).
* @param outputFile is the path of the generated file.
* @throws Exception if errors occur when reading and writing data.
* @throws Exception if errors occur when writing data.
*/
public static void readIonSchemaAndGenerate(int size, String path, String format, String outputFile) throws Exception {
try (IonReader reader = IonReaderBuilder.standard().build(new BufferedInputStream(new FileInputStream(path)))) {
IonDatagram schema = LOADER.load(reader);
for (int i = 0; i < schema.size(); i++) {
IonValue schemaValue = schema.get(i);
// Assume there's only one constraint between schema_header and schema_footer, if more constraints added, here is the point where developers should start.
if (schemaValue.getType().equals(IonType.STRUCT) && schemaValue.getTypeAnnotations()[0].equals(IonSchemaUtilities.KEYWORD_TYPE)) {
IonStruct constraintStruct = (IonStruct) schemaValue;
//Construct the writer and pass the constraints to the following writing data to files process.
File file = new File(outputFile);
try (IonWriter writer = WriteRandomIonValues.formatWriter(format, file)) {
WriteRandomIonValues.writeRequestedSizeFile(size, writer, file, constraintStruct);
}
// Print the successfully generated data notification which includes the file path information.
WriteRandomIonValues.printInfo(outputFile);
public static void constructAndWriteIonData(int size, Schema schema, String format, String outputFile) throws Exception {
// Assume there's only one type definition between schema_header and schema_footer.
// If more constraints added, here is the point where developers should start.
Type schemaType = schema.getTypes().next();
ReparsedType parsedTypeDefinition = new ReparsedType(schemaType);
CountingOutputStream outputStreamCounter = new CountingOutputStream(new FileOutputStream(outputFile));
try (IonWriter writer = formatWriter(format, outputStreamCounter)) {
int count = 0;
long currentSize = 0;
// Determine how many values should be written before the writer.flush(), and this process aims to reduce the execution time of writer.flush().
while (currentSize <= 0.05 * size) {
IonValue constructedData = DataConstructor.constructIonData(parsedTypeDefinition);
constructedData.writeTo(writer);
count ++;
writer.flush();
currentSize = outputStreamCounter.getCount();
}
while (currentSize <= size) {
for (int i = 0; i < count; i++) {
IonValue constructedData = DataConstructor.constructIonData(parsedTypeDefinition);
constructedData.writeTo(writer);
}
writer.flush();
currentSize = outputStreamCounter.getCount();
}
}
// Print the successfully generated data notification which includes the file path information.
DataConstructor.printInfo(outputFile);
}

/**
* Construct the writer based on the provided format (ion_text|ion_binary).
* @param format decides which writer should be constructed.
* @param outputStream represents the bytes stream which will be written into the output file.
* @return the writer which conforms with the required format.
*/
public static IonWriter formatWriter(String format, OutputStream outputStream) {
IonWriter writer;
Format formatName = Format.valueOf(format.toUpperCase());
switch (formatName) {
case ION_BINARY:
writer = IonBinaryWriterBuilder.standard().withLocalSymbolTableAppendEnabled().build(outputStream);
break;
case ION_TEXT:
writer = IonTextWriterBuilder.standard().build(outputStream);
break;
default:
throw new IllegalStateException("Please input the format ion_text or ion_binary");
}
return writer;
}
}
Loading