if (wholeSize.getSizeFilesNoLimit() < maxSize) {
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof ManifestElement) {
ManifestElement me = (ManifestElement)o;
containerBuilder.addItem(name, prefix+name, me, name.equals(defaultName));
} else {
tmpSize += 512;
}
}
tmpSize += wholeSize.getSizeFilesNoLimit();
} else {
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof ManifestElement) {
ManifestElement me = (ManifestElement)o;
if (me.getSize() > DEFAULT_MAX_CONTAINERITEMSIZE)
containerBuilder.addExternal(name, me.getData(), me.getMimeTypeOverride(), name.equals(defaultName));
else
containerBuilder.addItem(name, prefix+name, me, name.equals(defaultName));
} else {
tmpSize += 512;
}
}
tmpSize += wholeSize.getSizeFiles();
}
// now fill up with stuff from sub's
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
// 512 bytes for the dir entry already included in tmpSize.
if (o instanceof HashMap) {
@SuppressWarnings("unchecked")
HashMap<String, Object> hm = (HashMap<String, Object>)o;
// It will be possible to make it fit provided there is at least space for every subdir and file to be a redirect/external.
if (tmpSize < maxSize - (512 * hm.size())) {
// FIXME do we need 512 bytes for the dir entry here?
containerBuilder.pushCurrentDir();
containerBuilder.makeSubDirCD(name);
tmpSize += makePutHandlers(containerBuilder, hm, defaultName, "", maxSize-tmpSize, name);
containerBuilder.popCurrentDir();
} else {
// We definitely need the 512 bytes for the dir entry here.
ContainerBuilder subC = containerBuilder.makeSubContainer(name);
makePutHandlers(subC, hm, defaultName, "", DEFAULT_MAX_CONTAINERSIZE, name);
}
}
}
return tmpSize;
}
HashMap<String, Object> itemsLeft = new HashMap<String, Object>();
// Space used by regular files if they are all put in as redirects.
int minUsageForFiles = 0;
// Redirects have to go first since we can't move them.
{
Iterator<Map.Entry<String, Object>> iter = manifestElements.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, Object> entry = iter.next();
String name = entry.getKey();
Object o = entry.getValue();
if(o instanceof ManifestElement) {
ManifestElement me = (ManifestElement) o;
if(me.getTargetURI() != null) {
tmpSize += 512;
containerBuilder.addItem(name, prefix+name, me, name.equals(defaultName));
iter.remove();
} else {
minUsageForFiles += 512;
}
}
}
}
// (last) step three
// all subdirs fit into current container?
if ((wholeSize.getSizeSubTrees() + tmpSize + minUsageForFiles < maxSize) || (wholeSize.getSizeSubTreesNoLimit() + tmpSize + minUsageForFiles < maxSize)) {
//all subdirs fit into current container, do it
// and add files up to limit
if(logMINOR)
Logger.minor(this, "PackStat2: the sub dirs fit into container with spare, so it need to grab files to fill container up");
if (wholeSize.getSizeSubTreesNoLimit() + tmpSize + minUsageForFiles < maxSize) {
if(logMINOR) Logger.minor(this, " (unlimited)");
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof HashMap) {
@SuppressWarnings("unchecked")
HashMap<String, Object> hm = (HashMap<String, Object>)o;
containerBuilder.pushCurrentDir();
containerBuilder.makeSubDirCD(name);
makeEveryThingUnlimitedPutHandlers(containerBuilder, hm, defaultName, prefix);
containerBuilder.popCurrentDir();
}
}
tmpSize = wholeSize.getSizeSubTreesNoLimit();
} else {
if(logMINOR) Logger.minor(this, " (limited)");
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof HashMap) {
@SuppressWarnings("unchecked")
HashMap<String, Object> hm = (HashMap<String, Object>)o;
containerBuilder.pushCurrentDir();
containerBuilder.makeSubDirCD(name);
makeEveryThingPutHandlers(containerBuilder, hm, defaultName, prefix);
containerBuilder.popCurrentDir();
}
}
tmpSize = wholeSize.getSizeSubTrees();
}
} else {
// sub dirs does not fit into container, make each its own
if(logMINOR)
Logger.minor(this, "PackStat2: sub dirs does not fit into container, make each its own");
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof HashMap) {
@SuppressWarnings("unchecked")
HashMap<String, Object> hm = (HashMap<String, Object>)o;
ContainerBuilder subC = containerBuilder.makeSubContainer(name);
makePutHandlers(subC, hm, defaultName, "", DEFAULT_MAX_CONTAINERSIZE, name);
tmpSize += 512;
}
}
}
// fill up container with files
for(Map.Entry<String, Object> entry:manifestElements.entrySet()) {
String name = entry.getKey();
Object o = entry.getValue();
if (o instanceof ManifestElement) {
ManifestElement me = (ManifestElement)o;
long size = ContainerSizeEstimator.tarItemSize(me.getSize());
if ((me.getSize() <= DEFAULT_MAX_CONTAINERITEMSIZE) &&
(size < (maxSize-(tmpSize+minUsageForFiles-512 /* this one */)))) {
containerBuilder.addItem(name, prefix+name, me, name.equals(defaultName));
tmpSize += size;
minUsageForFiles -= 512;
} else {
tmpSize += 512;
minUsageForFiles -= 512;
itemsLeft.put(name, me);
}
}
}
assert(minUsageForFiles == 0);
if(tmpSize > maxSize)
throw new TooManyFilesInsertException();
// group files left into external archives ('CHK@.../name' redirects)
while (!itemsLeft.isEmpty()) {
if(logMINOR)
Logger.minor(this, "ItemsLeft checker: "+itemsLeft.size());
if (itemsLeft.size() == 1) {
// one item left, make it external
for(Map.Entry<String, Object> entry:itemsLeft.entrySet()) {
String lname = entry.getKey();
ManifestElement me = (ManifestElement)entry.getValue();
// It could still be a redirect, use addElement().
containerBuilder.addElement(lname, me, lname.equals(defaultName));
}
itemsLeft.clear();
continue;
}
final long leftLimit = DEFAULT_MAX_CONTAINERSIZE - DEFAULT_CONTAINERSIZE_SPARE;
ContainerSize leftSize = ContainerSizeEstimator.getSubTreeSize(itemsLeft, DEFAULT_MAX_CONTAINERITEMSIZE, leftLimit, 0);
if ((leftSize.getSizeFiles() > 0) && (leftSize.getSizeFilesNoLimit() <= leftLimit)) {
// possible container items are left, and everything fits into single archive
// do it.
ContainerBuilder archive = makeArchive();
for(Map.Entry<String, Object> entry:itemsLeft.entrySet()) {
String lname = entry.getKey();
ManifestElement me = (ManifestElement)entry.getValue();
containerBuilder.addArchiveItem(archive, lname, me, lname.equals(defaultName));
}
itemsLeft.clear();
continue;
}
// getSizeFiles() includes 512 bytes for each file over the size limit
if (((leftSize.getSizeFiles() - (512*itemsLeft.size())) == 0) && (leftSize.getSizeFilesNoLimit() > 0)) {
// all items left are to big (or redirect), make all external
for(Map.Entry<String, Object> entry:itemsLeft.entrySet()) {
String lname = entry.getKey();
ManifestElement me = (ManifestElement)entry.getValue();
containerBuilder.addElement(lname, me, lname.equals(defaultName));
}
itemsLeft.clear();
continue;
}
// fill up a archive
long archiveLimit = DEFAULT_CONTAINERSIZE_SPARE;
ContainerBuilder archive = makeArchive();
Iterator<Map.Entry<String, Object> > iter = itemsLeft.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Object> entry = iter.next();
String lname = entry.getKey();
ManifestElement me = (ManifestElement)entry.getValue();
if ((me.getSize() > -1) && (me.getSize() <= DEFAULT_MAX_CONTAINERITEMSIZE) && (me.getSize() < (DEFAULT_MAX_CONTAINERSIZE-archiveLimit))) {
containerBuilder.addArchiveItem(archive, lname, me, lname.equals(defaultName));
tmpSize += 512;
archiveLimit += ContainerSizeEstimator.tarItemSize(me.getSize());
iter.remove();
}
}
}
return tmpSize;