This is an automated email from the ASF dual-hosted git repository.
soumyava pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 4149c9422cf cleanup temp files for nested column serializer (#15236)
4149c9422cf is described below
commit 4149c9422cf31a8f35f498a9f03afd312f495ac6
Author: Clint Wylie <[email protected]>
AuthorDate: Tue Oct 24 15:30:00 2023 -0700
cleanup temp files for nested column serializer (#15236)
* cleanup temp files for nested column serializer
* fix style
* fix tests in default value mode
---
.../apache/druid/java/util/common/FileUtils.java | 21 ++-
.../druid/segment/nested/DictionaryIdLookup.java | 57 +++++--
.../segment/nested/NestedDataColumnSerializer.java | 2 +
.../nested/NestedDataColumnSerializerV4.java | 2 +
.../nested/ScalarDoubleColumnSerializer.java | 2 +
.../segment/nested/ScalarLongColumnSerializer.java | 2 +
.../nested/ScalarStringColumnSerializer.java | 2 +
.../segment/nested/VariantColumnSerializer.java | 2 +
.../druid/java/util/common/FileUtilsTest.java | 68 ++++----
.../segment/nested/DictionaryIdLookupTest.java | 177 +++++++++++++++++++++
10 files changed, 282 insertions(+), 53 deletions(-)
diff --git
a/processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java
b/processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java
index 43b6682d2c7..de66027615e 100644
--- a/processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java
+++ b/processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java
@@ -430,8 +430,12 @@ public class FileUtils
*
* @throws IllegalStateException if the directory could not be created
*/
- @SuppressForbidden(reason = "Files#createTempDirectory")
public static File createTempDir(@Nullable final String prefix)
+ {
+ return createTempDirInLocation(getTempDir(), prefix);
+ }
+
+ public static Path getTempDir()
{
final String parentDirectory = System.getProperty("java.io.tmpdir");
@@ -439,24 +443,29 @@ public class FileUtils
// Not expected.
throw new ISE("System property java.io.tmpdir is not set, cannot create
temporary directories");
}
+ return new File(parentDirectory).toPath();
+ }
+ @SuppressForbidden(reason = "Files#createTempDirectory")
+ public static File createTempDirInLocation(final Path parentDirectory,
@Nullable final String prefix)
+ {
try {
final Path tmpPath = Files.createTempDirectory(
- new File(parentDirectory).toPath(),
+ parentDirectory,
prefix == null || prefix.isEmpty() ? "druid" : prefix
);
return tmpPath.toFile();
}
catch (IOException e) {
// Some inspection to improve error messages.
- if (e instanceof NoSuchFileException && !new
File(parentDirectory).exists()) {
- throw new ISE("java.io.tmpdir (%s) does not exist", parentDirectory);
+ if (e instanceof NoSuchFileException &&
!parentDirectory.toFile().exists()) {
+ throw new ISE("Path [%s] does not exist", parentDirectory);
} else if ((e instanceof FileSystemException &&
e.getMessage().contains("Read-only file system"))
|| (e instanceof AccessDeniedException)) {
- throw new ISE("java.io.tmpdir (%s) is not writable, check
permissions", parentDirectory);
+ throw new ISE("Path [%s] is not writable, check permissions",
parentDirectory);
} else {
// Well, maybe it was something else.
- throw new ISE(e, "Failed to create temporary directory in
java.io.tmpdir (%s)", parentDirectory);
+ throw new ISE(e, "Failed to create temporary directory in path [%s]",
parentDirectory);
}
}
}
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/DictionaryIdLookup.java
b/processing/src/main/java/org/apache/druid/segment/nested/DictionaryIdLookup.java
index 4e46a1a529a..f4176db220c 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/DictionaryIdLookup.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/DictionaryIdLookup.java
@@ -56,28 +56,35 @@ import java.util.EnumSet;
public final class DictionaryIdLookup implements Closeable
{
private final String name;
+ private final Path tempBasePath;
+
@Nullable
private final DictionaryWriter<String> stringDictionaryWriter;
+ private Path stringDictionaryFile = null;
private SmooshedFileMapper stringBufferMapper = null;
private Indexed<ByteBuffer> stringDictionary = null;
@Nullable
private final DictionaryWriter<Long> longDictionaryWriter;
+ private Path longDictionaryFile = null;
private MappedByteBuffer longBuffer = null;
private FixedIndexed<Long> longDictionary = null;
@Nullable
private final DictionaryWriter<Double> doubleDictionaryWriter;
+ private Path doubleDictionaryFile = null;
MappedByteBuffer doubleBuffer = null;
FixedIndexed<Double> doubleDictionary = null;
@Nullable
private final DictionaryWriter<int[]> arrayDictionaryWriter;
+ private Path arrayDictionaryFile = null;
private MappedByteBuffer arrayBuffer = null;
private FrontCodedIntArrayIndexed arrayDictionary = null;
public DictionaryIdLookup(
String name,
+ Path tempBasePath,
@Nullable DictionaryWriter<String> stringDictionaryWriter,
@Nullable DictionaryWriter<Long> longDictionaryWriter,
@Nullable DictionaryWriter<Double> doubleDictionaryWriter,
@@ -85,6 +92,7 @@ public final class DictionaryIdLookup implements Closeable
)
{
this.name = name;
+ this.tempBasePath = tempBasePath;
this.stringDictionaryWriter = stringDictionaryWriter;
this.longDictionaryWriter = longDictionaryWriter;
this.doubleDictionaryWriter = doubleDictionaryWriter;
@@ -98,16 +106,20 @@ public final class DictionaryIdLookup implements Closeable
// for strings because of this. if other type dictionary writers could
potentially use multiple internal files
// in the future, we should transition them to using this approach as
well (or build a combination smoosher and
// mapper so that we can have a mutable smoosh)
- File stringSmoosh = FileUtils.createTempDir(StringUtils.urlEncode(name)
+ "__stringTempSmoosh");
+ File stringSmoosh = FileUtils.createTempDirInLocation(tempBasePath,
StringUtils.urlEncode(name) + "__stringTempSmoosh");
+ stringDictionaryFile = stringSmoosh.toPath();
final String fileName =
NestedCommonFormatColumnSerializer.getInternalFileName(
name,
NestedCommonFormatColumnSerializer.STRING_DICTIONARY_FILE_NAME
);
- final FileSmoosher smoosher = new FileSmoosher(stringSmoosh);
- try (final SmooshedWriter writer = smoosher.addWithSmooshedWriter(
- fileName,
- stringDictionaryWriter.getSerializedSize()
- )) {
+
+ try (
+ final FileSmoosher smoosher = new FileSmoosher(stringSmoosh);
+ final SmooshedWriter writer = smoosher.addWithSmooshedWriter(
+ fileName,
+ stringDictionaryWriter.getSerializedSize()
+ )
+ ) {
stringDictionaryWriter.writeTo(writer, smoosher);
writer.close();
smoosher.close();
@@ -134,8 +146,8 @@ public final class DictionaryIdLookup implements Closeable
public int lookupLong(@Nullable Long value)
{
if (longDictionary == null) {
- final Path longFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.LONG_DICTIONARY_FILE_NAME);
- longBuffer = mapWriter(longFile, longDictionaryWriter);
+ longDictionaryFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.LONG_DICTIONARY_FILE_NAME);
+ longBuffer = mapWriter(longDictionaryFile, longDictionaryWriter);
longDictionary = FixedIndexed.read(longBuffer, TypeStrategies.LONG,
ByteOrder.nativeOrder(), Long.BYTES).get();
// reset position
longBuffer.position(0);
@@ -150,8 +162,8 @@ public final class DictionaryIdLookup implements Closeable
public int lookupDouble(@Nullable Double value)
{
if (doubleDictionary == null) {
- final Path doubleFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.DOUBLE_DICTIONARY_FILE_NAME);
- doubleBuffer = mapWriter(doubleFile, doubleDictionaryWriter);
+ doubleDictionaryFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.DOUBLE_DICTIONARY_FILE_NAME);
+ doubleBuffer = mapWriter(doubleDictionaryFile, doubleDictionaryWriter);
doubleDictionary = FixedIndexed.read(
doubleBuffer,
TypeStrategies.DOUBLE,
@@ -171,8 +183,8 @@ public final class DictionaryIdLookup implements Closeable
public int lookupArray(@Nullable int[] value)
{
if (arrayDictionary == null) {
- final Path arrayFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.ARRAY_DICTIONARY_FILE_NAME);
- arrayBuffer = mapWriter(arrayFile, arrayDictionaryWriter);
+ arrayDictionaryFile = makeTempFile(name +
NestedCommonFormatColumnSerializer.ARRAY_DICTIONARY_FILE_NAME);
+ arrayBuffer = mapWriter(arrayDictionaryFile, arrayDictionaryWriter);
arrayDictionary = FrontCodedIntArrayIndexed.read(arrayBuffer,
ByteOrder.nativeOrder()).get();
// reset position
arrayBuffer.position(0);
@@ -213,15 +225,19 @@ public final class DictionaryIdLookup implements Closeable
{
if (stringBufferMapper != null) {
stringBufferMapper.close();
+ deleteTempFile(stringDictionaryFile);
}
if (longBuffer != null) {
ByteBufferUtils.unmap(longBuffer);
+ deleteTempFile(longDictionaryFile);
}
if (doubleBuffer != null) {
ByteBufferUtils.unmap(doubleBuffer);
+ deleteTempFile(doubleDictionaryFile);
}
if (arrayBuffer != null) {
ByteBufferUtils.unmap(arrayBuffer);
+ deleteTempFile(arrayDictionaryFile);
}
}
@@ -243,7 +259,22 @@ public final class DictionaryIdLookup implements Closeable
private Path makeTempFile(String name)
{
try {
- return Files.createTempFile(StringUtils.urlEncode(name), null);
+ return Files.createTempFile(tempBasePath, StringUtils.urlEncode(name),
null);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void deleteTempFile(Path path)
+ {
+ try {
+ final File file = path.toFile();
+ if (file.isDirectory()) {
+ FileUtils.deleteDirectory(file);
+ } else {
+ Files.delete(path);
+ }
}
catch (IOException e) {
throw new RuntimeException(e);
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializer.java
b/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializer.java
index 098b6103495..bcab3edd889 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializer.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializer.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Maps;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.collections.bitmap.MutableBitmap;
import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.RE;
import org.apache.druid.java.util.common.io.Closer;
@@ -234,6 +235,7 @@ public class NestedDataColumnSerializer extends
NestedCommonFormatColumnSerializ
globalDictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
dictionaryWriter,
longDictionaryWriter,
doubleDictionaryWriter,
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializerV4.java
b/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializerV4.java
index ceab8dcf55b..efa31a13a3f 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializerV4.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/NestedDataColumnSerializerV4.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Maps;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.collections.bitmap.MutableBitmap;
import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.RE;
import org.apache.druid.java.util.common.StringUtils;
@@ -198,6 +199,7 @@ public class NestedDataColumnSerializerV4 implements
GenericColumnSerializer<Str
globalDictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
dictionaryWriter,
longDictionaryWriter,
doubleDictionaryWriter,
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarDoubleColumnSerializer.java
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarDoubleColumnSerializer.java
index c1139f58be7..ef99d5a7331 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarDoubleColumnSerializer.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarDoubleColumnSerializer.java
@@ -19,6 +19,7 @@
package org.apache.druid.segment.nested;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.io.Closer;
@@ -76,6 +77,7 @@ public class ScalarDoubleColumnSerializer extends
ScalarNestedCommonFormatColumn
dictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
null,
null,
dictionaryWriter,
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarLongColumnSerializer.java
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarLongColumnSerializer.java
index 268a9c90e26..0af923ced99 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarLongColumnSerializer.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarLongColumnSerializer.java
@@ -19,6 +19,7 @@
package org.apache.druid.segment.nested;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.io.Closer;
@@ -77,6 +78,7 @@ public class ScalarLongColumnSerializer extends
ScalarNestedCommonFormatColumnSe
dictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
null,
dictionaryWriter,
null,
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarStringColumnSerializer.java
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarStringColumnSerializer.java
index 9fa4ca61772..7ec884de087 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/ScalarStringColumnSerializer.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/ScalarStringColumnSerializer.java
@@ -20,6 +20,7 @@
package org.apache.druid.segment.nested;
import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.io.Closer;
import org.apache.druid.java.util.common.io.smoosh.FileSmoosher;
@@ -71,6 +72,7 @@ public class ScalarStringColumnSerializer extends
ScalarNestedCommonFormatColumn
dictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
dictionaryWriter,
null,
null,
diff --git
a/processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java
b/processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java
index 7de4be65112..f342effb768 100644
---
a/processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java
+++
b/processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java
@@ -26,6 +26,7 @@ import it.unimi.dsi.fastutil.ints.IntIterator;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.collections.bitmap.MutableBitmap;
import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.java.util.common.FileUtils;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.io.Closer;
@@ -154,6 +155,7 @@ public class VariantColumnSerializer extends
NestedCommonFormatColumnSerializer
dictionaryIdLookup = closer.register(
new DictionaryIdLookup(
name,
+ FileUtils.getTempDir(),
dictionaryWriter,
longDictionaryWriter,
doubleDictionaryWriter,
diff --git
a/processing/src/test/java/org/apache/druid/java/util/common/FileUtilsTest.java
b/processing/src/test/java/org/apache/druid/java/util/common/FileUtilsTest.java
index 86909a26210..d14e2a83b17 100644
---
a/processing/src/test/java/org/apache/druid/java/util/common/FileUtilsTest.java
+++
b/processing/src/test/java/org/apache/druid/java/util/common/FileUtilsTest.java
@@ -26,7 +26,6 @@ import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.internal.matchers.ThrowableMessageMatcher;
-import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import java.io.ByteArrayInputStream;
@@ -40,9 +39,6 @@ public class FileUtilsTest
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
@Test
public void testMap() throws IOException
{
@@ -137,18 +133,28 @@ public class FileUtilsTest
}
}
+ @Test
+ public void testCreateTempDirInLocation() throws IOException
+ {
+ final File baseDir = temporaryFolder.newFolder();
+ File tmp = FileUtils.createTempDirInLocation(baseDir.toPath(), null);
+ Assert.assertTrue(tmp.getName().startsWith("druid"));
+ Assert.assertEquals(
+ baseDir.toPath(),
+ tmp.getParentFile().toPath()
+ );
+ }
+
@Test
public void testCreateTempDirNonexistentBase()
{
final String oldJavaTmpDir = System.getProperty("java.io.tmpdir");
- final String nonExistentDir = oldJavaTmpDir + "/nonexistent";
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage(StringUtils.format("java.io.tmpdir (%s)
does not exist", nonExistentDir));
+ final String nonExistentDir = oldJavaTmpDir + "nonexistent";
try {
System.setProperty("java.io.tmpdir", nonExistentDir);
- FileUtils.createTempDir();
+ Throwable e = Assert.assertThrows(IllegalStateException.class, () ->
FileUtils.createTempDir());
+ Assert.assertEquals("Path [" + nonExistentDir + "] does not exist",
e.getMessage());
}
finally {
System.setProperty("java.io.tmpdir", oldJavaTmpDir);
@@ -159,23 +165,19 @@ public class FileUtilsTest
public void testCreateTempDirUnwritableBase() throws IOException
{
final File baseDir = FileUtils.createTempDir();
+ final String oldJavaTmpDir = System.getProperty("java.io.tmpdir");
try {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("java.io.tmpdir (" + baseDir + ") is not
writable");
-
- final String oldJavaTmpDir = System.getProperty("java.io.tmpdir");
- try {
- System.setProperty("java.io.tmpdir", baseDir.getPath());
- baseDir.setWritable(false);
- FileUtils.createTempDir();
- }
- finally {
- System.setProperty("java.io.tmpdir", oldJavaTmpDir);
- }
+
+ System.setProperty("java.io.tmpdir", baseDir.getPath());
+ baseDir.setWritable(false);
+ Throwable e = Assert.assertThrows(IllegalStateException.class, () ->
FileUtils.createTempDir());
+
+ Assert.assertEquals("Path [" + baseDir + "] is not writable, check
permissions", e.getMessage());
}
finally {
baseDir.setWritable(true);
Files.delete(baseDir.toPath());
+ System.setProperty("java.io.tmpdir", oldJavaTmpDir);
}
}
@@ -197,9 +199,11 @@ public class FileUtilsTest
{
final File tmpFile = temporaryFolder.newFile();
- expectedException.expect(IOException.class);
- expectedException.expectMessage("Cannot create directory");
- FileUtils.mkdirp(tmpFile);
+ Throwable t = Assert.assertThrows(IOException.class, () ->
FileUtils.mkdirp(tmpFile));
+ MatcherAssert.assertThat(
+ t,
+ ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("Cannot
create directory"))
+ );
}
@Test
@@ -208,17 +212,13 @@ public class FileUtilsTest
final File tmpDir = temporaryFolder.newFolder();
final File testDirectory = new File(tmpDir, "test");
tmpDir.setWritable(false);
- try {
- final IOException e = Assert.assertThrows(IOException.class, () ->
FileUtils.mkdirp(testDirectory));
+ final IOException e = Assert.assertThrows(IOException.class, () ->
FileUtils.mkdirp(testDirectory));
- MatcherAssert.assertThat(
- e,
-
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("Cannot create
directory"))
- );
- }
- finally {
- tmpDir.setWritable(true);
- }
+ MatcherAssert.assertThat(
+ e,
+ ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("Cannot
create directory"))
+ );
+ tmpDir.setWritable(true);
// Now it should work.
FileUtils.mkdirp(testDirectory);
diff --git
a/processing/src/test/java/org/apache/druid/segment/nested/DictionaryIdLookupTest.java
b/processing/src/test/java/org/apache/druid/segment/nested/DictionaryIdLookupTest.java
new file mode 100644
index 00000000000..bba9a639803
--- /dev/null
+++
b/processing/src/test/java/org/apache/druid/segment/nested/DictionaryIdLookupTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.druid.segment.nested;
+
+import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.segment.AutoTypeColumnMerger;
+import org.apache.druid.segment.column.StringEncodingStrategies;
+import org.apache.druid.segment.column.StringEncodingStrategy;
+import org.apache.druid.segment.column.TypeStrategies;
+import org.apache.druid.segment.data.DictionaryWriter;
+import org.apache.druid.segment.data.FixedIndexedWriter;
+import org.apache.druid.segment.data.FrontCodedIntArrayIndexedWriter;
+import org.apache.druid.segment.writeout.SegmentWriteOutMedium;
+import org.apache.druid.segment.writeout.TmpFileSegmentWriteOutMediumFactory;
+import org.apache.druid.testing.InitializedNullHandlingTest;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.nio.file.Path;
+
+public class DictionaryIdLookupTest extends InitializedNullHandlingTest
+{
+ @Rule
+ public final TemporaryFolder temp = new TemporaryFolder();
+
+ @Test
+ public void testIdLookup() throws IOException
+ {
+ // add some values
+ ValueDictionary dictionary = new ValueDictionary();
+ dictionary.addStringValue("hello");
+ dictionary.addStringValue("world");
+ dictionary.addStringValue(null);
+ dictionary.addLongValue(123L);
+ dictionary.addLongValue(-123L);
+ dictionary.addDoubleValue(1.234);
+ dictionary.addDoubleValue(0.001);
+ dictionary.addStringArray(new Object[]{"hello", "world"});
+ dictionary.addLongArray(new Object[]{1L, 2L, 3L});
+ dictionary.addDoubleArray(new Object[]{0.01, -1.234, 0.001, 1.234});
+
+ // sort them
+ SortedValueDictionary sortedValueDictionary =
dictionary.getSortedCollector();
+
+ // setup dictionary writers
+ SegmentWriteOutMedium medium =
TmpFileSegmentWriteOutMediumFactory.instance()
+
.makeSegmentWriteOutMedium(temp.newFolder());
+ DictionaryWriter<String> stringWriter =
StringEncodingStrategies.getStringDictionaryWriter(
+ new StringEncodingStrategy.FrontCoded(4, (byte) 1),
+ medium,
+ "test"
+ );
+ FixedIndexedWriter<Long> longWriter = new FixedIndexedWriter<>(
+ medium,
+ TypeStrategies.LONG,
+ ByteOrder.nativeOrder(),
+ Long.BYTES,
+ true
+ );
+ FixedIndexedWriter<Double> doubleWriter = new FixedIndexedWriter<>(
+ medium,
+ TypeStrategies.DOUBLE,
+ ByteOrder.nativeOrder(),
+ Double.BYTES,
+ true
+ );
+ FrontCodedIntArrayIndexedWriter arrayWriter = new
FrontCodedIntArrayIndexedWriter(
+ medium,
+ ByteOrder.nativeOrder(),
+ 4
+ );
+
+ Path dictTempPath = temp.newFolder().toPath();
+
+ // make lookup with references to writers
+ DictionaryIdLookup idLookup = new DictionaryIdLookup(
+ "test",
+ dictTempPath,
+ stringWriter,
+ longWriter,
+ doubleWriter,
+ arrayWriter
+ );
+
+ // write the stuff
+ stringWriter.open();
+ longWriter.open();
+ doubleWriter.open();
+ arrayWriter.open();
+
+ File tempDir = dictTempPath.toFile();
+ Assert.assertEquals(0, tempDir.listFiles().length);
+
+ for (String s : sortedValueDictionary.getSortedStrings()) {
+ stringWriter.write(s);
+ }
+ for (Long l : sortedValueDictionary.getSortedLongs()) {
+ longWriter.write(l);
+ }
+ for (Double d : sortedValueDictionary.getSortedDoubles()) {
+ doubleWriter.write(d);
+ }
+
+ Iterable<int[]> sortedArrays = () -> new
AutoTypeColumnMerger.ArrayDictionaryMergingIterator(
+ new Iterable[]{sortedValueDictionary.getSortedArrays()},
+ idLookup
+ );
+
+ Assert.assertEquals(0, tempDir.listFiles().length);
+
+ // looking up some values pulls in string dictionary and long dictionary
+ Assert.assertEquals(0, idLookup.lookupString(null));
+ Assert.assertEquals(1, idLookup.lookupString("hello"));
+ Assert.assertEquals(2, idLookup.lookupString("world"));
+ Assert.assertEquals(3, idLookup.lookupLong(-123L));
+
+ Assert.assertEquals(2, tempDir.listFiles().length);
+
+ // writing arrays needs to use the lookups for lower value dictionaries,
so will create string, long, and double
+ // temp dictionary files
+ for (int[] arr : sortedArrays) {
+ arrayWriter.write(arr);
+ }
+ Assert.assertEquals(3, tempDir.listFiles().length);
+
+ if (NullHandling.sqlCompatible()) {
+ Assert.assertEquals(8, idLookup.lookupDouble(-1.234));
+ Assert.assertEquals(11, idLookup.lookupDouble(1.234));
+
+ Assert.assertEquals(3, tempDir.listFiles().length);
+
+ // looking up arrays pulls in array file
+ Assert.assertEquals(12, idLookup.lookupArray(new int[]{1, 2}));
+ Assert.assertEquals(13, idLookup.lookupArray(new int[]{4, 5, 6}));
+ Assert.assertEquals(14, idLookup.lookupArray(new int[]{10, 8, 9, 11}));
+ Assert.assertEquals(4, tempDir.listFiles().length);
+ } else {
+ // default value mode sticks zeros in dictionary even if not present in
column because of .. reasons
+ Assert.assertEquals(9, idLookup.lookupDouble(-1.234));
+ Assert.assertEquals(13, idLookup.lookupDouble(1.234));
+
+ Assert.assertEquals(3, tempDir.listFiles().length);
+
+ // looking up arrays pulls in array file
+ Assert.assertEquals(14, idLookup.lookupArray(new int[]{1, 2}));
+ Assert.assertEquals(15, idLookup.lookupArray(new int[]{5, 6, 7}));
+ Assert.assertEquals(16, idLookup.lookupArray(new int[]{12, 9, 11, 13}));
+ Assert.assertEquals(4, tempDir.listFiles().length);
+ }
+
+ // close it removes all the temp files
+ idLookup.close();
+ Assert.assertEquals(0, tempDir.listFiles().length);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]