Пример #1
0
  private SizeSet calcSizes(long maxFreeBlocks, long chunkSize) throws Exception {
    long dataSize = chunkSize;
    SizeSet last = new SizeSet();

    log.debug("maxFreeBlocks=%d, chunkSize=%d", maxFreeBlocks, chunkSize);

    /*	Find optimal size set. Logic:
    		assume data size is 1 chunk - it will check for minimum
    			required space
    		calculate descriptor partition size to represent all data blocks
    		check if size set is valid - fits the free space (for first run it will not obviously)
    		if it is not valid - recalculate data size that is guaranteed to fit - i.e.
    				free space minus calculated descriptor partition size
    				note that after descriptor size is recalculated using this new (smaller)
    				data size, it can only be the same or smaller
    		if it is valid - check if it makes sense to continue -
    				stop if
    				1. data size is less or equal than previous known from valid
    					size set
    				2. unclaimed space (free - descriptor - data) is less than one data chunk
    		if continue - remember valid size set
    */
    while (true) {
      long descriptorSize =
          Zone64.calculateDescriptorSize(dataSize / chunkSize) / AppleDisk.BLOCK_SIZE;
      // account for backup as well and round up
      long descriptorPartitionSize =
          Utils.roundUp(descriptorSize * 2, MfsView.VOLUME_SIZE_ROUNDING);

      long unclaimedBlocks = maxFreeBlocks - (descriptorPartitionSize + dataSize);
      if (unclaimedBlocks < 0) { // combined size does not fit into free space
        if (dataSize <= chunkSize) {
          log.debug(
              "unclaimedBlocks=%d, descriptorSize=%d, descriptorPartitionSize=%d, dataSize=%d",
              unclaimedBlocks, descriptorSize, descriptorPartitionSize, dataSize);
          throw new Exception(
              "Free space is to small to accomodate necessary data - extension is impossible");
        }
      } else {
        // combined size fits - it is a valid size set
        if (last == null) last = new SizeSet();
        else {
          if (dataSize <= last.data) break;
        }
        last.partition = descriptorPartitionSize;
        last.data = dataSize;
        last.descriptor = descriptorSize;
        if (unclaimedBlocks < chunkSize) break;
      }

      dataSize = maxFreeBlocks - descriptorPartitionSize;
    }

    return last;
  }
Пример #2
0
  private Zone addZone(Mfs mfs, long logicalStartBlock, SizeSet sizes, long chunkSize)
      throws Exception {
    if ((mfs == null) || (mfs.getMfs() == null))
      throw new Exception("No MFS - MFS has not been initialized");

    List<Zone> zones = mfs.getZones();

    if ((zones == null) || zones.isEmpty())
      throw new Exception("No Zones - MFS has not been initialized");

    Zone lastZone = zones.get(zones.size() - 1);
    int baseFsPointer =
        lastZone.getInts()[0]
            - (int) lastZone.getNum() * Utils.SIZEOF_INT
            + (int) Utils.blocksToBytes(lastZone.getDescriptorSize() + 1)
            + 160;
    Zone64 z =
        new Zone64(
            logicalStartBlock, // descriptor start
            logicalStartBlock + sizes.partition, // data start
            sizes.data, // data size
            chunkSize,
            baseFsPointer);
    z.setType(ZoneType.MEDIA);

    ZoneHeader lastNext = lastZone.getNext();
    /*	just put the next pointer indicating the end into the
    	new zone and fill the previous next with pointers to the new zone
    */
    z.setNext(lastNext);
    lastZone.setNext(z.getHeader());

    mfs.addZone(z);

    return z;
  }