| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.pdfbox.io; |
| |
| import java.io.File; |
| |
| /** |
| * Controls how memory/temporary files are used for |
| * buffering streams etc. |
| */ |
| public final class MemoryUsageSetting |
| { |
| private final boolean useMainMemory; |
| private final boolean useTempFile; |
| |
| /** maximum number of main-memory bytes allowed to be used; |
| * <code>-1</code> means 'unrestricted' */ |
| private final long maxMainMemoryBytes; |
| |
| /** maximum number of bytes allowed for storage at all (main-memory+file); |
| * <code>-1</code> means 'unrestricted' */ |
| private final long maxStorageBytes; |
| |
| /** directory to be used for scratch file */ |
| private File tempDir; |
| |
| /** |
| * Private constructor for setup buffering memory usage called by one of the setup methods. |
| * |
| * @param useMainMemory if <code>true</code> main memory usage is enabled; in case of |
| * <code>false</code> and <code>useTempFile</code> is <code>false</code> too |
| * we set this to <code>true</code> |
| * @param useTempFile if <code>true</code> using of temporary file(s) is enabled |
| * @param maxMainMemoryBytes maximum number of main-memory to be used; |
| * if <code>-1</code> means 'unrestricted'; |
| * if <code>0</code> we only use temporary file if <code>useTempFile</code> |
| * is <code>true</code> otherwise main-memory usage will have restriction |
| * defined by maxStorageBytes |
| * @param maxStorageBytes maximum size the main-memory and temporary file(s) may have all together; |
| * <code>0</code> or less will be ignored; if it is less than |
| * maxMainMemoryBytes we use maxMainMemoryBytes value instead |
| */ |
| private MemoryUsageSetting(boolean useMainMemory, boolean useTempFile, |
| long maxMainMemoryBytes, long maxStorageBytes) |
| { |
| // do some checks; adjust values as needed to get consistent setting |
| boolean locUseMainMemory = useTempFile ? useMainMemory : true; |
| long locMaxMainMemoryBytes = useMainMemory ? maxMainMemoryBytes : -1; |
| long locMaxStorageBytes = maxStorageBytes > 0 ? maxStorageBytes : -1; |
| |
| if (locMaxMainMemoryBytes < -1) |
| { |
| locMaxMainMemoryBytes = -1; |
| } |
| |
| if (locUseMainMemory && (locMaxMainMemoryBytes == 0)) |
| { |
| if (useTempFile) { |
| locUseMainMemory = false; |
| } |
| else |
| { |
| locMaxMainMemoryBytes = locMaxStorageBytes; |
| } |
| } |
| |
| if (locUseMainMemory && (locMaxStorageBytes > -1) && |
| ((locMaxMainMemoryBytes == -1) || (locMaxMainMemoryBytes > locMaxStorageBytes))) |
| { |
| locMaxStorageBytes = locMaxMainMemoryBytes; |
| } |
| |
| |
| this.useMainMemory = locUseMainMemory; |
| this.useTempFile = useTempFile; |
| this.maxMainMemoryBytes = locMaxMainMemoryBytes; |
| this.maxStorageBytes = locMaxStorageBytes; |
| } |
| |
| /** |
| * Setups buffering memory usage to only use main-memory (no temporary file) |
| * which is not restricted in size. |
| */ |
| public static MemoryUsageSetting setupMainMemoryOnly() |
| { |
| return setupMainMemoryOnly(-1); |
| } |
| |
| /** |
| * Setups buffering memory usage to only use main-memory with the defined maximum. |
| * |
| * @param maxMainMemoryBytes maximum number of main-memory to be used; |
| * <code>-1</code> for no restriction; |
| * <code>0</code> will also be interpreted here as no restriction |
| */ |
| public static MemoryUsageSetting setupMainMemoryOnly(long maxMainMemoryBytes) |
| { |
| return new MemoryUsageSetting(true, false, maxMainMemoryBytes, maxMainMemoryBytes); |
| } |
| |
| /** |
| * Setups buffering memory usage to only use temporary file(s) (no main-memory) |
| * with not restricted size. |
| */ |
| public static MemoryUsageSetting setupTempFileOnly() |
| { |
| return setupTempFileOnly(-1); |
| } |
| |
| /** |
| * Setups buffering memory usage to only use temporary file(s) (no main-memory) |
| * with the specified maximum size. |
| * |
| * @param maxStorageBytes maximum size the temporary file(s) may have all together; |
| * <code>-1</code> for no restriction; |
| * <code>0</code> will also be interpreted here as no restriction |
| */ |
| public static MemoryUsageSetting setupTempFileOnly(long maxStorageBytes) |
| { |
| return new MemoryUsageSetting(false, true, 0, maxStorageBytes); |
| } |
| |
| /** |
| * Setups buffering memory usage to use a portion of main-memory and additionally |
| * temporary file(s) in case the specified portion is exceeded. |
| * |
| * @param maxMainMemoryBytes maximum number of main-memory to be used; |
| * if <code>-1</code> this is the same as {@link #setupMainMemoryOnly()}; |
| * if <code>0</code> this is the same as {@link #setupTempFileOnly()} |
| */ |
| public static MemoryUsageSetting setupMixed(long maxMainMemoryBytes) |
| { |
| return setupMixed(maxMainMemoryBytes, -1); |
| } |
| |
| /** |
| * Setups buffering memory usage to use a portion of main-memory and additionally |
| * temporary file(s) in case the specified portion is exceeded. |
| * |
| * @param maxMainMemoryBytes maximum number of main-memory to be used; |
| * if <code>-1</code> this is the same as {@link #setupMainMemoryOnly()}; |
| * if <code>0</code> this is the same as {@link #setupTempFileOnly()} |
| * @param maxStorageBytes maximum size the main-memory and temporary file(s) may have all together; |
| * <code>0</code> or less will be ignored; if it is less than |
| * maxMainMemoryBytes we use maxMainMemoryBytes value instead |
| */ |
| public static MemoryUsageSetting setupMixed(long maxMainMemoryBytes, long maxStorageBytes) |
| { |
| return new MemoryUsageSetting(true, true, maxMainMemoryBytes, maxStorageBytes); |
| } |
| |
| /** |
| * Returns a copy of this instance with the maximum memory/storage restriction |
| * divided by the provided number of parallel uses. |
| * |
| * @param parallelUseCount specifies the number of parallel usages for the setting to |
| * be returned |
| * |
| * @return a copy from this instance with the maximum memory/storage restrictions |
| * adjusted to the multiple usage |
| */ |
| public MemoryUsageSetting getPartitionedCopy(int parallelUseCount) |
| { |
| long newMaxMainMemoryBytes = maxMainMemoryBytes <= 0 ? maxMainMemoryBytes : |
| maxMainMemoryBytes / parallelUseCount; |
| long newMaxStorageBytes = maxStorageBytes <= 0 ? maxStorageBytes : |
| maxStorageBytes / parallelUseCount; |
| |
| MemoryUsageSetting copy = new MemoryUsageSetting( useMainMemory, useTempFile, |
| newMaxMainMemoryBytes, newMaxStorageBytes ); |
| copy.tempDir = tempDir; |
| |
| return copy; |
| } |
| |
| /** |
| * Sets directory to be used for temporary files. |
| * |
| * @param tempDir directory for temporary files |
| * |
| * @return this instance |
| */ |
| public MemoryUsageSetting setTempDir(File tempDir) |
| { |
| this.tempDir = tempDir; |
| return this; |
| } |
| |
| /** |
| * Returns <code>true</code> if main-memory is to be used. |
| * |
| * <p>If this returns <code>false</code> it is ensured {@link #useTempFile()} |
| * returns <code>true</code>.</p> |
| */ |
| public boolean useMainMemory() |
| { |
| return useMainMemory; |
| } |
| |
| /** |
| * Returns <code>true</code> if temporary file is to be used. |
| * |
| * <p>If this returns <code>false</code> it is ensured {@link #useMainMemory} |
| * returns <code>true</code>.</p> |
| */ |
| public boolean useTempFile() |
| { |
| return useTempFile; |
| } |
| |
| /** |
| * Returns <code>true</code> if maximum main memory is restricted to a specific |
| * number of bytes. |
| */ |
| public boolean isMainMemoryRestricted() |
| { |
| return maxMainMemoryBytes >= 0; |
| } |
| |
| /** |
| * Returns <code>true</code> if maximum amount of storage is restricted to a specific |
| * number of bytes. |
| */ |
| public boolean isStorageRestricted() |
| { |
| return maxStorageBytes > 0; |
| } |
| |
| /** |
| * Returns maximum size of main-memory in bytes to be used. |
| */ |
| public long getMaxMainMemoryBytes() |
| { |
| return maxMainMemoryBytes; |
| } |
| |
| /** |
| * Returns maximum size of storage bytes to be used |
| * (main-memory in temporary files all together). |
| */ |
| public long getMaxStorageBytes() |
| { |
| return maxStorageBytes; |
| } |
| |
| /** |
| * Returns directory to be used for temporary files or <code>null</code> |
| * if it was not set. |
| */ |
| public File getTempDir() |
| { |
| return tempDir; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return useMainMemory ? |
| (useTempFile ? "Mixed mode with max. of " + maxMainMemoryBytes + " main memory bytes" + |
| (isStorageRestricted() ? " and max. of " + maxStorageBytes + " storage bytes" : |
| " and unrestricted scratch file size") : |
| (isMainMemoryRestricted() ? "Main memory only with max. of " + maxMainMemoryBytes + " bytes" : |
| "Main memory only with no size restriction")): |
| (isStorageRestricted() ? "Scratch file only with max. of " + maxStorageBytes + " bytes" : |
| "Scratch file only with no size restriction"); |
| } |
| } |