Search in sources :

Example 1 with OTransactionOptimistic

use of com.orientechnologies.orient.core.tx.OTransactionOptimistic in project orientdb by orientechnologies.

the class ODatabaseDocumentTx method begin.

public ODatabaseDocumentTx begin(final OTransaction.TXTYPE iType) {
    checkOpeness();
    checkIfActive();
    if (currentTx.isActive()) {
        if (iType == OTransaction.TXTYPE.OPTIMISTIC && currentTx instanceof OTransactionOptimistic) {
            currentTx.begin();
            return this;
        }
        currentTx.rollback(true, 0);
    }
    // CHECK IT'S NOT INSIDE A HOOK
    if (!inHook.isEmpty())
        throw new IllegalStateException("Cannot begin a transaction while a hook is executing");
    // WAKE UP LISTENERS
    for (ODatabaseListener listener : browseListeners()) try {
        listener.onBeforeTxBegin(this);
    } catch (Throwable t) {
        OLogManager.instance().error(this, "Error before tx begin", t);
    }
    switch(iType) {
        case NOTX:
            setDefaultTransactionMode();
            break;
        case OPTIMISTIC:
            currentTx = new OTransactionOptimistic(this);
            break;
        case PESSIMISTIC:
            throw new UnsupportedOperationException("Pessimistic transaction");
    }
    currentTx.begin();
    return this;
}
Also used : OTransactionOptimistic(com.orientechnologies.orient.core.tx.OTransactionOptimistic)

Example 2 with OTransactionOptimistic

use of com.orientechnologies.orient.core.tx.OTransactionOptimistic in project orientdb by orientechnologies.

the class OObjectSerializerHelper method toStream.

/**
   * Serialize the user POJO to a ORecordDocument instance.
   * 
   * @param iPojo
   *          User pojo to serialize
   * @param iRecord
   *          Record where to update
   * @param iObj2RecHandler
   */
public static ODocument toStream(final Object iPojo, final ODocument iRecord, final OEntityManager iEntityManager, final OClass schemaClass, final OUserObject2RecordHandler iObj2RecHandler, final ODatabaseObject db, final boolean iSaveOnlyDirty) {
    if (iSaveOnlyDirty && !iRecord.isDirty())
        return iRecord;
    final long timer = Orient.instance().getProfiler().startChrono();
    final Integer identityRecord = System.identityHashCode(iRecord);
    if (OSerializationThreadLocal.INSTANCE.get().contains(identityRecord))
        return iRecord;
    OSerializationThreadLocal.INSTANCE.get().add(identityRecord);
    OProperty schemaProperty;
    final Class<?> pojoClass = iPojo.getClass();
    final List<Field> properties = getClassFields(pojoClass);
    // CHECK FOR ID BINDING
    final Field idField = fieldIds.get(pojoClass);
    if (idField != null) {
        Object id = getFieldValue(iPojo, idField.getName());
        if (id != null) {
            // FOUND
            if (id instanceof ORecordId) {
                ORecordInternal.setIdentity(iRecord, (ORecordId) id);
            } else if (id instanceof Number) {
                // TREATS AS CLUSTER POSITION
                ((ORecordId) iRecord.getIdentity()).setClusterId(schemaClass.getDefaultClusterId());
                ((ORecordId) iRecord.getIdentity()).setClusterPosition(((Number) id).longValue());
            } else if (id instanceof String)
                ((ORecordId) iRecord.getIdentity()).fromString((String) id);
            else if (id.getClass().equals(Object.class))
                ORecordInternal.setIdentity(iRecord, (ORecordId) id);
            else
                OLogManager.instance().warn(OObjectSerializerHelper.class, "@Id field has been declared as %s while the supported are: ORID, Number, String, Object", id.getClass());
        }
    }
    // CHECK FOR VERSION BINDING
    final Field vField = fieldVersions.get(pojoClass);
    boolean versionConfigured = false;
    if (vField != null) {
        versionConfigured = true;
        Object ver = getFieldValue(iPojo, vField.getName());
        final int version = convertVersion(ver);
        ORecordInternal.setVersion(iRecord, version);
    }
    if (db.isMVCC() && !versionConfigured && db.getTransaction() instanceof OTransactionOptimistic)
        throw new OTransactionException("Cannot involve an object of class '" + pojoClass + "' in an Optimistic Transaction commit because it does not define @Version or @OVersion and therefore cannot handle MVCC");
    // SET OBJECT CLASS
    iRecord.setClassName(schemaClass != null ? schemaClass.getName() : null);
    String fieldName;
    Object fieldValue;
    // CALL BEFORE MARSHALLING
    invokeCallback(iPojo, iRecord, OBeforeSerialization.class);
    for (Field p : properties) {
        fieldName = p.getName();
        if (idField != null && fieldName.equals(idField.getName()))
            continue;
        if (vField != null && fieldName.equals(vField.getName()))
            continue;
        fieldValue = serializeFieldValue(getFieldType(iPojo, fieldName), getFieldValue(iPojo, fieldName));
        schemaProperty = schemaClass != null ? schemaClass.getProperty(fieldName) : null;
        if (fieldValue != null) {
            if (isEmbeddedObject(iPojo.getClass(), fieldValue.getClass(), fieldName, iEntityManager)) {
                // AUTO CREATE SCHEMA PROPERTY
                if (schemaClass == null) {
                    db.getMetadata().getSchema().createClass(iPojo.getClass());
                    iRecord.setClassNameIfExists(iPojo.getClass().getSimpleName());
                }
                if (schemaProperty == null) {
                    OType t = OType.getTypeByClass(fieldValue.getClass());
                    if (t == null)
                        t = OType.EMBEDDED;
                    schemaProperty = iRecord.getSchemaClass().createProperty(fieldName, t);
                }
            }
        }
        fieldValue = typeToStream(fieldValue, schemaProperty != null ? schemaProperty.getType() : null, iEntityManager, iObj2RecHandler, db, iRecord, iSaveOnlyDirty);
        iRecord.field(fieldName, fieldValue);
    }
    iObj2RecHandler.registerUserObject(iPojo, iRecord);
    // CALL AFTER MARSHALLING
    invokeCallback(iPojo, iRecord, OAfterSerialization.class);
    OSerializationThreadLocal.INSTANCE.get().remove(identityRecord);
    Orient.instance().getProfiler().stopChrono("Object.toStream", "Serialize object to stream", timer);
    return iRecord;
}
Also used : OProperty(com.orientechnologies.orient.core.metadata.schema.OProperty) OType(com.orientechnologies.orient.core.metadata.schema.OType) ORecordId(com.orientechnologies.orient.core.id.ORecordId) Field(java.lang.reflect.Field) OTransactionOptimistic(com.orientechnologies.orient.core.tx.OTransactionOptimistic) OTransactionException(com.orientechnologies.orient.core.exception.OTransactionException) ODatabaseObject(com.orientechnologies.orient.core.db.object.ODatabaseObject)

Example 3 with OTransactionOptimistic

use of com.orientechnologies.orient.core.tx.OTransactionOptimistic in project orientdb by orientechnologies.

the class OObjectEntitySerializer method toStream.

/**
   * Serialize the user POJO to a ORecordDocument instance.
   *
   * @param iPojo
   *          User pojo to serialize
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
@SuppressWarnings("unchecked")
protected static <T> T toStream(final T iPojo, final Proxy iProxiedPojo, ODatabaseObject db) throws IllegalArgumentException, IllegalAccessException {
    final ODocument iRecord = getDocument(iProxiedPojo);
    final long timer = Orient.instance().getProfiler().startChrono();
    final Integer identityRecord = System.identityHashCode(iPojo);
    if (OObjectSerializationThreadLocal.INSTANCE.get().containsKey(identityRecord))
        return (T) OObjectSerializationThreadLocal.INSTANCE.get().get(identityRecord);
    OObjectSerializationThreadLocal.INSTANCE.get().put(identityRecord, iProxiedPojo);
    OProperty schemaProperty;
    final Class<?> pojoClass = iPojo.getClass();
    final OClass schemaClass = iRecord.getSchemaClass();
    // CHECK FOR ID BINDING
    final Field idField = getIdField(pojoClass);
    if (idField != null) {
        Object id = getFieldValue(idField, iPojo);
        if (id != null) {
            // FOUND
            if (id instanceof ORecordId) {
                ORecordInternal.setIdentity(iRecord, (ORecordId) id);
            } else if (id instanceof Number) {
                // TREATS AS CLUSTER POSITION
                ((ORecordId) iRecord.getIdentity()).setClusterId(schemaClass.getDefaultClusterId());
                ((ORecordId) iRecord.getIdentity()).setClusterPosition(((Number) id).longValue());
            } else if (id instanceof String)
                ((ORecordId) iRecord.getIdentity()).fromString((String) id);
            else if (id.getClass().equals(Object.class))
                ORecordInternal.setIdentity(iRecord, (ORecordId) id);
            else
                OLogManager.instance().warn(OObjectSerializerHelper.class, "@Id field has been declared as %s while the supported are: ORID, Number, String, Object", id.getClass());
        }
        if (iRecord.getIdentity().isValid() && iRecord.getIdentity().isPersistent())
            iRecord.reload();
    }
    // CHECK FOR VERSION BINDING
    final Field vField = getVersionField(pojoClass);
    boolean versionConfigured = false;
    if (vField != null) {
        versionConfigured = true;
        Object ver = getFieldValue(vField, iPojo);
        if (ver != null) {
            // FOUND
            int version = iRecord.getVersion();
            if (ver instanceof Number) {
                // TREATS AS CLUSTER POSITION
                version = ((Number) ver).intValue();
            } else if (ver instanceof String)
                version = Integer.parseInt((String) ver);
            else
                OLogManager.instance().warn(OObjectSerializerHelper.class, "@Version field has been declared as %s while the supported are: Number, String", ver.getClass());
            ORecordInternal.setVersion(iRecord, version);
        }
    }
    if (db.isMVCC() && !versionConfigured && db.getTransaction() instanceof OTransactionOptimistic)
        throw new OTransactionException("Cannot involve an object of class '" + pojoClass + "' in an Optimistic Transaction commit because it does not define @Version or @OVersion and therefore cannot handle MVCC");
    String fieldName;
    Object fieldValue;
    // CALL BEFORE MARSHALLING
    invokeCallback(pojoClass, iPojo, iRecord, OBeforeSerialization.class);
    Class<?> currentClass = pojoClass;
    OObjectEntitySerializedSchema serializedSchema = getCurrentSerializedSchema();
    while (!currentClass.equals(Object.class) && serializedSchema.classes.contains(pojoClass)) {
        for (Field p : getDeclaredFields(currentClass)) {
            if (Modifier.isStatic(p.getModifiers()) || Modifier.isNative(p.getModifiers()) || Modifier.isTransient(p.getModifiers()) || p.getType().isAnonymousClass())
                continue;
            fieldName = p.getName();
            List<String> classTransientFields = serializedSchema.transientFields.get(currentClass);
            if ((idField != null && fieldName.equals(idField.getName()) || (vField != null && fieldName.equals(vField.getName())) || (classTransientFields != null && classTransientFields.contains(fieldName))))
                continue;
            fieldValue = getFieldValue(p, iPojo);
            if (fieldValue != null && fieldValue.getClass().isAnonymousClass())
                continue;
            if (isSerializedType(p))
                fieldValue = serializeFieldValue(p.getType(), fieldValue);
            schemaProperty = schemaClass != null ? schemaClass.getProperty(fieldName) : null;
            OType fieldType = schemaProperty != null ? schemaProperty.getType() : getTypeByClass(currentClass, fieldName);
            if (fieldValue != null) {
                if (isEmbeddedObject(p)) {
                    // AUTO CREATE SCHEMA CLASS
                    if (iRecord.getSchemaClass() == null) {
                        db.getMetadata().getSchema().createClass(iPojo.getClass());
                        iRecord.setClassNameIfExists(iPojo.getClass().getSimpleName());
                    }
                }
            }
            fieldValue = typeToStream(fieldValue, fieldType, db, iRecord);
            iRecord.field(fieldName, fieldValue, fieldType);
        }
        currentClass = currentClass.getSuperclass();
        if (currentClass == null || currentClass.equals(ODocument.class))
            // POJO EXTENDS ODOCUMENT: SPECIAL CASE: AVOID TO CONSIDER
            // ODOCUMENT FIELDS
            currentClass = Object.class;
    }
    // CALL AFTER MARSHALLING
    invokeCallback(pojoClass, iPojo, iRecord, OAfterSerialization.class);
    OObjectSerializationThreadLocal.INSTANCE.get().remove(identityRecord);
    Orient.instance().getProfiler().stopChrono("Object.toStream", "Serialize a POJO", timer);
    return (T) iProxiedPojo;
}
Also used : OProperty(com.orientechnologies.orient.core.metadata.schema.OProperty) OType(com.orientechnologies.orient.core.metadata.schema.OType) ORecordId(com.orientechnologies.orient.core.id.ORecordId) Field(java.lang.reflect.Field) OTransactionOptimistic(com.orientechnologies.orient.core.tx.OTransactionOptimistic) OTransactionException(com.orientechnologies.orient.core.exception.OTransactionException) OClass(com.orientechnologies.orient.core.metadata.schema.OClass) ProxyObject(javassist.util.proxy.ProxyObject) ODatabaseObject(com.orientechnologies.orient.core.db.object.ODatabaseObject) OSchemaProxyObject(com.orientechnologies.orient.object.metadata.schema.OSchemaProxyObject) ODocument(com.orientechnologies.orient.core.record.impl.ODocument)

Example 4 with OTransactionOptimistic

use of com.orientechnologies.orient.core.tx.OTransactionOptimistic in project orientdb by orientechnologies.

the class OTxTask method execute.

@Override
public Object execute(final ODistributedRequestId requestId, final OServer iServer, ODistributedServerManager iManager, final ODatabaseDocumentInternal database) throws Exception {
    ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.IN, "Executing transaction db=%s (reqId=%s)...", database.getName(), requestId);
    ODatabaseRecordThreadLocal.INSTANCE.set(database);
    final ODistributedDatabase ddb = iManager.getMessageService().getDatabase(database.getName());
    // CREATE A CONTEXT OF TX
    reqContext = ddb.registerTxContext(requestId);
    final ODistributedConfiguration dCfg = iManager.getDatabaseConfiguration(database.getName());
    result = new OTxTaskResult();
    if (tasks.size() == 0)
        // RETURN AFTER REGISTERED THE CONTEXT
        return result;
    database.begin();
    try {
        final OTransactionOptimistic tx = (OTransactionOptimistic) database.getTransaction();
        // REGISTER CREATE FIRST TO RESOLVE TEMP RIDS
        for (OAbstractRecordReplicatedTask task : tasks) {
            if (task instanceof OCreateRecordTask) {
                final OCreateRecordTask createRT = (OCreateRecordTask) task;
                final ORecordId rid = createRT.getRid();
                if (rid != null && rid.isPersistent()) {
                    if (rid.getRecord() != null)
                        // ALREADY CREATED: SKIP REGISTERING IN TX
                        continue;
                }
                final int clId = createRT.clusterId > -1 ? createRT.clusterId : createRT.getRid().isValid() ? createRT.getRid().getClusterId() : -1;
                final String clusterName = clId > -1 ? database.getClusterNameById(clId) : null;
                if (dCfg.isServerContainingCluster(iManager.getLocalNodeName(), clusterName))
                    tx.addRecord(createRT.getRecord(), ORecordOperation.CREATED, clusterName);
            }
        }
        final List<ORecordId> rids2Lock = new ArrayList<ORecordId>();
        // LOCK ALL THE RECORDS FIRST (ORDERED TO AVOID DEADLOCK)
        for (OAbstractRecordReplicatedTask task : tasks) rids2Lock.add(task.getRid());
        Collections.sort(rids2Lock);
        for (ORecordId rid : rids2Lock) reqContext.lock(rid, getRecordLock());
        for (OAbstractRecordReplicatedTask task : tasks) {
            final Object taskResult;
            // CHECK LOCAL CLUSTER IS AVAILABLE ON CURRENT SERVER
            if (!task.checkForClusterAvailability(iManager.getLocalNodeName(), dCfg))
                // SKIP EXECUTION BECAUSE THE CLUSTER IS NOT ON LOCAL NODE: THIS CAN HAPPENS IN CASE OF DISTRIBUTED TX WITH SHARDING
                taskResult = NON_LOCAL_CLUSTER;
            else {
                task.setLockRecords(false);
                task.checkRecordExists();
                taskResult = task.execute(requestId, iServer, iManager, database);
                reqContext.addUndoTask(task.getUndoTask(requestId));
            }
            result.results.add(taskResult);
        }
        database.commit();
        // SEND BACK CHANGED VALUE TO UPDATE
        for (int i = 0; i < result.results.size(); ++i) {
            final Object currentResult = result.results.get(i);
            if (currentResult == NON_LOCAL_CLUSTER)
                // SKIP IT
                continue;
            final OAbstractRecordReplicatedTask task = tasks.get(i);
            if (task instanceof OCreateRecordTask) {
                // SEND RID + VERSION
                final OCreateRecordTask t = (OCreateRecordTask) task;
                result.results.set(i, new OPlaceholder(t.getRecord()));
            } else if (task instanceof OUpdateRecordTask) {
                // SEND VERSION
                result.results.set(i, task.getRecord().getVersion());
            }
        }
        return result;
    } catch (Throwable e) {
        // if (e instanceof ODistributedRecordLockedException)
        // ddb.dumpLocks();
        ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.IN, "Rolling back transaction on local server db=%s (reqId=%s error=%s)...", database.getName(), requestId, e);
        database.rollback();
        // ddb.popTxContext(requestId);
        reqContext.unlock();
        if (!(e instanceof ONeedRetryException || e instanceof OTransactionException || e instanceof ORecordDuplicatedException || e instanceof ORecordNotFoundException))
            // DUMP ONLY GENERIC EXCEPTIONS
            ODistributedServerLog.info(this, getNodeSource(), null, DIRECTION.NONE, "Error on distributed transaction commit", e);
        return e;
    }
}
Also used : OPlaceholder(com.orientechnologies.orient.core.db.record.OPlaceholder) OAbstractRecordReplicatedTask(com.orientechnologies.orient.server.distributed.task.OAbstractRecordReplicatedTask) ArrayList(java.util.ArrayList) ORecordId(com.orientechnologies.orient.core.id.ORecordId) ONeedRetryException(com.orientechnologies.common.concur.ONeedRetryException) ORecordDuplicatedException(com.orientechnologies.orient.core.storage.ORecordDuplicatedException) OTransactionOptimistic(com.orientechnologies.orient.core.tx.OTransactionOptimistic) OTransactionException(com.orientechnologies.orient.core.exception.OTransactionException) ORecordNotFoundException(com.orientechnologies.orient.core.exception.ORecordNotFoundException)

Example 5 with OTransactionOptimistic

use of com.orientechnologies.orient.core.tx.OTransactionOptimistic in project orientdb by orientechnologies.

the class ODocument method setDirty.

/**
   * Propagates the dirty status to the owner, if any. This happens when the object is embedded in another one.
   */
@Override
public ORecordAbstract setDirty() {
    if (_owners != null) {
        // PROPAGATES TO THE OWNER
        ORecordElement e;
        for (WeakReference<ORecordElement> o : _owners) {
            e = o.get();
            if (e != null)
                e.setDirty();
        }
    } else if (!isDirty())
        getDirtyManager().setDirty(this);
    // THIS IS IMPORTANT TO BE SURE THAT FIELDS ARE LOADED BEFORE IT'S TOO LATE AND THE RECORD _SOURCE IS NULL
    checkForFields();
    super.setDirty();
    boolean addToChangedList = false;
    ORecordElement owner;
    if (!isEmbedded())
        owner = this;
    else {
        owner = getOwner();
        while (owner != null && owner.getOwner() != null) {
            owner = owner.getOwner();
        }
    }
    if (owner instanceof ODocument && ((ODocument) owner).isTrackingChanges() && ((ODocument) owner).getIdentity().isPersistent())
        addToChangedList = true;
    if (addToChangedList) {
        final ODatabaseDocument database = getDatabaseIfDefined();
        if (database != null) {
            final OTransaction transaction = database.getTransaction();
            if (transaction instanceof OTransactionOptimistic) {
                OTransactionOptimistic transactionOptimistic = (OTransactionOptimistic) transaction;
                transactionOptimistic.addChangedDocument(this);
            }
        }
    }
    return this;
}
Also used : OTransaction(com.orientechnologies.orient.core.tx.OTransaction) ODatabaseDocument(com.orientechnologies.orient.core.db.document.ODatabaseDocument) OTransactionOptimistic(com.orientechnologies.orient.core.tx.OTransactionOptimistic)

Aggregations

OTransactionOptimistic (com.orientechnologies.orient.core.tx.OTransactionOptimistic)5 OTransactionException (com.orientechnologies.orient.core.exception.OTransactionException)3 ORecordId (com.orientechnologies.orient.core.id.ORecordId)3 ODatabaseObject (com.orientechnologies.orient.core.db.object.ODatabaseObject)2 OProperty (com.orientechnologies.orient.core.metadata.schema.OProperty)2 OType (com.orientechnologies.orient.core.metadata.schema.OType)2 Field (java.lang.reflect.Field)2 ONeedRetryException (com.orientechnologies.common.concur.ONeedRetryException)1 ODatabaseDocument (com.orientechnologies.orient.core.db.document.ODatabaseDocument)1 OPlaceholder (com.orientechnologies.orient.core.db.record.OPlaceholder)1 ORecordNotFoundException (com.orientechnologies.orient.core.exception.ORecordNotFoundException)1 OClass (com.orientechnologies.orient.core.metadata.schema.OClass)1 ODocument (com.orientechnologies.orient.core.record.impl.ODocument)1 ORecordDuplicatedException (com.orientechnologies.orient.core.storage.ORecordDuplicatedException)1 OTransaction (com.orientechnologies.orient.core.tx.OTransaction)1 OSchemaProxyObject (com.orientechnologies.orient.object.metadata.schema.OSchemaProxyObject)1 OAbstractRecordReplicatedTask (com.orientechnologies.orient.server.distributed.task.OAbstractRecordReplicatedTask)1 ArrayList (java.util.ArrayList)1 ProxyObject (javassist.util.proxy.ProxyObject)1