Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
177f16ac
Commit
177f16ac
authored
Oct 27, 2025
by
Luna Riegel
Browse files
Refactor: Implement Checker multithreading
parent
97349c76
Changes
6
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/CacheManager.java
View file @
177f16ac
package
de.hft.stuttgart.citydoctor2.database
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlId
;
import
de.hft.stuttgart.citydoctor2.parser.InvalidGmlFileException
;
import
de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry
;
import
org.apache.commons.io.FilenameUtils
;
...
...
@@ -43,4 +44,7 @@ public class CacheManager {
}
public
static
void
preCacheFeatures
(
List
<
GmlId
>
features
)
{
cache
.
preCacheFeatures
(
features
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/CityObjectCache.java
View file @
177f16ac
...
...
@@ -23,4 +23,6 @@ public interface CityObjectCache {
void
resetCache
();
List
<
CityObject
>
retrieveLibraryObject
(
String
fileName
)
throws
InvalidGmlFileException
;
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/database/FeatureCache.java
View file @
177f16ac
...
...
@@ -55,7 +55,6 @@ public class FeatureCache implements CityObjectCache{
private
void
batchMarshall
(){
logger
.
trace
(
"Setting up batch Marshaller"
);
Map
<
GmlId
,
CityObject
>
cacheContent
=
new
HashMap
<>(
cache
.
asMap
());
...
...
@@ -102,6 +101,10 @@ public class FeatureCache implements CityObjectCache{
});
}
public
void
preCacheFeatures
(
List
<
GmlId
>
ids
)
{
cache
.
getAll
(
ids
);
}
@Override
public
void
replace
(
GmlId
id
,
CityObject
cityObject
)
{
cache
.
invalidate
(
id
);
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CityDoctorModel.java
View file @
177f16ac
...
...
@@ -196,6 +196,20 @@ public class CityDoctorModel {
}
}
public
void
preCacheShownFeatures
(){
List
<
GmlId
>
features
=
new
ArrayList
<>();
features
.
addAll
(
buildings
.
subList
(
0
,
Math
.
min
(
buildings
.
size
(),
200
)));
features
.
addAll
(
vegetation
.
subList
(
0
,
Math
.
min
(
vegetation
.
size
(),
200
)));
features
.
addAll
(
bridges
.
subList
(
0
,
Math
.
min
(
bridges
.
size
(),
200
)));
features
.
addAll
(
land
.
subList
(
0
,
Math
.
min
(
land
.
size
(),
200
)));
features
.
addAll
(
roads
.
subList
(
0
,
Math
.
min
(
roads
.
size
(),
200
)));
features
.
addAll
(
tunnels
.
subList
(
0
,
Math
.
min
(
tunnels
.
size
(),
200
)));
features
.
addAll
(
water
.
subList
(
0
,
Math
.
min
(
water
.
size
(),
200
)));
features
.
addAll
(
cityfurniture
.
subList
(
0
,
Math
.
min
(
cityfurniture
.
size
(),
200
)));
features
.
addAll
(
genericObjects
.
subList
(
0
,
Math
.
min
(
genericObjects
.
size
(),
200
)));
CacheManager
.
preCacheFeatures
(
features
);
}
private
void
exportAsGML
(
String
file
)
throws
CityDoctorWriteException
{
CityGMLWriterUtils
.
writeCityModel
(
file
,
this
);
}
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/Checker.java
View file @
177f16ac
...
...
@@ -89,6 +89,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
java.util.concurrent.*
;
import
java.util.stream.Stream
;
/**
...
...
@@ -195,6 +196,9 @@ public class Checker {
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"Checker.checksFinished"
));
}
if
(
l
!=
null
)
{
l
.
updateProgress
(-
1
);
}
SvrlContentHandler
handler
=
executeSchematronValidationIfAvailable
(
config
,
model
.
getFile
());
if
(
handler
!=
null
)
{
handleSchematronResults
(
handler
);
...
...
@@ -629,28 +633,65 @@ public class Checker {
private
void
checkCityModel
(
CityDoctorModel
model
,
ProgressListener
l
)
{
Stream
<
CityObject
>
features
=
model
.
createFeatureStream
();
float
featureSum
=
model
.
getNumberOfFeatures
();
boolean
lowMemoryMode
=
config
.
getParserConfiguration
().
useLowMemoryConsumption
();
// clear global errors
model
.
getGlobalErrors
().
clear
();
// stupid lamda with final variable restrictions
int
[]
currentFeature
=
new
int
[
1
];
features
.
forEach
(
co
->
{
if
(
config
.
getParserConfiguration
().
useLowMemoryConsumption
())
{
// no edges have been created yet, create them
co
.
prepareForChecking
();
}
// check every feature
executeChecksForCityObject
(
co
);
if
(
config
.
getParserConfiguration
().
useLowMemoryConsumption
())
{
// low memory consumption, remove edges again
co
.
clearMetaInformation
();
}
if
(
l
!=
null
)
{
currentFeature
[
0
]++;
l
.
updateProgress
(
currentFeature
[
0
]
/
featureSum
);
CheckerThreadsSynchronizer
sync
=
new
CheckerThreadsSynchronizer
(
model
,
l
);
ExecutorService
exec
=
new
ThreadPoolExecutor
(
10
,
10
,
60L
,
TimeUnit
.
SECONDS
,
new
LinkedBlockingQueue
<>());
Runnable
run
=
new
Runnable
()
{
@Override
public
void
run
()
{
while
(
sync
.
hasNext
())
{
CityObject
co
=
sync
.
getNext
();
// if (lowMemoryMode) {
co
.
prepareForChecking
();
// }
executeChecksForCityObject
(
co
);
// if (lowMemoryMode) {
co
.
clearMetaInformation
();
// }
sync
.
updateFeature
(
co
);
sync
.
updateCheckedCount
();
}
}
});
};
long
startTime
=
System
.
nanoTime
();
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
exec
.
execute
(
run
);
}
// // stupid lamda with final variable restrictions
// int[] currentFeature = new int[1];
// features.forEach(co -> {
// if (lowMemoryMode) {
// // no edges have been created yet, create them
// co.prepareForChecking();
// }
// // check every feature
// executeChecksForCityObject(co);
//
// if (lowMemoryMode) {
// // low memory consumption, remove edges again
// co.clearMetaInformation();
// }
// if (l != null) {
// currentFeature[0]++;
// l.updateProgress(currentFeature[0] / featureSum);
// }
// });
exec
.
shutdown
();
try
{
exec
.
awaitTermination
(
30
,
TimeUnit
.
DAYS
);
long
endTime
=
System
.
nanoTime
();
logger
.
info
(
"Time: "
+
(
endTime
-
startTime
)
/
1_000_000
+
" ms"
);
model
.
preCacheShownFeatures
();
}
catch
(
InterruptedException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
private
boolean
filterObject
(
CityObject
co
)
{
...
...
CityDoctorParent/CityDoctorValidation/src/main/java/de/hft/stuttgart/citydoctor2/check/CheckerThreadsSynchronizer.java
0 → 100644
View file @
177f16ac
package
de.hft.stuttgart.citydoctor2.check
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.datastructure.GmlId
;
import
de.hft.stuttgart.citydoctor2.parser.ProgressListener
;
import
java.util.EmptyStackException
;
import
java.util.Stack
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.locks.ReentrantLock
;
public
class
CheckerThreadsSynchronizer
{
private
AtomicInteger
checkedCount
=
new
AtomicInteger
(
0
);
private
final
float
featureCount
;
private
CityDoctorModel
model
;
private
ProgressListener
listener
;
private
ReentrantLock
lock
=
new
ReentrantLock
();
private
Stack
<
GmlId
>
ids
;
public
CheckerThreadsSynchronizer
(
CityDoctorModel
model
,
ProgressListener
listener
)
{
this
.
model
=
model
;
this
.
listener
=
listener
;
featureCount
=
model
.
getNumberOfFeatures
();
ids
=
new
Stack
<>();
ids
.
addAll
(
model
.
getFeatureIds
());
}
public
CityObject
getNext
()
{
// lock.lock();
// try {
if
(!
ids
.
isEmpty
()){
return
model
.
getCache
().
get
(
ids
.
pop
());
}
return
null
;
// } finally {
// lock.unlock();
// }
};
public
void
updateFeature
(
CityObject
feature
)
{
model
.
getCache
().
put
(
feature
);
}
public
boolean
hasNext
(){
// lock.lock();
try
{
ids
.
peek
();
return
true
;
}
catch
(
EmptyStackException
e
)
{
return
false
;
}
finally
{
// lock.unlock();
}
}
public
void
updateCheckedCount
(){
checkedCount
.
getAndIncrement
();
if
(
listener
!=
null
){
listener
.
updateProgress
(
checkedCount
.
get
()
/
featureCount
);
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment