Example #1
0
  private long createPropertyChain(Map<String, Object> properties) {
    if (properties == null || properties.isEmpty()) {
      return Record.NO_NEXT_PROPERTY.intValue();
    }
    PropertyStore propStore = getPropertyStore();
    List<PropertyRecord> propRecords = new ArrayList<PropertyRecord>();
    PropertyRecord currentRecord = new PropertyRecord(propStore.nextId());
    currentRecord.setInUse(true);
    currentRecord.setCreated();
    propRecords.add(currentRecord);
    for (Entry<String, Object> entry : properties.entrySet()) {
      int keyId = indexHolder.getKeyId(entry.getKey());
      if (keyId == -1) {
        keyId = createNewPropertyIndex(entry.getKey());
      }

      PropertyBlock block = new PropertyBlock();
      propStore.encodeValue(block, keyId, entry.getValue());
      if (currentRecord.size() + block.getSize() > PropertyType.getPayloadSize()) {
        // Here it means the current block is done for
        PropertyRecord prevRecord = currentRecord;
        // Create new record
        long propertyId = propStore.nextId();
        currentRecord = new PropertyRecord(propertyId);
        currentRecord.setInUse(true);
        currentRecord.setCreated();
        // Set up links
        prevRecord.setNextProp(propertyId);
        currentRecord.setPrevProp(prevRecord.getId());
        propRecords.add(currentRecord);
        // Now current is ready to start picking up blocks
      }
      currentRecord.addPropertyBlock(block);
    }
    /*
     * Add the property records in reverse order, which means largest
     * id first. That is to make sure we expand the property store file
     * only once.
     */
    for (int i = propRecords.size() - 1; i >= 0; i--) {
      propStore.updateRecord(propRecords.get(i));
    }
    /*
     *  0 will always exist, if the map was empty we wouldn't be here
     *  and even one property will create at least one record.
     */
    return propRecords.get(0).getId();
  }
Example #2
0
  /** @return true if the passed primitive needs updating in the store. */
  private boolean setPrimitiveProperty(PrimitiveRecord primitive, String name, Object value) {
    boolean result = false;
    long nextProp = primitive.getNextProp();
    int index = indexHolder.getKeyId(name);

    if (index == -1) {
      index = createNewPropertyIndex(name);
    }
    PropertyBlock block = new PropertyBlock();
    getPropertyStore().encodeValue(block, index, value);
    int size = block.getSize();

    /*
     * current is the current record traversed
     * thatFits is the earliest record that can host the block
     * thatHas is the record that already has a block for this index
     */
    PropertyRecord current = null, thatFits = null, thatHas = null;
    /*
     * We keep going while there are records or until we both found the
     * property if it exists and the place to put it, if exists.
     */
    while (!(nextProp == Record.NO_NEXT_PROPERTY.intValue()
        || (thatHas != null && thatFits != null))) {
      current = getPropertyStore().getRecord(nextProp);
      /*
       * current.getPropertyBlock() is cheap but not free. If we already
       * have found thatHas, then we can skip this lookup.
       */
      if (thatHas == null && current.getPropertyBlock(index) != null) {
        thatHas = current;
        PropertyBlock removed = thatHas.removePropertyBlock(index);
        if (removed.isLight()) {
          getPropertyStore().makeHeavy(removed);
          for (DynamicRecord dynRec : removed.getValueRecords()) {
            thatHas.addDeletedRecord(dynRec);
          }
        }
        getPropertyStore().updateRecord(thatHas);
      }
      /*
       * We check the size after we remove - potentially we can put in the same record.
       *
       * current.size() is cheap but not free. If we already found somewhere
       * where it fits, no need to look again.
       */
      if (thatFits == null && (PropertyType.getPayloadSize() - current.size() >= size)) {
        thatFits = current;
      }
      nextProp = current.getNextProp();
    }
    /*
     * thatHas is of no importance here. We know that the block is definitely not there.
     * However, we can be sure that if the property existed, thatHas is not null and does
     * not contain the block.
     *
     * thatFits is interesting. If null, we need to create a new record and link, otherwise
     * just add the block there.
     */
    if (thatFits == null) {
      thatFits = new PropertyRecord(getPropertyStore().nextId());
      thatFits.setInUse(true);
      result = true;

      if (primitive.getNextProp() != Record.NO_NEXT_PROPERTY.intValue()) {
        PropertyRecord first = getPropertyStore().getRecord(primitive.getNextProp());
        thatFits.setNextProp(first.getId());
        first.setPrevProp(thatFits.getId());
        getPropertyStore().updateRecord(first);
      }
      primitive.setNextProp(thatFits.getId());
    }
    thatFits.addPropertyBlock(block);
    getPropertyStore().updateRecord(thatFits);
    return result;
  }