Search in sources :

Example 21 with ORecordOperation

use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.

the class OTransactionOptimistic method addRecord.

public void addRecord(final ORecord iRecord, final byte iStatus, final String iClusterName) {
    checkTransaction();
    if (iStatus != ORecordOperation.LOADED)
        changedDocuments.remove(iRecord);
    try {
        switch(iStatus) {
            case ORecordOperation.CREATED:
                {
                    database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_CREATE, iClusterName);
                    RESULT res = database.callbackHooks(TYPE.BEFORE_CREATE, iRecord);
                    if (res == RESULT.RECORD_CHANGED && iRecord instanceof ODocument)
                        ((ODocument) iRecord).validate();
                }
                break;
            case ORecordOperation.LOADED:
                /**
         * Read hooks already invoked in {@link com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx#executeReadRecord}
         */
                break;
            case ORecordOperation.UPDATED:
                {
                    database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_UPDATE, iClusterName);
                    RESULT res = database.callbackHooks(TYPE.BEFORE_UPDATE, iRecord);
                    if (res == RESULT.RECORD_CHANGED && iRecord instanceof ODocument)
                        ((ODocument) iRecord).validate();
                }
                break;
            case ORecordOperation.DELETED:
                database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_DELETE, iClusterName);
                database.callbackHooks(TYPE.BEFORE_DELETE, iRecord);
                break;
        }
        try {
            final ORecordId rid = (ORecordId) iRecord.getIdentity();
            if (!rid.isValid()) {
                ORecordInternal.onBeforeIdentityChanged(iRecord);
                database.assignAndCheckCluster(iRecord, iClusterName);
                rid.setClusterPosition(newObjectCounter--);
                ORecordInternal.onAfterIdentityChanged(iRecord);
            }
            ORecordOperation txEntry = getRecordEntry(rid);
            if (txEntry == null) {
                if (!(rid.isTemporary() && iStatus != ORecordOperation.CREATED)) {
                    // NEW ENTRY: JUST REGISTER IT
                    txEntry = new ORecordOperation(iRecord, iStatus);
                    allEntries.put(rid.copy(), txEntry);
                }
            } else {
                // UPDATE PREVIOUS STATUS
                txEntry.record = iRecord;
                switch(txEntry.type) {
                    case ORecordOperation.LOADED:
                        switch(iStatus) {
                            case ORecordOperation.UPDATED:
                                txEntry.type = ORecordOperation.UPDATED;
                                break;
                            case ORecordOperation.DELETED:
                                txEntry.type = ORecordOperation.DELETED;
                                break;
                        }
                        break;
                    case ORecordOperation.UPDATED:
                        switch(iStatus) {
                            case ORecordOperation.DELETED:
                                txEntry.type = ORecordOperation.DELETED;
                                break;
                        }
                        break;
                    case ORecordOperation.DELETED:
                        break;
                    case ORecordOperation.CREATED:
                        switch(iStatus) {
                            case ORecordOperation.DELETED:
                                allEntries.remove(rid);
                                // txEntry.type = ORecordOperation.DELETED;
                                break;
                        }
                        break;
                }
            }
            switch(iStatus) {
                case ORecordOperation.CREATED:
                    database.callbackHooks(TYPE.AFTER_CREATE, iRecord);
                    break;
                case ORecordOperation.LOADED:
                    /**
           * Read hooks already invoked in
           * {@link com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx#executeReadRecord} .
           */
                    break;
                case ORecordOperation.UPDATED:
                    database.callbackHooks(TYPE.AFTER_UPDATE, iRecord);
                    break;
                case ORecordOperation.DELETED:
                    database.callbackHooks(TYPE.AFTER_DELETE, iRecord);
                    break;
            }
            // RESET TRACKING
            if (iRecord instanceof ODocument && ((ODocument) iRecord).isTrackingChanges()) {
                ODocumentInternal.clearTrackData(((ODocument) iRecord));
            }
        } catch (Exception e) {
            switch(iStatus) {
                case ORecordOperation.CREATED:
                    database.callbackHooks(TYPE.CREATE_FAILED, iRecord);
                    break;
                case ORecordOperation.UPDATED:
                    database.callbackHooks(TYPE.UPDATE_FAILED, iRecord);
                    break;
                case ORecordOperation.DELETED:
                    database.callbackHooks(TYPE.DELETE_FAILED, iRecord);
                    break;
            }
            throw OException.wrapException(new ODatabaseException("Error on saving record " + iRecord.getIdentity()), e);
        }
    } finally {
        switch(iStatus) {
            case ORecordOperation.CREATED:
                database.callbackHooks(TYPE.FINALIZE_CREATION, iRecord);
                break;
            case ORecordOperation.UPDATED:
                database.callbackHooks(TYPE.FINALIZE_UPDATE, iRecord);
                break;
            case ORecordOperation.DELETED:
                database.callbackHooks(TYPE.FINALIZE_DELETION, iRecord);
                break;
        }
    }
}
Also used : ORecordOperation(com.orientechnologies.orient.core.db.record.ORecordOperation) ODatabaseException(com.orientechnologies.orient.core.exception.ODatabaseException) RESULT(com.orientechnologies.orient.core.hook.ORecordHook.RESULT) ORecordId(com.orientechnologies.orient.core.id.ORecordId) OException(com.orientechnologies.common.exception.OException) OStorageException(com.orientechnologies.orient.core.exception.OStorageException) ORecordNotFoundException(com.orientechnologies.orient.core.exception.ORecordNotFoundException) OTransactionException(com.orientechnologies.orient.core.exception.OTransactionException) ODatabaseException(com.orientechnologies.orient.core.exception.ODatabaseException) ODocument(com.orientechnologies.orient.core.record.impl.ODocument)

Example 22 with ORecordOperation

use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.

the class OLiveQueryTest method testLiveInsertOnCluster.

@Test
public void testLiveInsertOnCluster() {
    ODatabaseDocumentTx db = new ODatabaseDocumentTx("memory:OLiveQueryTest");
    db.activateOnCurrentThread();
    db.create();
    try {
        OClass clazz = db.getMetadata().getSchema().createClass("test");
        int defaultCluster = clazz.getDefaultClusterId();
        OCluster cluster = db.getStorage().getClusterById(defaultCluster);
        MyLiveQueryListener listener = new MyLiveQueryListener();
        db.query(new OLiveQuery<ODocument>("live select from cluster:" + cluster.getName(), listener));
        db.command(new OCommandSQL("insert into cluster:" + cluster.getName() + " set name = 'foo', surname = 'bar'")).execute();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Assert.assertEquals(listener.ops.size(), 1);
        for (ORecordOperation doc : listener.ops) {
            Assert.assertEquals(doc.type, ORecordOperation.CREATED);
            Assert.assertEquals(((ODocument) doc.record).field("name"), "foo");
        }
    } finally {
        db.drop();
    }
}
Also used : ORecordOperation(com.orientechnologies.orient.core.db.record.ORecordOperation) OClass(com.orientechnologies.orient.core.metadata.schema.OClass) ODatabaseDocumentTx(com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx) OCluster(com.orientechnologies.orient.core.storage.OCluster) ODocument(com.orientechnologies.orient.core.record.impl.ODocument) Test(org.testng.annotations.Test)

Example 23 with ORecordOperation

use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.

the class ODistributedTransactionManager method processCommitResult.

protected boolean processCommitResult(final String localNodeName, final OTransaction iTx, final OTxTask txTask, final Set<String> involvedClusters, final Iterable<ORecordOperation> tmpEntries, final Collection<String> nodes, final int autoRetryDelay, final ODistributedRequestId reqId, final ODistributedResponse dResponse, final boolean isLastRetry) throws InterruptedException {
    final Object result = dResponse.getPayload();
    if (result instanceof OTxTaskResult) {
        final OTxTaskResult txResult = (OTxTaskResult) result;
        final List<Object> list = txResult.results;
        for (int i = 0; i < txTask.getTasks().size(); ++i) {
            final Object o = list.get(i);
            final OAbstractRecordReplicatedTask task = txTask.getTasks().get(i);
            if (task instanceof OCreateRecordTask) {
                final OCreateRecordTask t = (OCreateRecordTask) task;
                iTx.updateIdentityAfterCommit(t.getRid(), ((OPlaceholder) o).getIdentity());
                final ORecord rec = iTx.getRecord(t.getRid());
                if (rec != null)
                    ORecordInternal.setVersion(rec, ((OPlaceholder) o).getVersion());
            } else if (task instanceof OUpdateRecordTask) {
                final OUpdateRecordTask t = (OUpdateRecordTask) task;
                ORecordInternal.setVersion(iTx.getRecord(t.getRid()), (Integer) o);
            } else if (task instanceof ODeleteRecordTask) {
            }
        }
        // RESET DIRTY FLAGS TO AVOID CALLING AUTO-SAVE
        for (ORecordOperation op : tmpEntries) {
            final ORecord record = op.getRecord();
            if (record != null)
                ORecordInternal.unsetDirty(record);
        }
        if (ODistributedServerLog.isDebugEnabled())
            ODistributedServerLog.debug(this, localNodeName, null, ODistributedServerLog.DIRECTION.NONE, "Distributed transaction %s completed", reqId);
        sendTxCompleted(localNodeName, involvedClusters, nodes, reqId, true, txTask.getPartitionKey());
    } else if (result instanceof ODistributedRecordLockedException) {
        if (ODistributedServerLog.isDebugEnabled())
            ODistributedServerLog.debug(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s error: record %s is locked by %s", reqId, ((ODistributedRecordLockedException) result).getRid(), ((ODistributedRecordLockedException) result).getLockHolder());
        // if this is the last retry (and it failed), we don't need to wait anymore
        if (autoRetryDelay > 0 && !isLastRetry)
            Thread.sleep(autoRetryDelay / 2 + new Random().nextInt(autoRetryDelay));
        // RETRY
        return false;
    } else if (result instanceof Exception) {
        // EXCEPTION: LOG IT AND ADD AS NESTED EXCEPTION
        if (ODistributedServerLog.isDebugEnabled())
            ODistributedServerLog.debug(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s received error: %s", reqId, result, result.toString());
        // LET TO THE CALLER TO UNDO IT
        if (result instanceof OTransactionException || result instanceof ONeedRetryException)
            throw (RuntimeException) result;
        if (result instanceof ORecordNotFoundException) {
            // REPAIR THE RECORD IMMEDIATELY
            localDistributedDatabase.getDatabaseRepairer().repairRecord((ORecordId) ((ORecordNotFoundException) result).getRid());
            // RETRY
            return false;
        }
        throw OException.wrapException(new OTransactionException("Error on committing distributed transaction"), (Exception) result);
    } else {
        // UNKNOWN RESPONSE TYPE
        if (ODistributedServerLog.isDebugEnabled())
            ODistributedServerLog.info(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s error, received unknown response type: %s", reqId, result);
        // ROLLBACK TX
        storage.executeUndoOnLocalServer(dResponse.getRequestId(), txTask);
        sendTxCompleted(localNodeName, involvedClusters, nodes, dResponse.getRequestId(), false, txTask.getPartitionKey());
        throw new OTransactionException("Error on committing distributed transaction, received unknown response type " + result);
    }
    return true;
}
Also used : OPlaceholder(com.orientechnologies.orient.core.db.record.OPlaceholder) OException(com.orientechnologies.common.exception.OException) ONeedRetryException(com.orientechnologies.common.concur.ONeedRetryException) IOException(java.io.IOException) ORecordOperation(com.orientechnologies.orient.core.db.record.ORecordOperation) ONeedRetryException(com.orientechnologies.common.concur.ONeedRetryException) ORecord(com.orientechnologies.orient.core.record.ORecord)

Example 24 with ORecordOperation

use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.

the class OrientElement method checkDeletedInTx.

protected boolean checkDeletedInTx() {
    OrientBaseGraph curGraph = getGraph();
    if (curGraph == null)
        return false;
    ORID id;
    if (getRecord() != null)
        id = getRecord().getIdentity();
    else
        return false;
    final ORecordOperation oper = curGraph.getRawGraph().getTransaction().getRecordEntry(id);
    if (oper == null)
        return id.isTemporary();
    else
        return oper.type == ORecordOperation.DELETED;
}
Also used : ORecordOperation(com.orientechnologies.orient.core.db.record.ORecordOperation) ORID(com.orientechnologies.orient.core.id.ORID)

Example 25 with ORecordOperation

use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.

the class OTransactionOptimisticProxy method begin.

@Override
public void begin() {
    super.begin();
    // Needed for keep the exception and insure that all data is read from the socket.
    OException toThrow = null;
    try {
        setUsingLog(channel.readByte() == 1);
        Map<ORecord, byte[]> lazyDeserialize = new IdentityHashMap<ORecord, byte[]>();
        byte lastTxStatus;
        for (lastTxStatus = channel.readByte(); lastTxStatus == 1; lastTxStatus = channel.readByte()) {
            final byte recordStatus = channel.readByte();
            final ORecordId rid = channel.readRID();
            final byte recordType = channel.readByte();
            final ORecordOperation entry = new OTransactionEntryProxy(recordType);
            entry.type = recordStatus;
            switch(recordStatus) {
                case ORecordOperation.CREATED:
                    byte[] content = channel.readBytes();
                    ORecordInternal.fill(entry.getRecord(), rid, 0, null, true);
                    // oNetworkProtocolBinary.fillRecord(rid, content, 0, entry.getRecord(), database);
                    lazyDeserialize.put(entry.getRecord(), content);
                    // SAVE THE RECORD TO RETRIEVE THEM FOR THE NEW RID TO SEND BACK TO THE REQUESTER
                    createdRecords.put(rid.copy(), entry.getRecord());
                    break;
                case ORecordOperation.UPDATED:
                    int version = channel.readVersion();
                    byte[] bytes = channel.readBytes();
                    ORecordInternal.fill(entry.getRecord(), rid, version, null, true);
                    // oNetworkProtocolBinary.fillRecord(rid, bytes, version, entry.getRecord(), database);
                    lazyDeserialize.put(entry.getRecord(), bytes);
                    if (protocolVersion >= 23)
                        ORecordInternal.setContentChanged(entry.getRecord(), channel.readBoolean());
                    break;
                case ORecordOperation.DELETED:
                    // LOAD RECORD TO BE SURE IT HASN'T BEEN DELETED BEFORE + PROVIDE CONTENT FOR ANY HOOK
                    final ORecord rec = rid.getRecord();
                    int deleteVersion = channel.readVersion();
                    if (rec == null)
                        toThrow = new ORecordNotFoundException(rid);
                    else {
                        ORecordInternal.setVersion(rec, deleteVersion);
                        entry.setRecord(rec);
                    }
                    break;
                default:
                    throw new OTransactionException("Unrecognized tx command: " + recordStatus);
            }
            // PUT IN TEMPORARY LIST TO GET FETCHED AFTER ALL FOR CACHE
            tempEntries.put(entry.getRecord().getIdentity(), entry);
        }
        String dbSerializerName = "";
        if (database != null)
            dbSerializerName = database.getSerializer().toString();
        String name = oNetworkProtocolBinary.getRecordSerializerName(connection);
        for (Map.Entry<ORecord, byte[]> entry : lazyDeserialize.entrySet()) {
            ORecord record = entry.getKey();
            final boolean contentChanged = ORecordInternal.isContentChanged(record);
            if (ORecordInternal.getRecordType(record) == ODocument.RECORD_TYPE && !dbSerializerName.equals(name)) {
                ORecordSerializer ser = ORecordSerializerFactory.instance().getFormat(name);
                ser.fromStream(entry.getValue(), record, null);
                record.setDirty();
                ORecordInternal.setContentChanged(record, contentChanged);
            } else {
                record.fromStream(entry.getValue());
                record.setDirty();
                ORecordInternal.setContentChanged(record, contentChanged);
            }
        }
        if (toThrow != null)
            throw toThrow;
        if (lastTxStatus == -1)
            // ABORT TX
            throw new OTransactionAbortedException("Transaction aborted by the client");
        final ODocument remoteIndexEntries = new ODocument(channel.readBytes());
        fillIndexOperations(remoteIndexEntries);
        // FIRE THE TRIGGERS ONLY AFTER HAVING PARSED THE REQUEST
        for (Entry<ORID, ORecordOperation> entry : tempEntries.entrySet()) {
            if (entry.getValue().type == ORecordOperation.UPDATED) {
                // SPECIAL CASE FOR UPDATE: WE NEED TO LOAD THE RECORD AND APPLY CHANGES TO GET WORKING HOOKS (LIKE INDEXES)
                final ORecord record = entry.getValue().record.getRecord();
                final boolean contentChanged = ORecordInternal.isContentChanged(record);
                final ORecord loadedRecord = record.getIdentity().copy().getRecord();
                if (loadedRecord == null)
                    throw new ORecordNotFoundException(record.getIdentity());
                if (ORecordInternal.getRecordType(loadedRecord) == ODocument.RECORD_TYPE && ORecordInternal.getRecordType(loadedRecord) == ORecordInternal.getRecordType(record)) {
                    ((ODocument) loadedRecord).merge((ODocument) record, false, false);
                    loadedRecord.setDirty();
                    ORecordInternal.setContentChanged(loadedRecord, contentChanged);
                    ORecordInternal.setVersion(loadedRecord, record.getVersion());
                    entry.getValue().record = loadedRecord;
                    // SAVE THE RECORD TO RETRIEVE THEM FOR THE NEW VERSIONS TO SEND BACK TO THE REQUESTER
                    updatedRecords.put((ORecordId) entry.getKey(), entry.getValue().getRecord());
                }
            }
            addRecord(entry.getValue().getRecord(), entry.getValue().type, null);
        }
        tempEntries.clear();
        // UNMARSHALL ALL THE RECORD AT THE END TO BE SURE ALL THE RECORD ARE LOADED IN LOCAL TX
        for (ORecord record : createdRecords.values()) {
            unmarshallRecord(record);
            if (record instanceof ODocument) {
                // Force conversion of value to class for trigger default values.
                ODocumentInternal.autoConvertValueToClass(connection.getDatabase(), (ODocument) record);
            }
        }
        for (ORecord record : updatedRecords.values()) unmarshallRecord(record);
    } catch (IOException e) {
        rollback();
        throw OException.wrapException(new OSerializationException("Cannot read transaction record from the network. Transaction aborted"), e);
    }
}
Also used : OSerializationException(com.orientechnologies.orient.core.exception.OSerializationException) OException(com.orientechnologies.common.exception.OException) IOException(java.io.IOException) IOException(java.io.IOException) ORecordId(com.orientechnologies.orient.core.id.ORecordId) OTransactionAbortedException(com.orientechnologies.orient.core.exception.OTransactionAbortedException) ORecordOperation(com.orientechnologies.orient.core.db.record.ORecordOperation) OTransactionException(com.orientechnologies.orient.core.exception.OTransactionException) ORecord(com.orientechnologies.orient.core.record.ORecord) ORecordNotFoundException(com.orientechnologies.orient.core.exception.ORecordNotFoundException) ORecordSerializer(com.orientechnologies.orient.core.serialization.serializer.record.ORecordSerializer) ORID(com.orientechnologies.orient.core.id.ORID) ODocument(com.orientechnologies.orient.core.record.impl.ODocument)

Aggregations

ORecordOperation (com.orientechnologies.orient.core.db.record.ORecordOperation)27 ODocument (com.orientechnologies.orient.core.record.impl.ODocument)13 ORecordId (com.orientechnologies.orient.core.id.ORecordId)11 ORecord (com.orientechnologies.orient.core.record.ORecord)11 OException (com.orientechnologies.common.exception.OException)7 IOException (java.io.IOException)7 OLiveResultListener (com.orientechnologies.orient.core.sql.query.OLiveResultListener)5 Test (org.testng.annotations.Test)5 OTransactionException (com.orientechnologies.orient.core.exception.OTransactionException)4 ORID (com.orientechnologies.orient.core.id.ORID)4 ONeedRetryException (com.orientechnologies.common.concur.ONeedRetryException)3 ODatabaseDocumentInternal (com.orientechnologies.orient.core.db.ODatabaseDocumentInternal)3 ODatabaseDocument (com.orientechnologies.orient.core.db.document.ODatabaseDocument)3 ODatabaseDocumentTx (com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx)3 ORecordNotFoundException (com.orientechnologies.orient.core.exception.ORecordNotFoundException)3 OCommandSQL (com.orientechnologies.orient.core.sql.OCommandSQL)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 Test (org.junit.Test)3 ODatabaseException (com.orientechnologies.orient.core.exception.ODatabaseException)2 OStorageException (com.orientechnologies.orient.core.exception.OStorageException)2