Skip to content

Commit 8eeae53

Browse files
authored
feat!: write ordered maps by default (#35)
* feat!: write ordered maps by default * build!: java client 6.1.6 only supports server 4.9+ * feat: add -um to force unordered maps
1 parent d944221 commit 8eeae53

File tree

10 files changed

+110
-31
lines changed

10 files changed

+110
-31
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ __Options__:
7272
-tr,--tls-revoke Revoke certificates identified by their serial number. Values: serial numbers separated by comma (default: null (Do not revoke certificates))
7373
-te,--tls-encrypt-only Enable TLS encryption and disable TLS certificate validation
7474
-uk,--send-user-key Send user defined key in addition to hash digest to store on the server. (default: userKey is not sent to reduce meta-data overhead)
75+
-um,--unorderedMaps If this flag is present write all maps as unordered maps.
7576
-u,--usage Print usage.
7677
-v,--verbose Verbose mode for debug logging (default: INFO)
7778
-V,--version Print version

doc/releasenotes.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,11 @@
5959

6060
## Aerospike Loader [2.4.3] Release Date [4 Jan 2022]
6161
### Fix/Changes:
62-
- Update log4j to version 2.17.1.
62+
- Update log4j to version 2.17.1.
63+
64+
## Aerospike Loader [3.0.0] Release Date [27 Jan 2023]
65+
### Breaking Changes:
66+
- Upgrade Aerospike Java client to 6.1.6 which is only compatible with Aerospike server 4.9 or newer.
67+
- Write key ordered maps by default.
68+
### New features:
69+
- Add -um/--unorderedMaps flags to force writing unordered maps.

example/alldatatype.dsv

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
set##key##intData##floatData##stringData##listData##mapData##dateData##blobData##geoData
2-
set1##key1##11##1.9##string1##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##01/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.4, -456.7]}
3-
set2##key2##12##4.5##string2##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##02/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.5, -456.7]}
4-
set3##key3##13##3.6##string3##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##03/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.6, -456.7]}
5-
set4##key4##14##5.6##string4##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##04/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.7, -436.7]}
6-
set5##key5##15##8.3##string5##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##05/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.8, -556.7]}
7-
set6##key6##16##3.0##string6##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##06/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.4, -476.7]}
8-
set7##key7##17##6.9##string7##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##07/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [133.4, -256.7]}
9-
set8##key8##18##0.2##string8##["d","b", ["c", "d"]]##{"c": {"b": "c"}}##08/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [143.4, -756.7]}
2+
set1##key1##11##1.9##string1##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##01/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.4, -45.7]}
3+
set2##key2##12##4.5##string2##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##02/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.5, -45.7]}
4+
set3##key3##13##3.6##string3##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##03/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.6, -45.7]}
5+
set4##key4##14##5.6##string4##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##04/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.7, -43.7]}
6+
set5##key5##15##8.3##string5##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##05/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.8, -55.7]}
7+
set6##key6##16##3.0##string6##["d","e", ["c", "d"]]##{"c": {"b": "c"}}##06/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [123.4, -47.7]}
8+
set7##key7##17##6.9##string7##["a","b", ["c", "d"]]##{"a": {"b": "c"}}##07/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [133.4, -25.7]}
9+
set8##key8##18##0.2##string8##["d","b", ["c", "d"]]##{"c": {"b": "c"}}##08/16/2011##6c6f63626c6f623830##{"type": "Point", "coordinates": [143.4, -75.7]}

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.aerospike</groupId>
55
<artifactId>aerospike-load</artifactId>
6-
<version>2.4.3</version>
6+
<version>3.0.0</version>
77
<name>Aerospike DSV Loader</name>
88
<packaging>jar</packaging>
99

@@ -32,7 +32,7 @@
3232
<dependency>
3333
<groupId>com.aerospike</groupId>
3434
<artifactId>aerospike-client</artifactId>
35-
<version>4.4.11</version>
35+
<version>6.1.6</version>
3636
</dependency>
3737
<!-- Apache command line parser. -->
3838
<dependency>

src/main/java/com/aerospike/load/AerospikeLoad.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
* -uk,--send-user-key Send user defined key in addition to hash digest to store on the server. (default: userKey is not sent to reduce meta-data overhead)
8282
* -u,--usage Print usage.
8383
* -v,--verbose Verbose mode for debug logging (default: INFO)
84+
* -um,--unordered-map Write maps as unorderd (default: false)
8485
* The file names can be a series of file names or directories.
8586
*
8687
* @author Aerospike
@@ -187,6 +188,7 @@ public static void main(String[] args) throws IOException {
187188
"Send user defined key in addition to hash digest to store on the server. (default: userKey is not sent to reduce meta-data overhead)"
188189
);
189190
options.addOption("v", "verbose", false, "Logging all");
191+
options.addOption("um", "unorderdMaps", false, "Write all maps as unorderd maps");
190192
options.addOption("u", "usage", false, "Print usage.");
191193

192194
CommandLineParser parser = new PosixParser();

src/main/java/com/aerospike/load/AsWriterTask.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Date;
2929
import java.util.HashMap;
3030
import java.util.List;
31+
import java.util.TreeMap;
3132
import java.util.concurrent.Callable;
3233

3334
import org.apache.logging.log4j.LogManager;
@@ -461,7 +462,14 @@ private Bin createBinForJson(String binName, String binRawValue) {
461462
return new Bin(binName, jsonArray);
462463
} else {
463464
JSONObject jsonObj = (JSONObject) obj;
464-
return new Bin(binName, jsonObj);
465+
466+
if (this.params.unorderdMaps) {
467+
return new Bin(binName, jsonObj);
468+
}
469+
470+
TreeMap<?,?> sortedMap = new TreeMap<>();
471+
sortedMap.putAll(jsonObj);
472+
return new Bin(binName, sortedMap);
465473
}
466474

467475
} catch (ParseException e) {

src/main/java/com/aerospike/load/Parameters.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class Parameters {
3535
long timeZoneOffset;
3636
int abortErrorCount;
3737
boolean verbose;
38+
boolean unorderdMaps;
3839

3940
/**
4041
* Set parameters from commandline argument.
@@ -45,6 +46,7 @@ public class Parameters {
4546
* @param timeZoneOffset
4647
* @param abortAtError
4748
* @param verbose
49+
* @param unorderdMaps
4850
*/
4951
protected Parameters(
5052
Host[] hosts,
@@ -53,7 +55,8 @@ protected Parameters(
5355
long maxThroughput,
5456
long timeZoneOffset,
5557
int abortErrorCount,
56-
boolean verbose
58+
boolean verbose,
59+
boolean unorderdMaps
5760
) {
5861
this.hosts = hosts;
5962
this.namespace = namespace;
@@ -62,6 +65,7 @@ protected Parameters(
6265
this.timeZoneOffset = timeZoneOffset;
6366
this.abortErrorCount = abortErrorCount;
6467
this.verbose = verbose;
68+
this.unorderdMaps = unorderdMaps;
6569
}
6670

6771
@Override
@@ -71,6 +75,8 @@ public String toString() {
7175
", maxThroughput=" + this.maxThroughput +
7276
", write-action=" + this.writePolicy.recordExistsAction.toString() +
7377
", timeZoneOffset=" + this.timeZoneOffset +
74-
", abortErrorCount=" + this.abortErrorCount + "]";
78+
", abortErrorCount=" + this.abortErrorCount +
79+
", verbose=" + this.verbose +
80+
", unorderdMaps=" + this.unorderdMaps + "]";
7581
}
7682
}

src/main/java/com/aerospike/load/Utils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,12 @@ protected static Parameters parseParameters(CommandLine cl) throws Exception {
138138
verbose = true;
139139
}
140140

141-
return new Parameters(hosts, namespace, writePolicy, maxThroughput, timeZoneOffset, abortErrorCount, verbose);
141+
boolean unorderdMaps = false;
142+
if (cl.hasOption("um")) {
143+
unorderdMaps = true;
144+
}
145+
146+
return new Parameters(hosts, namespace, writePolicy, maxThroughput, timeZoneOffset, abortErrorCount, verbose, unorderdMaps);
142147
}
143148

144149
/**

src/test/java/com/aerospike/load/DataTypeTest.java

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.ArrayList;
1717
import java.util.Date;
1818
import java.util.HashMap;
19+
import java.util.SortedMap;
1920
import java.util.Iterator;
2021
import java.util.List;
2122
import java.util.Map;
@@ -35,8 +36,7 @@
3536
import com.aerospike.client.Key;
3637
import com.aerospike.client.Record;
3738
import com.aerospike.client.policy.Policy;
38-
39-
import com.aerospike.load.Parser;
39+
import com.aerospike.client.cdt.MapOrder;
4040

4141
enum BinType {
4242
INTEGER, STRING, BLOB, LIST, MAP, JSON, TIMESTAMP;
@@ -53,6 +53,7 @@ public class DataTypeTest {
5353
String port = "3000";
5454
String ns = "test";
5555
String set = null;
56+
MapOrder expectedMapOrder = MapOrder.KEY_ORDERED;
5657
//String config = "src/test/resources/allDatatypeCsv.json";
5758
String error_count = "0";
5859
String write_action = "update";
@@ -434,6 +435,40 @@ public void testStaticBinName() throws Exception {
434435
System.out.println("Test static BinName: Complete");
435436
}
436437

438+
//Validate map sort order
439+
@Test
440+
public void testValidateMapOrder() throws Exception {
441+
System.out.println("TestValidateMapOrder: start");
442+
if(!client.isConnected()) {
443+
System.out.println("Client is not able to connect:" + host + ":" + port);
444+
return;
445+
}
446+
447+
// Create datafile
448+
449+
HashMap<String, String> binMap = (HashMap<String, String>) testSchema.get("test_map");
450+
451+
452+
int setMod = 5, range = 100, seed = 10, nrecords = 10;
453+
dataFile = rootDir + "dataMap.dsv";
454+
writeDataMap(dataFile, nrecords, setMod, range, seed, binMap);
455+
456+
// Run Aerospike loader
457+
this.expectedMapOrder = MapOrder.UNORDERED;
458+
AerospikeLoad.main(new String[]{"-h", host,"-p", port,"-n", ns, "-ec", error_count,"-wa", write_action, "-um", "-c", "src/test/resources/configMap.json", dataFile});
459+
460+
// Validate loaded data
461+
String dstType = "map";
462+
boolean dataValid = validateMap(client, dataFile, nrecords, setMod, range, seed, binMap, dstType);
463+
boolean error = getError(log);
464+
465+
assertTrue(dataValid);
466+
assertTrue(!error);
467+
this.expectedMapOrder = MapOrder.KEY_ORDERED;
468+
469+
System.out.println("TestValidateMap: Complete");
470+
}
471+
437472
// Helper functions
438473
public void writeDataMap(String fileName, int nrecords, int setMod, int range, int seed,
439474
HashMap<String, String> binMap) {
@@ -595,14 +630,28 @@ private boolean validateBin(Key key, Bin bin, String binType, String dstType, Re
595630
expected = bin.value.toString().replace("'", "");
596631
expected = expected.replace("\"", "");
597632

598-
} else if (dstType != null && (dstType.equalsIgnoreCase("map")
599-
|| dstType.equalsIgnoreCase("json"))) {
600-
System.out.println(String.format("Currently json and map can not be matched."));
633+
} else if (dstType != null && (dstType.equalsIgnoreCase("json"))) {
634+
System.out.println(String.format("Currently json can not be matched."));
601635

602636
//received = received.toString().replace("=", ":");
603637
//expected = bin.value.toString().replace("'", "");
604638
//expected = expected.replace("\"", "");
639+
605640
return true;
641+
} else if (dstType != null && (dstType.equalsIgnoreCase("map"))) {
642+
System.out.println(String.format("Currently only map order is checked."));
643+
644+
//received = received.toString().replace("=", ":");
645+
//expected = bin.value.toString().replace("'", "");
646+
//expected = expected.replace("\"", "");
647+
648+
MapOrder mapOrder = (received instanceof SortedMap<?,?>)? MapOrder.KEY_ORDERED : MapOrder.UNORDERED;
649+
650+
if (mapOrder == this.expectedMapOrder) {
651+
return true;
652+
}
653+
654+
return false;
606655
} else {
607656
expected = bin.value.toString();
608657
}
@@ -678,7 +727,8 @@ public String getValue(String binName, String binType, int i) {
678727
value = "[\"a\", \"b\", \"c\", [\"d\", \"e\"]]";
679728
break;
680729
case MAP:
681-
value = "{\"a\":\"b\", \"b\":\"c\", \"c\":{\"d\":\"e\"}}";
730+
value = "{\"a\":\"b\", \"c\":{\"e\":\"d\"}, \"b\":\"c\"}";
731+
// sorted value should be "{\"a\":\"b\", \"b\":\"c\", \"c\":{\"d\":\"e\"}}";
682732
break;
683733
case STRING:
684734
if (binName.equalsIgnoreCase("utf8")) {

src/test/resources/dataMap.dsv

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
mapData##set##key
2-
{"a":"b", "b":"c", "c":{"d":"e"}}##set1##key1
3-
{"a":"b", "b":"c", "c":{"d":"e"}}##set2##key2
4-
{"a":"b", "b":"c", "c":{"d":"e"}}##set3##key3
5-
{"a":"b", "b":"c", "c":{"d":"e"}}##set4##key4
6-
{"a":"b", "b":"c", "c":{"d":"e"}}##set0##key5
7-
{"a":"b", "b":"c", "c":{"d":"e"}}##set1##key6
8-
{"a":"b", "b":"c", "c":{"d":"e"}}##set2##key7
9-
{"a":"b", "b":"c", "c":{"d":"e"}}##set3##key8
10-
{"a":"b", "b":"c", "c":{"d":"e"}}##set4##key9
11-
{"a":"b", "b":"c", "c":{"d":"e"}}##set0##key10
2+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set1##key1
3+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set2##key2
4+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set3##key3
5+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set4##key4
6+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set0##key5
7+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set1##key6
8+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set2##key7
9+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set3##key8
10+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set4##key9
11+
{"a":"b", "c":{"e":"d"}, "b":"c"}##set0##key10

0 commit comments

Comments
 (0)