Esempio n. 1
0
  private void writeInlineEdge(
      DataOutput out, InternalRelation edge, TitanType type, boolean writeEdgeType) {
    assert type.isSimple();
    assert writeEdgeType
        || type.isEdgeLabel()
        || (type.isPropertyKey() && !hasGenericDataType((TitanKey) type));

    if (edge == null) {
      assert !writeEdgeType;
      if (type.isPropertyKey()) {
        out.writeObject(null);
      } else {
        assert type.isEdgeLabel();
        VariableLong.writePositive(out, 0);
      }
    } else {
      if (writeEdgeType) {
        IDHandler.writeInlineEdgeType(out, type.getID(), idManager);
      }
      if (edge.isProperty()) {
        Object attribute = ((TitanProperty) edge).getAttribute();
        if (hasGenericDataType((TitanKey) type)) out.writeClassAndObject(attribute);
        else out.writeObject(attribute);
      } else {
        assert edge.isUnidirected() && edge.isEdge();
        VariableLong.writePositive(out, edge.getVertex(1).getID());
      }
    }
  }
Esempio n. 2
0
  private Entry getEntry(
      InternalTitanTransaction tx,
      InternalRelation edge,
      InternalTitanVertex perspective,
      Map<TitanType, TypeSignature> signatures,
      boolean columnOnly) {
    TitanType et = edge.getType();
    long etid = et.getID();

    int dirID;
    if (edge.isProperty()) {
      dirID = 0;
    } else if (edge.getVertex(0).equals(perspective)) {
      // Out TitanRelation
      assert edge.isDirected() || edge.isUnidirected();
      dirID = 2;
    } else {
      // In TitanRelation
      assert !edge.isUnidirected() && edge.getVertex(1).equals(perspective);
      dirID = 3;
    }

    int etIDLength = IDHandler.edgeTypeLength(etid, idManager);

    ByteBuffer column = null, value = null;
    if (et.isSimple()) {
      if (et.isFunctional()) {
        column = ByteBuffer.allocate(etIDLength);
        IDHandler.writeEdgeType(column, etid, dirID, idManager);
      } else {
        column = ByteBuffer.allocate(etIDLength + VariableLong.positiveLength(edge.getID()));
        IDHandler.writeEdgeType(column, etid, dirID, idManager);
        VariableLong.writePositive(column, edge.getID());
      }
      column.flip();
      if (!columnOnly) {
        if (edge.isEdge()) {
          long nodeIDDiff =
              ((TitanEdge) edge).getOtherVertex(perspective).getID() - perspective.getID();
          int nodeIDDiffLength = VariableLong.length(nodeIDDiff);
          if (et.isFunctional()) {
            value =
                ByteBuffer.allocate(nodeIDDiffLength + VariableLong.positiveLength(edge.getID()));
            VariableLong.write(value, nodeIDDiff);
            VariableLong.writePositive(value, edge.getID());
          } else {
            value = ByteBuffer.allocate(nodeIDDiffLength);
            VariableLong.write(value, nodeIDDiff);
          }
          value.flip();
        } else {
          assert edge.isProperty();
          DataOutput out = serializer.getDataOutput(defaultOutputCapacity, true);
          // Write object
          writeAttribute(out, (TitanProperty) edge);
          if (et.isFunctional()) {
            VariableLong.writePositive(out, edge.getID());
          }
          value = out.getByteBuffer();
        }
      }
    } else {
      TypeSignature ets = getSignature(tx, et, signatures);

      InternalRelation[] keys = new InternalRelation[ets.keyLength()],
          values = new InternalRelation[ets.valueLength()];
      List<InternalRelation> rest = new ArrayList<InternalRelation>();
      ets.sort(edge.getRelations(SimpleAtomicQuery.queryAll(edge), false), keys, values, rest);

      DataOutput out = serializer.getDataOutput(defaultOutputCapacity, true);
      IDHandler.writeEdgeType(out, etid, dirID, idManager);

      for (int i = 0; i < keys.length; i++) writeInlineEdge(out, keys[i], ets.getKeyType(i));

      if (!et.isFunctional()) {
        VariableLong.writePositive(out, edge.getID());
      }
      column = out.getByteBuffer();

      if (!columnOnly) {
        out = serializer.getDataOutput(defaultOutputCapacity, true);

        if (edge.isEdge()) {
          long nodeIDDiff =
              ((TitanEdge) edge).getOtherVertex(perspective).getID() - perspective.getID();
          VariableLong.write(out, nodeIDDiff);
        } else {
          assert edge.isProperty();
          writeAttribute(out, (TitanProperty) edge);
        }

        if (et.isFunctional()) {
          assert edge.isEdge();
          VariableLong.writePositive(out, edge.getID());
        }
        for (int i = 0; i < values.length; i++)
          writeInlineEdge(out, values[i], ets.getValueType(i));
        for (InternalRelation v : rest) writeInlineEdge(out, v);
        value = out.getByteBuffer();
      }
    }
    return new Entry(column, value);
  }
Esempio n. 3
0
  @Override
  public void save(
      final Collection<InternalRelation> addedRelations,
      final Collection<InternalRelation> deletedRelations,
      final InternalTitanTransaction tx)
      throws StorageException {
    // Setup
    log.debug(
        "Saving transaction. Added {}, removed {}", addedRelations.size(), deletedRelations.size());
    final Map<TitanType, TypeSignature> signatures = new HashMap<TitanType, TypeSignature>();
    final TransactionHandle txh = tx.getTxHandle();

    final StoreMutator mutator = getStoreMutator(txh);
    final boolean acquireLocks = tx.getTxConfiguration().hasAcquireLocks();

    // 1. Assign TitanVertex IDs
    assignIDs(addedRelations, tx);

    for (int saveAttempt = 0; saveAttempt < maxWriteRetryAttempts; saveAttempt++) {
      //        while (true) { //Indefinite loop, broken if no exception occurs, otherwise retried
      // or failed immediately
      try {
        // 2. Collect deleted edges
        ListMultimap<InternalTitanVertex, InternalRelation> mutations = ArrayListMultimap.create();
        if (deletedRelations != null && !deletedRelations.isEmpty()) {
          for (InternalRelation del : deletedRelations) {
            assert del.isRemoved();
            for (int pos = 0; pos < del.getArity(); pos++) {
              InternalTitanVertex node = del.getVertex(pos);
              if (pos == 0 || !del.isUnidirected()) {
                mutations.put(node, del);
              }
              if (pos == 0
                  && acquireLocks
                  && del.getType().isFunctional()
                  && ((InternalTitanType) del.getType()).isFunctionalLocking()) {
                Entry entry = getEntry(tx, del, node, signatures);
                mutator.acquireEdgeLock(
                    IDHandler.getKey(node.getID()), entry.getColumn(), entry.getValue());
              }
            }
            if (acquireLocks && del.isProperty()) {
              lockKeyedProperty((TitanProperty) del, mutator);
            }
          }
        }

        ListMultimap<InternalTitanType, InternalRelation> simpleEdgeTypes = null;
        ListMultimap<InternalTitanType, InternalRelation> otherEdgeTypes = null;

        // 3. Sort Added Edges
        for (InternalRelation edge : addedRelations) {
          if (edge.isRemoved()) continue;
          assert edge.isNew();

          TitanType et = edge.getType();

          // Give special treatment to edge type definitions
          if (SystemTypeManager.prepersistedSystemTypes.contains(et)) {
            assert edge.getVertex(0) instanceof InternalTitanType;
            InternalTitanType node = (InternalTitanType) edge.getVertex(0);
            assert node.hasID();
            if (node.isSimple()) {
              if (simpleEdgeTypes == null) simpleEdgeTypes = ArrayListMultimap.create();
              simpleEdgeTypes.put(node, edge);
            } else {
              if (otherEdgeTypes == null) otherEdgeTypes = ArrayListMultimap.create();
              otherEdgeTypes.put(node, edge);
            }
          } else { // STANDARD TitanRelation
            assert (edge.getArity() == 1 && edge.isProperty())
                || (edge.getArity() == 2 && edge.isEdge());
            for (int pos = 0; pos < edge.getArity(); pos++) {
              InternalTitanVertex node = edge.getVertex(pos);
              assert node.hasID();
              if (pos == 0 || !edge.isUnidirected()) {
                mutations.put(node, edge);
              }
              if (pos == 0
                  && acquireLocks
                  && edge.getType().isFunctional()
                  && !node.isNew()
                  && ((InternalTitanType) edge.getType()).isFunctionalLocking()) {
                Entry entry = getEntry(tx, edge, node, signatures, true);
                mutator.acquireEdgeLock(IDHandler.getKey(node.getID()), entry.getColumn(), null);
              }
            }
          }
          if (acquireLocks && edge.isProperty()) {
            lockKeyedProperty((TitanProperty) edge, mutator);
          }
        }

        // 3. Persist
        if (simpleEdgeTypes != null) persist(simpleEdgeTypes, signatures, tx, mutator);
        if (otherEdgeTypes != null) persist(otherEdgeTypes, signatures, tx, mutator);
        mutator.flush();

        // Commit saved EdgeTypes to TypeManager
        if (simpleEdgeTypes != null) commitEdgeTypes(simpleEdgeTypes.keySet());
        if (otherEdgeTypes != null) commitEdgeTypes(otherEdgeTypes.keySet());

        if (!mutations.isEmpty()) persist(mutations, signatures, tx, mutator);
        mutator.flush();

        // Successfully completed - return to break out of loop
        break;
      } catch (Throwable e) {
        if (e instanceof TemporaryStorageException) {
          if (saveAttempt < maxWriteRetryAttempts - 1) temporaryStorageException(e);
          else
            throw new PermanentStorageException(
                "Tried committing "
                    + maxWriteRetryAttempts
                    + " times on temporary exception without success",
                e);
        } else if (e instanceof StorageException) {
          throw (StorageException) e;
        } else {
          throw new PermanentStorageException(
              "Unidentified exception occurred during persistence", e);
        }
      }
    }
  }