Skip to content

Commit 13a66a1

Browse files
committed
change logic to use streams for package data attributes instead of loading into ram
1 parent 2109840 commit 13a66a1

File tree

8 files changed

+156
-26
lines changed

8 files changed

+156
-26
lines changed

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/heap/HeapCoordinates.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2019, Andrew Lindesay
2+
* Copyright 2013-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

@@ -36,6 +36,10 @@ public long getLength() {
3636
return length;
3737
}
3838

39+
public boolean isEmpty() {
40+
return 0L == length;
41+
}
42+
3943
@SuppressWarnings("RedundantIfStatement") // was auto-generated!
4044
@Override
4145
public boolean equals(Object o) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2021, Andrew Lindesay
3+
* Distributed under the terms of the MIT License.
4+
*/
5+
6+
package org.haiku.pkg.heap;
7+
8+
import com.google.common.base.Preconditions;
9+
10+
import java.io.IOException;
11+
import java.io.InputStream;
12+
13+
public class HeapInputStream extends InputStream {
14+
15+
private final HeapReader reader;
16+
17+
private final HeapCoordinates coordinates;
18+
19+
private long offsetInCoordinates = 0L;
20+
21+
public HeapInputStream(HeapReader reader, HeapCoordinates coordinates) {
22+
this.reader = Preconditions.checkNotNull(reader);
23+
this.coordinates = Preconditions.checkNotNull(coordinates);
24+
}
25+
26+
@Override
27+
public int read() throws IOException {
28+
if (offsetInCoordinates < coordinates.getLength()) {
29+
int result = reader.readHeap(coordinates.getOffset() + offsetInCoordinates);
30+
offsetInCoordinates++;
31+
return result;
32+
}
33+
34+
return -1;
35+
}
36+
37+
@Override
38+
public int read(byte[] b, int off, int len) throws IOException {
39+
Preconditions.checkArgument(null != b, "buffer required");
40+
Preconditions.checkArgument(off >= 0, "bad offset supplied");
41+
Preconditions.checkArgument(len >= 0, "bad length supplied");
42+
43+
if (len + offsetInCoordinates >= coordinates.getLength()) {
44+
len = (int) (coordinates.getLength() - offsetInCoordinates);
45+
}
46+
47+
if (0 == len) {
48+
return -1;
49+
}
50+
51+
HeapCoordinates readCoordinates = new HeapCoordinates(
52+
coordinates.getOffset() + offsetInCoordinates, len);
53+
54+
reader.readHeap(b, off, readCoordinates);
55+
offsetInCoordinates += len;
56+
57+
return len;
58+
}
59+
}

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/model/Attribute.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018-2019, Andrew Lindesay
2+
* Copyright 2018-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

@@ -8,9 +8,7 @@
88
import com.google.common.base.Preconditions;
99
import com.google.common.collect.ImmutableList;
1010
import org.haiku.pkg.AttributeContext;
11-
import org.haiku.pkg.HpkException;
1211

13-
import java.util.ArrayList;
1412
import java.util.Collections;
1513
import java.util.List;
1614
import java.util.Optional;
@@ -22,7 +20,7 @@
2220

2321
public abstract class Attribute {
2422

25-
private AttributeId attributeId;
23+
private final AttributeId attributeId;
2624

2725
private List<Attribute> childAttributes = Collections.emptyList();
2826

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/model/PkgArchitecture.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014, Andrew Lindesay
2+
* Copyright 2013-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

@@ -19,5 +19,7 @@ public enum PkgArchitecture {
1919
PPC, // 5
2020
ARM, // 6
2121
M68K, // 7
22-
SPARC // 8
22+
SPARC, // 8
23+
ARM64, // 9
24+
RISCV64 // 10
2325
}

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/model/RawHeapAttribute.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
/*
2-
* Copyright 2018, Andrew Lindesay
2+
* Copyright 2018-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

66
package org.haiku.pkg.model;
77

88
import com.google.common.base.Preconditions;
9+
import com.google.common.io.ByteSource;
910
import org.haiku.pkg.AttributeContext;
10-
import org.haiku.pkg.HpkException;
1111
import org.haiku.pkg.heap.HeapCoordinates;
12+
import org.haiku.pkg.heap.HeapInputStream;
13+
import org.haiku.pkg.heap.HeapReader;
14+
15+
import java.io.IOException;
16+
import java.io.InputStream;
1217

1318
/**
1419
* <p>This type of attribute refers to raw data. It uses coordinates into the heap to provide a source for the
@@ -44,10 +49,8 @@ public int hashCode() {
4449
}
4550

4651
@Override
47-
public byte[] getValue(AttributeContext context) {
48-
byte[] buffer = new byte[(int) heapCoordinates.getLength()];
49-
context.getHeapReader().readHeap(buffer, 0, heapCoordinates);
50-
return buffer;
52+
public ByteSource getValue(AttributeContext context) {
53+
return new HeapByteSource(context.getHeapReader(), heapCoordinates);
5154
}
5255

5356
@Override
@@ -60,4 +63,26 @@ public String toString() {
6063
return String.format("%s : @%s",super.toString(),heapCoordinates.toString());
6164
}
6265

66+
private static class HeapByteSource extends ByteSource {
67+
68+
private final HeapReader heapReader;
69+
private final HeapCoordinates heapCoordinates;
70+
71+
public HeapByteSource(HeapReader heapReader, HeapCoordinates heapCoordinates) {
72+
this.heapCoordinates = heapCoordinates;
73+
this.heapReader = heapReader;
74+
}
75+
76+
@Override
77+
public InputStream openStream() throws IOException {
78+
return new HeapInputStream(heapReader, heapCoordinates);
79+
}
80+
81+
@Override
82+
public com.google.common.base.Optional<Long> sizeIfKnown() {
83+
return com.google.common.base.Optional.of(heapCoordinates.getLength());
84+
}
85+
86+
}
87+
6388
}

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/model/RawInlineAttribute.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
/*
2-
* Copyright 2018, Andrew Lindesay
2+
* Copyright 2018-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

66
package org.haiku.pkg.model;
77

88
import com.google.common.base.Preconditions;
9+
import com.google.common.io.ByteSource;
910
import org.haiku.pkg.AttributeContext;
1011

1112
import java.util.Arrays;
1213

1314
public class RawInlineAttribute extends RawAttribute {
1415

15-
private byte[] rawValue;
16+
private final byte[] rawValue;
1617

1718
public RawInlineAttribute(AttributeId attributeId, byte[] rawValue) {
1819
super(attributeId);
@@ -39,8 +40,8 @@ public int hashCode() {
3940
}
4041

4142
@Override
42-
public byte[] getValue(AttributeContext context) {
43-
return rawValue;
43+
public ByteSource getValue(AttributeContext context) {
44+
return ByteSource.wrap(rawValue);
4445
}
4546

4647
@Override

haikudepotserver-packagefile/src/main/java/org/haiku/pkg/output/AttributeWriter.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/*
2-
* Copyright 2018, Andrew Lindesay
2+
* Copyright 2018-2021, Andrew Lindesay
33
* Distributed under the terms of the MIT License.
44
*/
55

66
package org.haiku.pkg.output;
77

88
import com.google.common.base.Preconditions;
9+
import com.google.common.io.ByteSource;
910
import org.haiku.pkg.AttributeContext;
1011
import org.haiku.pkg.HpkException;
1112
import org.haiku.pkg.model.Attribute;
@@ -43,24 +44,19 @@ private void write(int indent, AttributeContext context, Attribute attribute) th
4344

4445
try {
4546
switch (attribute.getAttributeType()) {
46-
4747
case RAW:
48-
byte[] data = (byte[]) attribute.getValue(context);
49-
write(String.format("%d bytes",data.length));
48+
ByteSource byteSource = (ByteSource) attribute.getValue(context);
49+
write(String.format("%d bytes", byteSource.size()));
5050
break;
51-
5251
case INT:
5352
write(attribute.getValue(context).toString());
5453
break;
55-
5654
case STRING:
5755
write(attribute.getValue(context).toString());
5856
break;
59-
6057
default:
6158
write("???");
6259
break;
63-
6460
}
6561
}
6662
catch (HpkException e) {

haikudepotserver-packagefile/src/test/java/org/haiku/pkg/HpkgFileExtractorAttributeTest.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1+
/*
2+
* Copyright 2021, Andrew Lindesay
3+
* Distributed under the terms of the MIT License.
4+
*/
5+
16
package org.haiku.pkg;
27

8+
import com.google.common.base.Preconditions;
9+
import com.google.common.hash.HashCode;
10+
import com.google.common.hash.Hashing;
11+
import com.google.common.io.ByteSource;
312
import org.fest.assertions.Assertions;
4-
import org.haiku.pkg.model.*;
13+
import org.haiku.pkg.model.Attribute;
14+
import org.haiku.pkg.model.AttributeId;
15+
import org.haiku.pkg.model.AttributeType;
16+
import org.haiku.pkg.model.IntAttribute;
517
import org.junit.Test;
618

719
import java.io.File;
820
import java.util.ArrayList;
921
import java.util.List;
22+
import java.util.Locale;
23+
import java.util.Optional;
1024

1125
public class HpkgFileExtractorAttributeTest extends AbstractHpkTest {
1226

@@ -32,8 +46,39 @@ public void testReadFile() throws Exception {
3246
Assertions.assertThat(summaryAttribute.getAttributeId()).isEqualTo(AttributeId.PACKAGE_SUMMARY);
3347
Assertions.assertThat(summaryAttribute.getAttributeType()).isEqualTo(AttributeType.STRING);
3448
Assertions.assertThat(summaryAttribute.getValue(packageAttributeContext)).isEqualTo("An application to display Haiku usage tips");
49+
50+
// Pull out the actual binary to check. The expected data results were obtained
51+
// from a Haiku host with the package installed.
52+
Attribute binaryDirectoryEntry = findByDirectoryEntries(tocAttributes, tocContext, List.of("apps", "Tipster"));
53+
Attribute binaryData = binaryDirectoryEntry.getChildAttribute(AttributeId.DATA);
54+
ByteSource binaryDataByteSource = (ByteSource) binaryData.getValue(tocContext);
55+
Assertions.assertThat(binaryDataByteSource.size()).isEqualTo(153840L);
56+
HashCode hashCode = binaryDataByteSource.hash(Hashing.md5());
57+
Assertions.assertThat(hashCode.toString().toLowerCase(Locale.ROOT)).isEqualTo("13b16cd7d035ddda09a744c49a8ebdf2");
58+
}
59+
}
60+
61+
private Attribute findByDirectoryEntries(
62+
List<Attribute> attributes,
63+
AttributeContext context,
64+
List<String> pathComponents) {
65+
Preconditions.checkArgument(!pathComponents.isEmpty());
66+
Optional<Attribute> resultOptional = attributes.stream()
67+
.filter(a -> a.getAttributeId() == AttributeId.DIRECTORY_ENTRY)
68+
.filter(a -> a.getValue(context).equals(pathComponents.get(0)))
69+
.findFirst();
70+
71+
if (resultOptional.isPresent()) {
72+
if (1 == pathComponents.size()) {
73+
return resultOptional.get();
74+
}
75+
return findByDirectoryEntries(
76+
resultOptional.get().getChildAttributes(),
77+
context,
78+
pathComponents.subList(1, pathComponents.size()));
3579
}
3680

81+
throw new AssertionError("unable to find the diretory entry [" + pathComponents.get(0) + "]");
3782
}
3883

3984
private List<Attribute> toList(AttributeIterator attributeIterator) {

0 commit comments

Comments
 (0)