Lazy load binaries for reduced memory usage

This commit is contained in:
Grahame Grieve 2025-01-06 10:56:43 +11:00
parent d11b358e39
commit 12cfe341fc
2 changed files with 67 additions and 12 deletions

View File

@ -57,6 +57,7 @@ import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.BaseWorkerContext.IByteProvider;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.ILoggingService.LogCategory;
import org.hl7.fhir.r5.context.IWorkerContext.ITerminologyOperationDetails;
@ -141,6 +142,7 @@ import org.hl7.fhir.r5.utils.UserDataNames;
import org.hl7.fhir.r5.utils.client.EFhirClientException;
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
@ -148,6 +150,7 @@ import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.i18n.I18nBase;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationOptions;
@ -158,6 +161,58 @@ import javax.annotation.Nonnull;
public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext {
public interface IByteProvider {
byte[] bytes() throws IOException;
}
public class BytesProvider implements IByteProvider {
private byte[] bytes;
protected BytesProvider(byte[] bytes) {
super();
this.bytes = bytes;
}
@Override
public byte[] bytes() throws IOException {
return bytes;
}
}
public class BytesFromPackageProvider implements IByteProvider {
private NpmPackage pi;
private String name;
public BytesFromPackageProvider(NpmPackage pi, String name) {
this.pi = pi;
this.name = name;
}
@Override
public byte[] bytes() throws IOException {
return TextFile.streamToBytes(pi.load("other", name));
}
}
public class BytesFromFileProvider implements IByteProvider {
private String name;
public BytesFromFileProvider(String name) {
this.name = name;
}
@Override
public byte[] bytes() throws IOException {
return TextFile.streamToBytes(ManagedFileAccess.inStream(name));
}
}
class OIDSource {
private String folder;
private Connection db;
@ -265,7 +320,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private UcumService ucumService;
protected Map<String, byte[]> binaries = new HashMap<String, byte[]>();
protected Map<String, IByteProvider> binaries = new HashMap<String, IByteProvider>();
protected Map<String, Set<OIDDefinition>> oidCacheManual = new HashMap<>();
protected List<OIDSource> oidSources = new ArrayList<>();
@ -3137,7 +3192,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
@Override
public byte[] getBinaryForKey(String binaryKey) {
return binaries.get(binaryKey);
IByteProvider bp = binaries.get(binaryKey);
try {
return bp == null ? null : bp.bytes();
} catch (Exception e) {
throw new FHIRException(e);
}
}
public void finishLoading(boolean genSnapshots) {

View File

@ -352,7 +352,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
else if (name.equals("version.info"))
readVersionInfo(stream);
else
loadBytes(name, stream);
binaries.put(name, new BytesProvider(TextFile.streamToBytes(stream)));
}
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client, boolean useEcosystem) {
@ -572,7 +572,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
for (String s : pi.list("other")) {
binaries.put(s, TextFile.streamToBytes(pi.load("other", s)));
binaries.put(s, new BytesFromPackageProvider(pi, s));
}
if (version == null) {
version = pi.version();
@ -606,7 +606,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
private void readVersionInfo(InputStream stream) throws IOException, DefinitionException {
byte[] bytes = IOUtils.toByteArray(stream);
binaries.put("version.info", bytes);
binaries.put("version.info", new BytesProvider(bytes));
String[] vi = new String(bytes).split("\\r?\\n");
for (String s : vi) {
@ -624,11 +624,6 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
private void loadBytes(String name, InputStream stream) throws IOException {
byte[] bytes = IOUtils.toByteArray(stream);
binaries.put(name, bytes);
}
@Override
public IResourceValidator newValidator() throws FHIRException {
if (validatorFactory == null)
@ -662,13 +657,13 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
public void loadBinariesFromFolder(String folder) throws IOException {
for (String n : ManagedFileAccess.file(folder).list()) {
loadBytes(n, ManagedFileAccess.inStream(Utilities.path(folder, n)));
binaries.put(n, new BytesFromFileProvider(Utilities.path(folder, n)));
}
}
public void loadBinariesFromFolder(NpmPackage pi) throws IOException {
for (String n : pi.list("other")) {
loadBytes(n, pi.load("other", n));
binaries.put(n, new BytesFromPackageProvider(pi, n));
}
}