/**
  * Gets the sum of the sizes of the blocks in this record, in bytes.
  *
  * @return
  */
 public int size() {
   int result = 0;
   for (PropertyBlock block : blockRecords) {
     result += block.getSize();
   }
   return result;
 }
Example #2
0
 public void ensureHeavy(PropertyBlock block) {
   if (block.getType() == PropertyType.STRING) {
     if (block.isLight()) {
       Collection<DynamicRecord> stringRecords =
           stringPropertyStore.getLightRecords(block.getSingleValueLong());
       for (DynamicRecord stringRecord : stringRecords) {
         stringRecord.setType(PropertyType.STRING.intValue());
         block.addValueRecord(stringRecord);
       }
     }
     for (DynamicRecord stringRecord : block.getValueRecords()) {
       stringPropertyStore.ensureHeavy(stringRecord);
     }
   } else if (block.getType() == PropertyType.ARRAY) {
     if (block.isLight()) {
       Collection<DynamicRecord> arrayRecords =
           arrayPropertyStore.getLightRecords(block.getSingleValueLong());
       for (DynamicRecord arrayRecord : arrayRecords) {
         arrayRecord.setType(PropertyType.ARRAY.intValue());
         block.addValueRecord(arrayRecord);
       }
     }
     for (DynamicRecord arrayRecord : block.getValueRecords()) {
       arrayPropertyStore.ensureHeavy(arrayRecord);
     }
   }
 }
Example #3
0
 private void deleteNode2(
     long node, DefinedProperty prop1, DefinedProperty prop2, DefinedProperty prop3)
     throws IOException {
   ArrayMap<Integer, Pair<DefinedProperty, Long>> props = new ArrayMap<>();
   xaCon.getTransaction().nodeLoadProperties(node, false, newPropertyReceiver(props));
   int count = 0;
   for (int keyId : props.keySet()) {
     long id = props.get(keyId).other();
     PropertyRecord record = pStore.getRecord(id);
     PropertyBlock block = record.getPropertyBlock(props.get(keyId).first().propertyKeyId());
     DefinedProperty data = block.newPropertyData(pStore);
     if (data.propertyKeyId() == prop1.propertyKeyId()) {
       assertEquals("prop1", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals("-string2", data.value());
     } else if (data.propertyKeyId() == prop2.propertyKeyId()) {
       assertEquals("prop2", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(-2, data.value());
     } else if (data.propertyKeyId() == prop3.propertyKeyId()) {
       assertEquals("prop3", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(true, data.value());
       xaCon.getTransaction().nodeRemoveProperty(node, prop3.propertyKeyId());
     } else {
       throw new IOException();
     }
     count++;
   }
   assertEquals(3, count);
   CountingPropertyReceiver propertyCounter = new CountingPropertyReceiver();
   xaCon.getTransaction().nodeLoadProperties(node, false, propertyCounter);
   assertEquals(3, propertyCounter.count);
   MutableRelationshipLoadingPosition pos = getPosition(xaCon, node);
   Iterator<RelationshipRecord> rels = getMore(xaCon, node, pos).iterator();
   assertTrue(rels.hasNext());
   xaCon.getTransaction().nodeDelete(node);
 }
 public PropertyBlock getPropertyBlock(int keyIndex) {
   for (PropertyBlock block : blockRecords) {
     if (block.getKeyIndexId() == keyIndex) {
       return block;
     }
   }
   return null;
 }
Example #5
0
  private void updateRecord(PropertyRecord record, PersistenceWindow window) {
    long id = record.getId();
    registerIdFromUpdateRecord(id);
    Buffer buffer = window.getOffsettedBuffer(id);
    if (record.inUse()) {
      // Set up the record header
      short prevModifier =
          record.getPrevProp() == Record.NO_NEXT_RELATIONSHIP.intValue()
              ? 0
              : (short) ((record.getPrevProp() & 0xF00000000L) >> 28);
      short nextModifier =
          record.getNextProp() == Record.NO_NEXT_RELATIONSHIP.intValue()
              ? 0
              : (short) ((record.getNextProp() & 0xF00000000L) >> 32);
      byte modifiers = (byte) (prevModifier | nextModifier);
      /*
       * [pppp,nnnn] previous, next high bits
       */
      buffer.put(modifiers);
      buffer.putInt((int) record.getPrevProp()).putInt((int) record.getNextProp());

      // Then go through the blocks
      int longsAppended = 0; // For marking the end of blocks
      for (PropertyBlock block : record.getPropertyBlocks()) {
        long[] propBlockValues = block.getValueBlocks();
        for (long propBlockValue : propBlockValues) {
          buffer.putLong(propBlockValue);
        }

        longsAppended += propBlockValues.length;
        /*
         * For each block we need to update its dynamic record chain if
         * it is just created. Deleted dynamic records are in the property
         * record and dynamic records are never modified. Also, they are
         * assigned as a whole, so just checking the first should be enough.
         */
        if (!block.isLight() && block.getValueRecords().get(0).isCreated()) {
          updateDynamicRecords(block.getValueRecords());
        }
      }
      if (longsAppended < PropertyType.getPayloadSizeLongs()) {
        buffer.putLong(0);
      }
    } else {
      if (!isInRecoveryMode()) {
        freeId(id);
      }
      // skip over the record header, nothing useful there
      buffer.setOffset(buffer.getOffset() + 9);
      buffer.putLong(0);
    }
    updateDynamicRecords(record.getDeletedRecords());
  }
  public void addPropertyBlock(PropertyBlock block) {
    assert size() + block.getSize() <= PropertyType.getPayloadSize()
        : ("Exceeded capacity of property record "
            + this
            + ". My current size is reported as "
            + size()
            + "The added block was "
            + block
            + " (note that size is "
            + block.getSize()
            + ")");

    blockRecords.add(block);
  }
Example #7
0
 private void deleteRel1(
     long rel,
     DefinedProperty prop1,
     DefinedProperty prop2,
     DefinedProperty prop3,
     long firstNode,
     long secondNode,
     int relType)
     throws IOException {
   ArrayMap<Integer, Pair<DefinedProperty, Long>> props = new ArrayMap<>();
   xaCon.getTransaction().relLoadProperties(rel, false, newPropertyReceiver(props));
   int count = 0;
   for (int keyId : props.keySet()) {
     long id = props.get(keyId).other();
     PropertyRecord record = pStore.getRecord(id);
     PropertyBlock block = record.getPropertyBlock(props.get(keyId).first().propertyKeyId());
     DefinedProperty data = block.newPropertyData(pStore);
     if (data.propertyKeyId() == prop1.propertyKeyId()) {
       assertEquals("prop1", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals("-string1", data.value());
     } else if (data.propertyKeyId() == prop2.propertyKeyId()) {
       assertEquals("prop2", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(-1, data.value());
     } else if (data.propertyKeyId() == prop3.propertyKeyId()) {
       assertEquals("prop3", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(false, data.value());
       xaCon.getTransaction().relRemoveProperty(rel, prop3.propertyKeyId());
     } else {
       throw new IOException();
     }
     count++;
   }
   assertEquals(3, count);
   CountingPropertyReceiver propertyCounter = new CountingPropertyReceiver();
   xaCon.getTransaction().relLoadProperties(rel, false, propertyCounter);
   assertEquals(3, propertyCounter.count);
   RelationshipRecord relData = xaCon.getTransaction().relLoadLight(rel);
   assertEquals(firstNode, relData.getFirstNode());
   assertEquals(secondNode, relData.getSecondNode());
   assertEquals(relType, relData.getType());
   xaCon.getTransaction().relDelete(rel);
   MutableRelationshipLoadingPosition firstPos = getPosition(xaCon, firstNode);
   Iterator<RelationshipRecord> first = getMore(xaCon, firstNode, firstPos).iterator();
   first.next();
   MutableRelationshipLoadingPosition secondPos = getPosition(xaCon, secondNode);
   Iterator<RelationshipRecord> second = getMore(xaCon, secondNode, secondPos).iterator();
   second.next();
   assertTrue(first.hasNext());
   assertTrue(second.hasNext());
 }
Example #8
0
  public static boolean encode(
      int keyId, Object array, PropertyBlock target, int payloadSizeInBytes) {
    /*
     *  If the array is huge, we don't have to check anything else.
     *  So do the length check first.
     */
    int arrayLength = Array.getLength(array);
    if (arrayLength > 63) /*because we only use 6 bits for length*/ {
      return false;
    }

    ShortArray type = typeOf(array);
    if (type == null) {
      return false;
    }

    int requiredBits = type.calculateRequiredBitsForArray(array, arrayLength);
    if (!willFit(requiredBits, arrayLength, payloadSizeInBytes)) {
      // Too big array
      return false;
    }
    final int numberOfBytes = calculateNumberOfBlocksUsed(arrayLength, requiredBits) * 8;
    if (Bits.requiredLongs(numberOfBytes) > PropertyType.getPayloadSizeLongs()) {
      return false;
    }
    Bits result = Bits.bits(numberOfBytes);
    // [][][    ,bbbb][bbll,llll][yyyy,tttt][kkkk,kkkk][kkkk,kkkk][kkkk,kkkk]
    writeHeader(keyId, type, arrayLength, requiredBits, result);
    type.writeAll(array, arrayLength, requiredBits, result);
    target.setValueBlocks(result.getLongs());
    return true;
  }
Example #9
0
 /*
  * It is assumed that the argument does hold a property block - all zeros is
  * a valid (not in use) block, so even if the Bits object has been exhausted a
  * result is returned, that has inUse() return false. Also, the argument is not
  * touched.
  */
 private PropertyBlock getPropertyBlock(Buffer buffer) {
   long header = buffer.getLong();
   PropertyType type = PropertyType.getPropertyType(header, true);
   if (type == null) {
     return null;
   }
   PropertyBlock toReturn = new PropertyBlock();
   // toReturn.setInUse( true );
   int numBlocks = type.calculateNumberOfBlocksUsed(header);
   long[] blockData = new long[numBlocks];
   blockData[0] = header; // we already have that
   for (int i = 1; i < numBlocks; i++) {
     blockData[i] = buffer.getLong();
   }
   toReturn.setValueBlocks(blockData);
   return toReturn;
 }
Example #10
0
 public PropertyRecord getRecord(long id) {
   PropertyRecord record;
   PersistenceWindow window = acquireWindow(id, OperationType.READ);
   try {
     record = getRecord(id, window, RecordLoad.NORMAL);
   } finally {
     releaseWindow(window);
   }
   for (PropertyBlock block : record.getPropertyBlocks()) {
     // assert block.inUse();
     if (block.getType() == PropertyType.STRING) {
       Collection<DynamicRecord> stringRecords =
           stringPropertyStore.getLightRecords(block.getSingleValueLong());
       for (DynamicRecord stringRecord : stringRecords) {
         stringRecord.setType(PropertyType.STRING.intValue());
         block.addValueRecord(stringRecord);
       }
     } else if (block.getType() == PropertyType.ARRAY) {
       Collection<DynamicRecord> arrayRecords =
           arrayPropertyStore.getLightRecords(block.getSingleValueLong());
       for (DynamicRecord arrayRecord : arrayRecords) {
         arrayRecord.setType(PropertyType.ARRAY.intValue());
         block.addValueRecord(arrayRecord);
       }
     }
   }
   return record;
 }
Example #11
0
 public static Object decode(PropertyBlock block) {
   Bits bits =
       Bits.bitsFromLongs(Arrays.copyOf(block.getValueBlocks(), block.getValueBlocks().length));
   // [][][    ,bbbb][bbll,llll][yyyy,tttt][kkkk,kkkk][kkkk,kkkk][kkkk,kkkk]
   bits.getInt(24); // Get rid of key
   bits.getByte(4); // Get rid of short array type
   int typeId = bits.getByte(4);
   int arrayLength = bits.getByte(6);
   int requiredBits = bits.getByte(6);
   /*
    * So, it can be the case that values require 64 bits to store. However, you cannot encode this
    * value with 6 bits. calculateRequiredBitsForArray never returns 0, because even for an array of
    * all 0s one bit is required for every value. So when writing, we let it overflow and write out
    * 0. When we are reading back, we just have to make sure that reading in 0 means 64.
    */
   if (requiredBits == 0) {
     requiredBits = 64;
   }
   ShortArray type = typeOf((byte) typeId);
   return type.createArray(arrayLength, bits, requiredBits);
 }
Example #12
0
 private void validateRel2(
     long rel,
     DefinedProperty prop1,
     DefinedProperty prop2,
     DefinedProperty prop3,
     long firstNode,
     long secondNode,
     int relType)
     throws IOException {
   ArrayMap<Integer, Pair<DefinedProperty, Long>> props = new ArrayMap<>();
   xaCon.getTransaction().relLoadProperties(rel, false, newPropertyReceiver(props));
   int count = 0;
   for (int keyId : props.keySet()) {
     long id = props.get(keyId).other();
     PropertyRecord record = pStore.getRecord(id);
     PropertyBlock block = record.getPropertyBlock(props.get(keyId).first().propertyKeyId());
     DefinedProperty data = block.newPropertyData(pStore);
     if (data.propertyKeyId() == prop1.propertyKeyId()) {
       assertEquals("prop1", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals("string2", data.value());
       xaCon.getTransaction().relChangeProperty(rel, prop1.propertyKeyId(), "-string2");
     } else if (data.propertyKeyId() == prop2.propertyKeyId()) {
       assertEquals("prop2", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(2, data.value());
       xaCon.getTransaction().relChangeProperty(rel, prop2.propertyKeyId(), new Integer(-2));
     } else if (data.propertyKeyId() == prop3.propertyKeyId()) {
       assertEquals("prop3", MyPropertyKeyToken.getIndexFor(keyId).name());
       assertEquals(false, data.value());
       xaCon.getTransaction().relChangeProperty(rel, prop3.propertyKeyId(), true);
     } else {
       throw new IOException();
     }
     count++;
   }
   assertEquals(3, count);
   RelationshipRecord relData = xaCon.getTransaction().relLoadLight(rel);
   assertEquals(firstNode, relData.getFirstNode());
   assertEquals(secondNode, relData.getSecondNode());
   assertEquals(relType, relData.getType());
 }
Example #13
0
 /*
  * This will add the value records without checking if they are already
  * in the block - so make sure to call this after checking isHeavy() or
  * you will end up with duplicates.
  */
 public void makeHeavy(PropertyBlock record) {
   if (record.getType() == PropertyType.STRING) {
     Collection<DynamicRecord> stringRecords =
         stringPropertyStore.getLightRecords(record.getSingleValueLong());
     for (DynamicRecord stringRecord : stringRecords) {
       stringRecord.setType(PropertyType.STRING.intValue());
       record.addValueRecord(stringRecord);
     }
   } else if (record.getType() == PropertyType.ARRAY) {
     Collection<DynamicRecord> arrayRecords =
         arrayPropertyStore.getLightRecords(record.getSingleValueLong());
     for (DynamicRecord arrayRecord : arrayRecords) {
       arrayRecord.setType(PropertyType.ARRAY.intValue());
       record.addValueRecord(arrayRecord);
     }
   }
 }
Example #14
0
 public void makeHeavyIfLight(PropertyBlock record) {
   if (record.isLight()) {
     /*
      * This will add the value records without checking if they are already
      * in the block - so we only call this after checking isLight() or
      * else we will end up with duplicates.
      */
     if (record.getType() == PropertyType.STRING) {
       Collection<DynamicRecord> stringRecords =
           stringPropertyStore.getLightRecords(record.getSingleValueLong());
       for (DynamicRecord stringRecord : stringRecords) {
         stringRecord.setType(PropertyType.STRING.intValue());
         record.addValueRecord(stringRecord);
       }
     } else if (record.getType() == PropertyType.ARRAY) {
       Collection<DynamicRecord> arrayRecords =
           arrayPropertyStore.getLightRecords(record.getSingleValueLong());
       for (DynamicRecord arrayRecord : arrayRecords) {
         arrayRecord.setType(PropertyType.ARRAY.intValue());
         record.addValueRecord(arrayRecord);
       }
     }
   }
 }
Example #15
0
 public static Object getStringFor(AbstractDynamicStore store, PropertyBlock propertyBlock) {
   return getStringFor(store, propertyBlock.getSingleValueLong(), propertyBlock.getValueRecords());
 }
Example #16
0
  public void encodeValue(PropertyBlock block, int keyId, Object value) {
    if (value instanceof String) { // Try short string first, i.e. inlined in the property block
      String string = (String) value;
      if (LongerShortString.encode(keyId, string, block, PropertyType.getPayloadSize())) return;

      // Fall back to dynamic string store
      long stringBlockId = nextStringBlockId();
      setSingleBlockValue(block, keyId, PropertyType.STRING, stringBlockId);
      byte[] encodedString = encodeString(string);
      Collection<DynamicRecord> valueRecords = allocateStringRecords(stringBlockId, encodedString);
      for (DynamicRecord valueRecord : valueRecords) {
        valueRecord.setType(PropertyType.STRING.intValue());
        block.addValueRecord(valueRecord);
      }
    } else if (value instanceof Integer)
      setSingleBlockValue(block, keyId, PropertyType.INT, ((Integer) value).longValue());
    else if (value instanceof Boolean)
      setSingleBlockValue(
          block, keyId, PropertyType.BOOL, (((Boolean) value).booleanValue() ? 1L : 0L));
    else if (value instanceof Float)
      setSingleBlockValue(
          block, keyId, PropertyType.FLOAT, Float.floatToRawIntBits(((Float) value).floatValue()));
    else if (value instanceof Long) {
      long keyAndType = keyId | (((long) PropertyType.LONG.intValue()) << 24);
      if (ShortArray.LONG.getRequiredBits((Long) value)
          <= 35) { // We only need one block for this value, special layout compared to, say, an
                   // integer
        block.setSingleBlock(keyAndType | (1L << 28) | (((Long) value).longValue() << 29));
      } else { // We need two blocks for this value
        block.setValueBlocks(new long[] {keyAndType, ((Long) value).longValue()});
      }
    } else if (value instanceof Double)
      block.setValueBlocks(
          new long[] {
            keyId | (((long) PropertyType.DOUBLE.intValue()) << 24),
            Double.doubleToRawLongBits(((Double) value).doubleValue())
          });
    else if (value instanceof Byte)
      setSingleBlockValue(block, keyId, PropertyType.BYTE, ((Byte) value).longValue());
    else if (value instanceof Character)
      setSingleBlockValue(block, keyId, PropertyType.CHAR, ((Character) value).charValue());
    else if (value instanceof Short)
      setSingleBlockValue(block, keyId, PropertyType.SHORT, ((Short) value).longValue());
    else if (value
        .getClass()
        .isArray()) { // Try short array first, i.e. inlined in the property block
      if (ShortArray.encode(keyId, value, block, PropertyType.getPayloadSize())) return;

      // Fall back to dynamic array store
      long arrayBlockId = nextArrayBlockId();
      setSingleBlockValue(block, keyId, PropertyType.ARRAY, arrayBlockId);
      Collection<DynamicRecord> arrayRecords = allocateArrayRecords(arrayBlockId, value);
      for (DynamicRecord valueRecord : arrayRecords) {
        valueRecord.setType(PropertyType.ARRAY.intValue());
        block.addValueRecord(valueRecord);
      }
    } else {
      throw new IllegalArgumentException(
          "Unknown property type on: " + value + ", " + value.getClass());
    }
  }
Example #17
0
 public Object getValue(PropertyBlock propertyBlock) {
   return propertyBlock.getType().getValue(propertyBlock, this);
 }
Example #18
0
 public String getStringFor(PropertyBlock propertyBlock) {
   ensureHeavy(propertyBlock);
   return getStringFor(propertyBlock.getValueRecords());
 }
Example #19
0
 private void setSingleBlockValue(
     PropertyBlock block, int keyId, PropertyType type, long longValue) {
   block.setSingleBlock(keyId | (((long) type.intValue()) << 24) | (longValue << 28));
 }
Example #20
0
 public Object getArrayFor(PropertyBlock propertyBlock) {
   ensureHeavy(propertyBlock);
   return getArrayFor(propertyBlock.getValueRecords());
 }
Example #21
0
 public Object getArrayFor(PropertyBlock propertyBlock) {
   assert !propertyBlock.isLight();
   return getArrayFor(
       propertyBlock.getSingleValueLong(), propertyBlock.getValueRecords(), arrayPropertyStore);
 }
Example #22
0
  private void validateNodeRel2(
      long node,
      DefinedProperty prop1,
      DefinedProperty prop2,
      DefinedProperty prop3,
      long rel1,
      long rel2,
      int relType1,
      int relType2)
      throws IOException {
    NodeRecord nodeRecord = xaCon.getTransaction().nodeLoadLight(node);
    assertTrue(nodeRecord != null);
    ArrayMap<Integer, Pair<DefinedProperty, Long>> props = new ArrayMap<>();
    xaCon.getTransaction().nodeLoadProperties(node, false, newPropertyReceiver(props));
    int count = 0;
    for (int keyId : props.keySet()) {
      long id = props.get(keyId).other();
      PropertyRecord record = pStore.getRecord(id);
      PropertyBlock block = record.getPropertyBlock(props.get(keyId).first().propertyKeyId());
      DefinedProperty data = block.newPropertyData(pStore);
      if (data.propertyKeyId() == prop1.propertyKeyId()) {
        assertEquals("prop1", MyPropertyKeyToken.getIndexFor(keyId).name());
        assertEquals("string2", data.value());
        xaCon.getTransaction().nodeChangeProperty(node, prop1.propertyKeyId(), "-string2");
      } else if (data.propertyKeyId() == prop2.propertyKeyId()) {
        assertEquals("prop2", MyPropertyKeyToken.getIndexFor(keyId).name());
        assertEquals(2, data.value());
        xaCon.getTransaction().nodeChangeProperty(node, prop2.propertyKeyId(), new Integer(-2));
      } else if (data.propertyKeyId() == prop3.propertyKeyId()) {
        assertEquals("prop3", MyPropertyKeyToken.getIndexFor(keyId).name());
        assertEquals(false, data.value());
        xaCon.getTransaction().nodeChangeProperty(node, prop3.propertyKeyId(), true);
      } else {
        throw new IOException();
      }
      count++;
    }
    assertEquals(3, count);
    count = 0;

    MutableRelationshipLoadingPosition pos = getPosition(xaCon, node);
    while (true) {
      Iterable<RelationshipRecord> relData = getMore(xaCon, node, pos);
      if (!relData.iterator().hasNext()) {
        break;
      }
      for (RelationshipRecord rel : relData) {
        if (rel.getId() == rel1) {
          assertEquals(node, rel.getSecondNode());
          assertEquals(relType1, rel.getType());
        } else if (rel.getId() == rel2) {
          assertEquals(node, rel.getFirstNode());
          assertEquals(relType2, rel.getType());
        } else {
          throw new IOException();
        }
        count++;
      }
    }
    assertEquals(2, count);
  }