/*
* Copyright 2012 NGDATA nv
*
* Licensed 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.lilyproject.tools.tester;
import java.io.IOException;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.codehaus.jackson.JsonNode;
import org.lilyproject.repository.api.Link;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.Record;
import org.lilyproject.repository.api.RecordId;
import org.lilyproject.tools.import_.json.QNameConverter;
import org.lilyproject.util.json.JsonFormatException;
import org.lilyproject.util.json.JsonUtil;
public class CreateAction extends AbstractTestAction implements TestAction {
private TestRecordType recordTypeToCreate;
private static final byte[] MAC_ADDRESS;
static {
byte[] macAddress = null;
try {
for (Iterator<NetworkInterface> iterator =
Collections.list(NetworkInterface.getNetworkInterfaces()).iterator();
iterator.hasNext() && macAddress == null; ) {
macAddress = iterator.next().getHardwareAddress();
}
} catch (IOException e) {
throw new IllegalStateException("failed to initialize localhost mac address", e);
}
if (macAddress == null) {
throw new IllegalStateException("failed to initialize localhost mac address");
}
MAC_ADDRESS = macAddress;
}
public CreateAction(JsonNode actionNode, TestActionContext testActionContext) throws JsonFormatException,
org.lilyproject.tools.import_.json.JsonFormatException {
super(actionNode, testActionContext);
recordTypeToCreate = testActionContext.recordTypes.get(QNameConverter.fromJson(
JsonUtil.getString(actionNode, "recordType"), testActionContext.nameSpaces));
}
@Override
protected void runAction() {
ActionResult result = createRecord(recordTypeToCreate);
report(result.success, result.duration);
if (result.success) {
testActionContext.records.addRecord(destination, new TestRecord(((Record)result.object).getId(),
recordTypeToCreate));
}
}
private ActionResult createRecord(TestRecordType recordTypeToCreate) {
double duration = 0;
Record record;
if (testActionContext.roundRobinPrefixGenerator == null) {
record = testActionContext.repository.getRecordFactory().newRecord();
} else {
record = testActionContext.repository.getRecordFactory().newRecord(createPrefixedRecordId());
}
// Prepare record by generating values for the fields
record.setRecordType(recordTypeToCreate.getRecordType().getName());
List<TestFieldType> fieldTypesToCreate = recordTypeToCreate.getFieldTypes();
for (TestFieldType testFieldType : fieldTypesToCreate) {
QName fieldQName = testFieldType.getFieldType().getName();
ActionResult result = testFieldType.generateValue(this);
duration += result.duration;
if (!result.success) {
return new ActionResult(false, null, duration);
}
record.setField(fieldQName, result.object);
}
// Perform the actual creation of the record on the repository
boolean success;
long before = System.nanoTime();
long createDuration = 0;
try {
record = testActionContext.table.create(record);
createDuration = System.nanoTime() - before;
success = true;
} catch (Throwable t) {
createDuration = System.nanoTime() - before;
reportError("Error creating record.", t);
success = false;
}
report(success, createDuration, "C", "repoCreate." + recordTypeToCreate.getRecordType().getName().getName());
duration += createDuration;
return new ActionResult(success, record, duration);
}
private RecordId createPrefixedRecordId() {
final StringBuilder recordId = new StringBuilder();
recordId.append(testActionContext.roundRobinPrefixGenerator.next());
recordId.append(System.currentTimeMillis());
for (byte part : MAC_ADDRESS) {
recordId.append(String.format("%02X", part));
}
return testActionContext.repository.getIdGenerator().newRecordId(recordId.toString());
}
@Override
public ActionResult linkFieldAction(TestFieldType testFieldType, RecordId recordId) {
String linkedRecordSource = testFieldType.getLinkedRecordSource();
// Pick a link from the RecordSpace source
if (linkedRecordSource != null) {
TestRecord record = testActionContext.records.getRecord(linkedRecordSource);
if (record == null) {
return new ActionResult(false, null, 0);
}
return new ActionResult(true, new Link(record.getRecordId()), 0);
}
// Create a record of the specified RecordType
String linkedRecordTypeName = testFieldType.getLinkedRecordTypeName();
if (linkedRecordTypeName != null) {
TestRecordType linkedRecordType;
try {
linkedRecordType = testActionContext.recordTypes.get(QNameConverter.fromJson(linkedRecordTypeName,
testActionContext.nameSpaces));
} catch (org.lilyproject.tools.import_.json.JsonFormatException e) {
throw new RuntimeException("Error creating link field", e);
}
ActionResult result = createRecord(linkedRecordType);
report(result.success, result.duration,
"linkCreate." + linkedRecordType.getRecordType().getName().getName());
if (!result.success) {
return new ActionResult(false, null, 0);
}
return new ActionResult(true, new Link(((Record) result.object).getId()), result.duration);
}
// Generate a link that possibly (most likely) points to a non-existing record
return new ActionResult(true, testFieldType.generateLink(), 0);
}
}