Skip to content

Commit ac121cd

Browse files
committed
BulkWriter support binary/float16/int8 vectors in Struct field
Signed-off-by: yhmo <yihua.mo@zilliz.com>
1 parent 46b3538 commit ac121cd

8 files changed

Lines changed: 700 additions & 40 deletions

File tree

examples/src/main/java/io/milvus/v2/bulkwriter/BulkWriterStructExample.java

Lines changed: 460 additions & 0 deletions
Large diffs are not rendered by default.

sdk-bulkwriter/src/main/java/io/milvus/bulkwriter/RemoteBulkWriter.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,13 @@ protected void callBack(List<String> fileList) {
190190
@Override
191191
public void close() throws Exception {
192192
logger.info("execute remaining actions to prevent loss of memory data or residual empty directories.");
193-
exit();
193+
try {
194+
exit();
195+
} finally {
196+
if (storageClient != null) {
197+
storageClient.close();
198+
}
199+
}
194200
logger.info(String.format("RemoteBulkWriter done! output remote files: %s", getBatchFiles()));
195201
}
196202

sdk-bulkwriter/src/main/java/io/milvus/bulkwriter/common/utils/ParquetUtils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ private static void fillStructType(Types.MessageTypeBuilder messageTypeBuilder,
201201
case FloatVector:
202202
setMessageType(groupBuilder, PrimitiveType.PrimitiveTypeName.FLOAT, null, subField, true);
203203
break;
204+
case BinaryVector:
205+
case Float16Vector:
206+
case BFloat16Vector:
207+
case Int8Vector:
208+
boolean isSigned = (subField.getDataType() == io.milvus.v2.common.DataType.Int8Vector);
209+
setMessageType(groupBuilder, PrimitiveType.PrimitiveTypeName.INT32,
210+
LogicalTypeAnnotation.IntLogicalTypeAnnotation.intType(8, isSigned), subField, true);
211+
break;
204212
default:
205213
break;
206214
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package io.milvus.bulkwriter.common.utils;
21+
22+
import java.nio.ByteBuffer;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.Map;
26+
27+
public class WriterUtils {
28+
private WriterUtils() {
29+
}
30+
31+
public static Object normalizeValue(Object value) {
32+
if (value instanceof ByteBuffer) {
33+
ByteBuffer byteBuffer = (ByteBuffer) value;
34+
byte[] bytes = byteBuffer.array();
35+
List<Integer> result = new ArrayList<>(bytes.length);
36+
for (byte b : bytes) {
37+
result.add((int) b);
38+
}
39+
return result;
40+
}
41+
if (value instanceof List) {
42+
List<?> values = (List<?>) value;
43+
List<Object> normalized = null;
44+
for (int i = 0; i < values.size(); i++) {
45+
Object item = values.get(i);
46+
Object normalizedItem = normalizeValue(item);
47+
if (normalized != null) {
48+
normalized.add(normalizedItem);
49+
continue;
50+
}
51+
if (normalizedItem != item) {
52+
normalized = new ArrayList<>(values.size());
53+
for (int j = 0; j < i; j++) {
54+
normalized.add(values.get(j));
55+
}
56+
normalized.add(normalizedItem);
57+
}
58+
}
59+
return normalized != null ? normalized : value;
60+
}
61+
if (value instanceof Map) {
62+
Map<Object, Object> values = (Map<Object, Object>) value;
63+
values.replaceAll((k, v) -> normalizeValue(v));
64+
return values;
65+
}
66+
return value;
67+
}
68+
}

sdk-bulkwriter/src/main/java/io/milvus/bulkwriter/storage/client/MinioStorageClient.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
import java.security.NoSuchAlgorithmException;
5959
import java.util.concurrent.CompletableFuture;
6060
import java.util.concurrent.CompletionException;
61+
import java.util.concurrent.ExecutorService;
62+
import java.util.concurrent.TimeUnit;
6163

6264
import static com.amazonaws.services.s3.internal.Constants.MB;
6365

@@ -167,8 +169,18 @@ public void close() {
167169
if (!closeHttpClient || httpClient == null) {
168170
return;
169171
}
170-
httpClient.dispatcher().executorService().shutdown();
172+
ExecutorService executorService = httpClient.dispatcher().executorService();
173+
executorService.shutdown();
171174
httpClient.connectionPool().evictAll();
175+
try {
176+
if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
177+
executorService.shutdownNow();
178+
}
179+
} catch (InterruptedException e) {
180+
executorService.shutdownNow();
181+
Thread.currentThread().interrupt();
182+
logger.warn("Interrupted while shutting down MinIO HTTP client executor", e);
183+
}
172184
if (httpClient.cache() != null) {
173185
try {
174186
httpClient.cache().close();

sdk-bulkwriter/src/main/java/io/milvus/bulkwriter/writer/CSVFileWriter.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
import com.google.common.collect.Lists;
44
import com.google.gson.Gson;
55
import com.google.gson.GsonBuilder;
6+
import io.milvus.bulkwriter.common.utils.WriterUtils;
67
import io.milvus.v2.service.collection.request.CreateCollectionReq;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
910

1011
import java.io.BufferedWriter;
1112
import java.io.IOException;
12-
import java.nio.ByteBuffer;
1313
import java.util.ArrayList;
14-
import java.util.Arrays;
1514
import java.util.List;
1615
import java.util.Map;
1716

@@ -43,6 +42,7 @@ private void initWriter() throws IOException {
4342
@Override
4443
public void appendRow(Map<String, Object> rowValues, boolean firstWrite) throws IOException {
4544
rowValues.keySet().removeIf(key -> key.equals(DYNAMIC_FIELD_NAME) && !this.collectionSchema.isEnableDynamicField());
45+
rowValues.replaceAll((key, value) -> WriterUtils.normalizeValue(value));
4646

4747
Gson gson = new GsonBuilder().serializeNulls().create();
4848
List<String> fieldNameList = Lists.newArrayList(rowValues.keySet());
@@ -62,8 +62,6 @@ public void appendRow(Map<String, Object> rowValues, boolean firstWrite) throws
6262
String strVal = "";
6363
if (val == null) {
6464
strVal = nullKey;
65-
} else if (val instanceof ByteBuffer) {
66-
strVal = Arrays.toString(((ByteBuffer) val).array());
6765
} else if (val instanceof List || val instanceof Map) {
6866
strVal = gson.toJson(val); // server-side is using json to parse array field and vector field
6967
} else {

sdk-bulkwriter/src/main/java/io/milvus/bulkwriter/writer/JSONFileWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
5+
import io.milvus.bulkwriter.common.utils.WriterUtils;
56
import io.milvus.v2.service.collection.request.CreateCollectionReq;
67
import org.slf4j.Logger;
78
import org.slf4j.LoggerFactory;
89

910
import java.io.BufferedWriter;
1011
import java.io.IOException;
11-
import java.nio.ByteBuffer;
1212
import java.util.Map;
1313

1414
import static io.milvus.param.Constant.DYNAMIC_FIELD_NAME;
@@ -38,7 +38,7 @@ private void initWriter() throws IOException {
3838
public void appendRow(Map<String, Object> rowValues, boolean firstWrite) throws IOException {
3939
Gson gson = new GsonBuilder().serializeNulls().create();
4040
rowValues.keySet().removeIf(key -> key.equals(DYNAMIC_FIELD_NAME) && !this.collectionSchema.isEnableDynamicField());
41-
rowValues.replaceAll((key, value) -> value instanceof ByteBuffer ? ((ByteBuffer) value).array() : value);
41+
rowValues.replaceAll((key, value) -> WriterUtils.normalizeValue(value));
4242

4343
try {
4444
if (firstWrite) {

0 commit comments

Comments
 (0)