/* * 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.util.ArrayList; 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.JsonFormatException; import org.lilyproject.tools.import_.json.QNameConverter; import org.lilyproject.util.json.JsonUtil; public class UpdateAction extends AbstractTestAction implements TestAction { private String pattern; private String patternDetail; public UpdateAction(JsonNode actionNode, TestActionContext testActionContext) { super(actionNode, testActionContext); pattern = JsonUtil.getString(actionNode, "pattern", "all"); patternDetail = JsonUtil.getString(actionNode, "patternDetail", null); } @Override protected void runAction() { TestRecord testRecord = testActionContext.records.getRecord(source); if (testRecord == null) { return; } TestRecordType recordTypeToUpdate = testRecord.getRecordType(); RecordId recordId = testRecord.getRecordId(); ActionResult result = updateRecord(recordTypeToUpdate, recordId); report(result.success, result.duration, "U", null); if (result.success) { testActionContext.records.addRecord(destination, new TestRecord(((Record)result.object).getId(), recordTypeToUpdate)); } } private ActionResult updateRecord(TestRecordType recordTypeToUpdate, RecordId recordId) { double duration = 0; long before = 0; List<TestFieldType> fieldsToUpdate = new ArrayList<TestFieldType>(); // Select x random fields to update if ("random".equals(pattern)) { List<TestFieldType> recordFields = recordTypeToUpdate.getFieldTypes(); for (int i = 0; i < Integer.valueOf(patternDetail); i++) { int selectedField = (int) Math.floor(Math.random() * recordFields.size()); fieldsToUpdate.add(recordFields.get(selectedField)); } // Select specified fields to update } else if ("fields".equals(pattern)) { String[] fieldNames = patternDetail.split(","); List<QName> fieldQNames = new ArrayList<QName>(fieldNames.length); for (String fieldName: fieldNames) { try { fieldQNames.add(QNameConverter.fromJson(fieldName, testActionContext.nameSpaces)); } catch (JsonFormatException e) { throw new RuntimeException("Error updating record", e); } } for (TestFieldType testFieldType : recordTypeToUpdate.getFieldTypes()) { if (fieldQNames.contains(testFieldType.getFieldType().getName())) { fieldsToUpdate.add(testFieldType); } } } // Update all fields else { fieldsToUpdate.addAll(recordTypeToUpdate.getFieldTypes()); } Record record = testActionContext.repository.getRecordFactory().newRecord(recordId); // If there is a Link-field that links to specified record type we need to read the field // in order to update the record that is linked to boolean readRecord = false; for (TestFieldType field: fieldsToUpdate) { if (field.getLinkedRecordTypeName() != null || field.getLinkedRecordSource() != null) { readRecord = true; break; } } Record originalRecord = null; if (readRecord) { before = System.nanoTime(); try { originalRecord = testActionContext.table.read(record.getId()); long readDuration = System.nanoTime() - before; report(true, readDuration, "repoRead"); duration += readDuration; } catch (Throwable t) { long readDuration = System.nanoTime() - before; report(false, readDuration, "readLinkFields"); reportError("Error updating subrecord.", t); duration += readDuration; return new ActionResult(false, null, duration); } } // Prepare the record with updated field values for (TestFieldType testFieldType : fieldsToUpdate) { ActionResult result = testFieldType.updateValue(this, originalRecord); duration += result.duration; if (!result.success) { return new ActionResult(false, null, duration); } // In case of a link field to a specific recordType we only update that record, but not the link itself if (result.object != null) { record.setField(testFieldType.fieldType.getName(), result.object); } } boolean success; before = System.nanoTime(); long updateDuration = 0; try { record = testActionContext.table.update(record); updateDuration = System.nanoTime() - before; success = true; } catch (Throwable t) { updateDuration = System.nanoTime() - before; success = false; reportError("Error updating record.", t); } duration += updateDuration; report(success, updateDuration, "repoUpdate."+recordTypeToUpdate.getRecordType().getName().getName()); return new ActionResult(success, record, duration); } @Override public ActionResult linkFieldAction(TestFieldType testFieldType, RecordId recordId) { double duration = 0; String linkedRecordSource = testFieldType.getLinkedRecordSource(); // Update the record where the link points to String linkedRecordTypeName = testFieldType.getLinkedRecordTypeName(); if (linkedRecordTypeName != null) { TestRecordType linkedRecordType; try { linkedRecordType = testActionContext.recordTypes.get(QNameConverter.fromJson(linkedRecordTypeName, testActionContext.nameSpaces)); } catch (JsonFormatException e) { throw new RuntimeException("Error updating link field", e); } ActionResult result = updateRecord(linkedRecordType, recordId); report(result.success, result.duration, "linkUpdate."+linkedRecordType.getRecordType().getName().getName()); duration += result.duration; if (!result.success) { return new ActionResult(false, null, duration); } // We updated the record that was linked to but not the linkfield itself. So we return null in the ActionResult. return new ActionResult(true, null, duration); } // 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); } // Generate a link that possibly (most likely) points to a non-existing record return new ActionResult(true, testFieldType.generateLink(), 0); } }