Skip to content

Commit d86ca27

Browse files
committed
Merge branch 'mongodb-support' of github.com:picoded/JavaCommons-dstack into mongodb-support
2 parents c8019a6 + cc917bd commit d86ca27

30 files changed

Lines changed: 1822 additions & 83 deletions

.github/.codecov.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
coverage:
2+
status:
3+
project:
4+
# Full configuration format is found here :
5+
# https://docs.codecov.com/docs/commit-status#section-project-status
6+
default:
7+
# basic
8+
#target: 10%
9+
#threshold: 10%
10+
paths:
11+
- "src"
12+
# advanced settings
13+
if_ci_failed: error #success, failure, error, ignore
14+
informational: true
15+
only_pulls: false

.github/workflows/gradle-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
branches: [ master ]
77
jobs:
88
build:
9-
runs-on: ubuntu-18.04
9+
runs-on: ubuntu-latest
1010
steps:
1111
- uses: actions/checkout@v1
1212
- name: Init submodules

.github/workflows/redis.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Redis support test
2+
on:
3+
push:
4+
branches: [ master, "redis*", "*redis*" ]
5+
pull_request:
6+
branches: [ master ]
7+
jobs:
8+
unit_test:
9+
runs-on: ubuntu-latest
10+
11+
# Configuration, for us to perform test against multiple version in the future
12+
strategy:
13+
matrix:
14+
redis-version: [7]
15+
16+
# The test step
17+
steps:
18+
# Start Redis
19+
- name: Start Redis
20+
uses: supercharge/redis-github-action@1.4.0
21+
with:
22+
redis-version: ${{ matrix.redis-version }}
23+
24+
# The usual checkout, and test
25+
- uses: actions/checkout@v1
26+
- name: Init submodules
27+
run: ./git-init-submodules.sh
28+
- name: Set up JDK 1.8
29+
uses: actions/setup-java@v1
30+
with:
31+
java-version: 1.8
32+
- name: Cache Gradle packages
33+
uses: actions/cache@v2
34+
with:
35+
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/build.gradle') }}
36+
path: |
37+
~/.gradle/caches
38+
~/.gradle/wrapper
39+
- name: Setup gradle binaries
40+
run: ./gradlew
41+
- name: Pull dependencies libs, and perform initial compile
42+
run: ./gradlew src
43+
- name: Run unit tests
44+
run: ./gradlew test -Ptest_redis
45+
- name: Run jacocoTestReport
46+
run: ./gradlew jacocoTestReport
47+
- name: Archive code coverage results
48+
uses: actions/upload-artifact@v2
49+
if: always()
50+
with:
51+
name: test-result-report
52+
path: |
53+
build/reports/**/*
54+
build/test-results/**/*
55+
build/jacoco/**/*
56+
- name: Upload code coverage to codecov
57+
uses: codecov/codecov-action@v2
58+
if: always()
59+
with:
60+
# flags: gradle-build # optional
61+
# directory: build/jacoco/
62+
verbose: true # optional (default = false)
63+
fail_ci_if_error: false

README.md

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,37 @@ All while maintaining the same interface for the application. Leaving the decisi
1313
Its most notable claass is `DataObjectMap` which functions as a `SQL` queryable `NoSQL` interface. That functions even against an SQL backend.
1414
Followed by `DStack` which faciltates the stacking of data backend provider for devops. Such as a distributed cache with an SQL backend.
1515

16-
# Support Matrix
17-
18-
| backend | status | notes | DataObjectMap | KeyValueMap | KeyLongMap | FileWorkspaceMap |
19-
|---------------|---------------|------------------------------------------------------|---------------|-------------|------------|------------------|
20-
| struct.simple | development | reference implementation, not for used in production | storage | storage | storage | storage |
21-
| struct.cache | development | | storage | | | |
22-
| jsql | in-production | see SQL support table below for details | full | full | full | full |
23-
| hazelcast | development | | storage | storage | | |
24-
| file.simple | development | | | | | development |
25-
| ignite | development | roadmap | | | | |
26-
| cockroachdb | development | roadmap | | | | |
16+
# Provider Support Matrix
17+
18+
| backend | status | notes | DataObjectMap | KeyValueMap | KeyLongMap | FileWorkspaceMap |
19+
|------------------|---------------|------------------------------------------------------|---------------|-------------|------------|------------------|
20+
| struct.simple | in-production | reference implementation, not recommended for use | storage | storage | storage | storage |
21+
| struct.cache | in-production | local instance caching, useful for WORM data | storage | storage | | |
22+
| jsql | in-production | *with limits: see SQL support notes below | full | full | full | full |
23+
| mongodb | in-production | *with limits: see MongoDB support notes below | full | full | full | full |
24+
| hazelcast.cache | in-production | | full | full | full | |
25+
| hazelcast.store | in-production | | full | full | full | |
26+
| file.simple | in-production | | | | | storage |
27+
| file.layered | in-production | | | | | storage |
28+
| resdisson | experimental | | storage | storage | | |
29+
| ignite | roadmap | roadmap | | | | |
30+
| cockroachdb | roadmap | roadmap | | | | |
31+
32+
**Important notes**
33+
34+
- "full", means it has been optimized for both storage, and query operations.
35+
- "storage" means does not support optimization for queries, for large queries, this can have detrimental performance implication, as the apistack will need to iterate a large number of data.
36+
- Hazelcast require a custom build / deployment with the JavaCommons JAR file to support the required functionality
37+
- MySQL connection / db seems to support only up to 16 digits of accuracy
38+
- Requires read-after-write consistency, for expected behaviour, use w=majority&readConcernLevel=linearizable
2739

2840
# Data Structures
2941

3042
| DataStructure | Status | Description |
3143
|------------------|---------------|----------------------------------------------------------------------------|
3244
| DataObjectMap | in-production | Map document storage, with SQL query support |
3345
| KeyValueMap | in-production | High performance key to string value storage |
34-
| KeyLongMap | experimental | Varient of KeyValue with atomic long support (if used in single tier mode) |
35-
| FileWorkspaceMap | development | File workspace storage support |
46+
| KeyLongMap | in-production | Varient of KeyValue with atomic long support (if used in single tier mode) |
47+
| FileWorkspaceMap | in-production | File workspace storage support |
3648
| MessageQueue | road-map | Message queue |
3749
| JobQueue | road-map | Job request, response queue |
38-
39-
# Important known issues
40-
41-
- MySQL connection / db seems to support only up to 16 digits of accuracy

build.gradle

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ dependencies {
9191
api "com.oracle.ojdbc:ojdbc8:19.3.0.0" // for oracle
9292

9393
// api files("./lib/jsql/ojdbc6.jar") // for oracle
94-
api "org.xerial:sqlite-jdbc:3.25.2" // for sqlite
94+
api "org.xerial:sqlite-jdbc:3.34.0" // for sqlite
9595
api "mysql:mysql-connector-java:8.0.26" // for mysql
9696

9797
// Newer MSSQL connection (THIS DOES NOT WORK)
@@ -113,6 +113,9 @@ dependencies {
113113
api 'org.mongodb:mongodb-driver-sync:4.5.1'
114114
api 'com.github.luben:zstd-jni:1.5.2-3'
115115

116+
// Redis
117+
api 'org.redisson:redisson:3.17.1'
118+
116119
// PostgresSQL library
117120
api "org.postgresql:postgresql:42.2.5"
118121

@@ -279,6 +282,9 @@ test {
279282
if(!project.hasProperty("test_mongodb")) {
280283
exclude "**/*MongoDB*"
281284
}
285+
if(!project.hasProperty("test_redis")) {
286+
exclude "**/*Redis*"
287+
}
282288
}
283289

284290
// Setup test to run on parllel threads = to number of processors by default
@@ -382,6 +388,9 @@ task incrementalTest(type: TestWatcher) {
382388
if(!project.hasProperty("test_mongodb")) {
383389
exclude "**/*MongoDB*"
384390
}
391+
if(!project.hasProperty("test_redis")) {
392+
exclude "**/*Redis*"
393+
}
385394
}
386395

387396
// Setup test to run on parllel threads = to number of processors by default

src/main/java/picoded/dstack/DataObjectMap.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,33 @@ default String[] getFromKeyName_id(String keyName, String orderByStr, int offset
312312
return retList.toArray(new String[retList.size()]);
313313
}
314314

315+
//
316+
// Query count optimization handling
317+
//--------------------------------------------------------------------------
318+
319+
/**
320+
* Get the size of the current DataObjectMap
321+
*
322+
* Note that if the dataset size is larger then Integer.MAX_VALUE
323+
* it is clamped accordingly to the MAX_VALUE
324+
**/
325+
@Override
326+
default int size() {
327+
long s = queryCount(null, null);
328+
if (s > Integer.MAX_VALUE) {
329+
return Integer.MAX_VALUE;
330+
}
331+
return (int) s;
332+
}
333+
334+
/**
335+
* Get the size as a long for the DataObjectMap
336+
* This should be used instead of size (to work around int limits)
337+
*/
338+
default long longSize() {
339+
return queryCount(null, null);
340+
}
341+
315342
//
316343
// Get key names handling
317344
//--------------------------------------------------------------------------

src/main/java/picoded/dstack/FileWorkspaceMap.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,15 @@ default FileWorkspace[] getArrayFromID(String[] idArray, boolean isUnchecked) {
123123
*
124124
* This is equivalent of "TRUNCATE TABLE {TABLENAME}"
125125
**/
126+
@Override
126127
void clear();
127128

129+
/**
130+
* Return the current list of ID keys for fileWorkspaceMap
131+
**/
132+
@Override
133+
Set<String> keySet();
134+
128135
// Special iteration support
129136
//--------------------------------------------------------------------------
130137

src/main/java/picoded/dstack/file/layered/FileLayered_FileWorkspaceMap.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import picoded.dstack.file.simple.FileSimple_FileWorkspaceMap;
44

55
import java.io.File;
6+
import java.util.HashSet;
7+
import java.util.Set;
68

79
public class FileLayered_FileWorkspaceMap extends FileSimple_FileWorkspaceMap {
810

@@ -51,4 +53,64 @@ public File workspaceDirObj(String oid) {
5153
return new File(baseDir, workspacePath);
5254
}
5355

56+
//--------------------------------------------------------------------------
57+
//
58+
// KeySet support
59+
//
60+
//--------------------------------------------------------------------------
61+
62+
/**
63+
* Get and returns all the GUID's, note that due to its
64+
* potential of returning a large data set, production use
65+
* should be avoided.
66+
*
67+
* @return set of keys
68+
**/
69+
@Override
70+
public Set<String> keySet() {
71+
// The return hashset
72+
HashSet<String> ret = new HashSet<String>();
73+
74+
// List all the files/folders
75+
File[] l1_dirList = baseDir.listFiles();
76+
77+
// For each one of it, process it!
78+
for (File l1_dir : l1_dirList) {
79+
// Skip if its not a directory
80+
if (!l1_dir.isDirectory()) {
81+
continue;
82+
}
83+
84+
// List all the files/folders
85+
File[] l2_dirList = l1_dir.listFiles();
86+
87+
for (File l2_dir : l2_dirList) {
88+
// Skip if its not a directory
89+
if (!l2_dir.isDirectory()) {
90+
continue;
91+
}
92+
93+
// Get the oidDirLIst
94+
File[] oid_list = l2_dir.listFiles();
95+
96+
// For each oid dir
97+
for (File oid_dir : oid_list) {
98+
// Get the presumed oid
99+
String oid = oid_dir.getName();
100+
101+
// Validate the dir name (oid)
102+
if (!validateOid(oid)) {
103+
continue;
104+
}
105+
106+
// Add the oid to the ret set
107+
ret.add(oid);
108+
}
109+
}
110+
}
111+
112+
// Return the full keyset
113+
return ret;
114+
}
115+
54116
}

src/main/java/picoded/dstack/file/simple/FileSimple_FileWorkspaceMap.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ protected boolean validateOid(String oid) {
7373
}
7474

7575
// Adding safety check for file operation, ensuring oid is alphanumeric
76-
if (!oid.matches("[a-zA-Z0-9]+")) {
76+
if (!oid.matches("[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]+")) {
7777
return false;
7878
}
7979

@@ -147,7 +147,7 @@ public void backend_setupWorkspace(String oid) {
147147
if (file == null) {
148148
throw new RuntimeException("Invalid OID (unable to setup)");
149149
}
150-
boolean mkdir = file.mkdirs();
150+
file.mkdirs();
151151
}
152152

153153
//--------------------------------------------------------------------------
@@ -627,4 +627,48 @@ public Set<String> backend_getFileAndFolderPathSet(final String oid, final Strin
627627
return backend_filterPathSet(retSet, "", minDepth, maxDepth, 0);
628628
}
629629

630+
//--------------------------------------------------------------------------
631+
//
632+
// KeySet support
633+
//
634+
//--------------------------------------------------------------------------
635+
636+
/**
637+
* Get and returns all the GUID's, note that due to its
638+
* potential of returning a large data set, production use
639+
* should be avoided.
640+
*
641+
* @return set of keys
642+
**/
643+
@Override
644+
public Set<String> keySet() {
645+
// The return hashset
646+
HashSet<String> ret = new HashSet<String>();
647+
648+
// List all the files/folders
649+
File[] dirList = baseDir.listFiles();
650+
651+
// For each one of it, process it!
652+
for (File subFile : dirList) {
653+
// Skip if its not a directory
654+
if (!subFile.isDirectory()) {
655+
continue;
656+
}
657+
658+
// Get the presumed oid
659+
String oid = subFile.getName();
660+
661+
// Validate the dir name (oid)
662+
if (!validateOid(oid)) {
663+
continue;
664+
}
665+
666+
// Add the oid to the ret set
667+
ret.add(oid);
668+
}
669+
670+
// Return the full keyset
671+
return ret;
672+
}
673+
630674
}

0 commit comments

Comments
 (0)