Skip to content

Commit 373b83b

Browse files
committed
CGDFG blobs as nodes
1 parent 91665b3 commit 373b83b

File tree

8 files changed

+135
-11
lines changed

8 files changed

+135
-11
lines changed

src/CloudGraphsDFG/CloudGraphsDFG.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,17 @@ import ...DistributedFactorGraphs: setSolverParams!,
7676
getEstimateFields,
7777
_getname,
7878
_getmodule,
79-
getTypeFromSerializationModule
79+
getTypeFromSerializationModule,
80+
listBlobStores,
81+
BlobStoreEntry,
82+
AbstractDataEntry,
83+
MongodbDataEntry,
84+
getDataEntries,
85+
listDataEntries,
86+
getDataEntry,
87+
addDataEntry!,
88+
updateDataEntry!,
89+
deleteDataEntry!
8090

8191
using Neo4j
8292
using Base64

src/CloudGraphsDFG/entities/CloudGraphsDFG.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mutable struct CloudGraphsDFG{T <: AbstractParams} <: AbstractDFG{T}
1313
description::String #TODO Maybe remove description
1414
addHistory::Vector{Symbol}
1515
solverParams::T # Solver parameters
16+
blobStores::Dict{Symbol, AbstractBlobStore}
1617

1718
# inner constructor for all constructors in common
1819
function CloudGraphsDFG{T}(neo4jInstance::Neo4jInstance,
@@ -25,7 +26,8 @@ mutable struct CloudGraphsDFG{T <: AbstractParams} <: AbstractDFG{T}
2526
createSessionNodes::Bool=true,
2627
userData::Dict{Symbol, String} = Dict{Symbol, String}(),
2728
robotData::Dict{Symbol, String} = Dict{Symbol, String}(),
28-
sessionData::Dict{Symbol, String} = Dict{Symbol, String}()) where T <: AbstractParams
29+
sessionData::Dict{Symbol, String} = Dict{Symbol, String}(),
30+
blobStores::Dict{Symbol, AbstractBlobStore} = Dict{Symbol, AbstractBlobStore}()) where T <: AbstractParams
2931
# Validate the userId, robotId, and sessionId
3032
!isValidLabel(userId) && error("'$userId' is not a valid User ID")
3133
!isValidLabel(robotId) && error("'$robotId' is not a valid Robot ID")
@@ -35,7 +37,7 @@ mutable struct CloudGraphsDFG{T <: AbstractParams} <: AbstractDFG{T}
3537
# graph = Neo4j.getgraph(neo4jConnection)
3638
# neo4jInstance = Neo4jInstance(neo4jConnection, graph)
3739

38-
dfg = new{T}(neo4jInstance, userId, robotId, sessionId, description, addHistory, solverParams)
40+
dfg = new{T}(neo4jInstance, userId, robotId, sessionId, description, addHistory, solverParams, blobStores)
3941
# Create the session if it doesn't already exist
4042
if createSessionNodes
4143
createDfgSessionIfNotExist(dfg)
@@ -93,7 +95,6 @@ function CloudGraphsDFG(; hostname="localhost",
9395
solverParams::T=NoSolverParams(),
9496
kwargs...) where T <: AbstractParams
9597

96-
@info "Creating $sessionId"
9798
return CloudGraphsDFG{T}(hostname,
9899
port,
99100
username,
@@ -140,4 +141,5 @@ function show(io::IO, ::MIME"text/plain", c::CloudGraphsDFG)
140141
println(io, " - Neo4J instance: $(c.neo4jInstance.connection.host)")
141142
println(io, " - Session: $(c.userId):$(c.robotId):$(c.sessionId)")
142143
println(io, " - Description: ", c.description)
144+
println(io, " - Blob Stores: ", listBlobStores(c))
143145
end

src/CloudGraphsDFG/services/CloudGraphsDFG.jl

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ function updateVariable!(dfg::CloudGraphsDFG, variable::DFGVariable; skipAddErro
175175
!skipAddError && !exist && @warn "Variable label '$(variable.label)' does not exist in the factor graph, adding"
176176

177177
# Create/update the base variable
178-
# NOTE: We are no merging the variable.tags into the labels anymore. We can index by that but not
178+
# NOTE: We are not merging the variable.tags into the labels anymore. We can index by that but not
179179
# going to pollute the graph with unnecessary (and potentially dangerous) labels.
180180
addProps = Dict("softtype" => "\"$(string(typeof(getSofttype(variable))))\"")
181181
query = """
@@ -239,6 +239,10 @@ function getVariable(dfg::CloudGraphsDFG, label::Union{Symbol, String})
239239
for solverKey in listVariableSolverData(dfg, label)
240240
variable.solverDataDict[solverKey] = getVariableSolverData(dfg, label, solverKey)
241241
end
242+
dataDict = getDataEntries(dfg, label)
243+
for (k,v) in dataDict
244+
variable.dataDict[k] = v
245+
end
242246
# TODO - data entries
243247

244248
return variable
@@ -254,6 +258,9 @@ function mergeVariableData!(dfg::CloudGraphsDFG, sourceVariable::DFGVariable; cu
254258
for (k,v) in sourceVariable.solverDataDict
255259
updateVariableSolverData!(dfg, getLabel(sourceVariable), v, currentTransaction=currentTransaction)
256260
end
261+
for (k,v) in sourceVariable.dataDict
262+
updateDatEntry!(dfg, getLabel(sourceVariable), v, currentTransaction=currentTransaction)
263+
end
257264
return sourceVariable
258265
end
259266

@@ -632,6 +639,83 @@ function deletePPE!(dfg::CloudGraphsDFG, variablekey::Symbol, ppekey::Symbol=:de
632639
return _unpackPPE(dfg, props)
633640
end
634641

642+
## DataEntry CRUD
643+
644+
function getDataEntries(dfg::CloudGraphsDFG, label::Symbol; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
645+
entries = Dict{Symbol, BlobStoreEntry}()
646+
# TODO: Optimize if necessary.
647+
for key in listDataEntries(dfg, label, currentTransaction=currentTransaction)
648+
entry = getDataEntry(dfg, label, key, currentTransaction=currentTransaction)
649+
entries[entry.label] = entry
650+
end
651+
return entries
652+
end
653+
654+
function listDataEntries(dfg::CloudGraphsDFG, label::Symbol; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
655+
return _listVarSubnodesForType(
656+
dfg,
657+
label,
658+
BlobStoreEntry,
659+
"label";
660+
currentTransaction=currentTransaction)
661+
end
662+
663+
function getDataEntry(dfg::CloudGraphsDFG, label::Symbol, key::Symbol; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
664+
properties = _getVarSubnodeProperties(
665+
dfg, label,
666+
BlobStoreEntry,
667+
key;
668+
currentTransaction=currentTransaction)
669+
return Unmarshal.unmarshal(
670+
BlobStoreEntry,
671+
properties)
672+
end
673+
674+
function addDataEntry!(dfg::CloudGraphsDFG, label::Symbol, bde::AbstractDataEntry; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
675+
if bde.label in listDataEntries(dfg, label, currentTransaction=currentTransaction)
676+
error("Data label '$(bde.label)' already exists")
677+
end
678+
packed = _matchmergeVariableSubnode!(
679+
dfg,
680+
label,
681+
_getLabelsForInst(dfg, bde, parentKey=label),
682+
bde,
683+
:DATA,
684+
currentTransaction=currentTransaction)
685+
return Unmarshal.unmarshal(
686+
BlobStoreEntry,
687+
packed)
688+
end
689+
690+
function updateDataEntry!(dfg::CloudGraphsDFG, label::Symbol, bde::AbstractDataEntry; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
691+
if !(bde.label in listDataEntries(dfg, label, currentTransaction=currentTransaction))
692+
@warn "Data label '$(bde.label)' does not exist, adding"
693+
end
694+
packed = _matchmergeVariableSubnode!(
695+
dfg,
696+
label,
697+
_getLabelsForInst(dfg, bde, parentKey=label),
698+
bde,
699+
:DATA,
700+
currentTransaction=currentTransaction)
701+
return Unmarshal.unmarshal(
702+
BlobStoreEntry,
703+
packed)
704+
end
705+
706+
function deleteDataEntry!(dfg::CloudGraphsDFG, label::Symbol, key::Symbol; currentTransaction::Union{Nothing, Neo4j.Transaction}=nothing)
707+
props = _deleteVarSubnode!(
708+
dfg,
709+
label,
710+
:DATA,
711+
_getLabelsForType(dfg, BlobStoreEntry, parentKey=label),
712+
key,
713+
currentTransaction=currentTransaction)
714+
return Unmarshal.unmarshal(
715+
BlobStoreEntry,
716+
props)
717+
end
718+
635719
## VariableSolverData CRUD
636720

637721
"""

src/CloudGraphsDFG/services/CommonFunctions.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ function _structToNeo4jProps(inst::Union{User, Robot, Session, PVND, N, APPE, AB
147147
if field isa ZonedDateTime
148148
val = "datetime(\"$(string(field))\")"
149149
end
150+
if field isa UUID
151+
val = "\"$(string(field))\""
152+
end
150153
# TODO: Switch this to decorator pattern
151154
if typeof(inst) <: DFGNode
152155
# Variables
@@ -248,7 +251,7 @@ function _getLabelsForInst(dfg::CloudGraphsDFG,
248251
typeof(inst) <: DFGFactor && push!(labels, String(getLabel(inst)))
249252
typeof(inst) <: AbstractPointParametricEst && push!(labels, String(inst.solverKey))
250253
typeof(inst) <: VariableNodeData && push!(labels, String(inst.solverKey))
251-
typeof(inst) <: AbstractDataEntry && push!(labels, String(inst.key))
254+
typeof(inst) <: AbstractDataEntry && push!(labels, String(inst.label))
252255
return labels
253256
end
254257

src/DataBlobs/services/BlobStores.jl

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,13 @@ function addData!(dfg::AbstractDFG, blobstore::AbstractBlobStore, label::Symbol,
7777
return de=>db
7878
end
7979

80-
function updateData!(dfg::AbstractDFG, blobstore::AbstractBlobStore, label::Symbol, entry::AbstractDataEntry, blob::Vector{UInt8})
81-
assertHash(entry, blob, hashfunction=hashfunction)
82-
de = updateDataEntry!(dfg, label, entry)
80+
function updateData!(dfg::AbstractDFG, blobstore::AbstractBlobStore, label::Symbol, entry::AbstractDataEntry, blob::Vector{UInt8}; hashfunction = sha256)
81+
# Recalculate the hash - NOTE Assuming that this is going to be a BlobStoreEntry. TBD.
82+
newEntry = BlobStoreEntry(entry.label, entry.id, blobstore.key, bytes2hex(hashfunction(blob)),
83+
"$(dfg.userId)|$(dfg.robotId)|$(dfg.sessionId)|$(label)",
84+
entry.description, entry.mimeType, entry.createdTimestamp)
85+
86+
de = updateDataEntry!(dfg, label, newEntry)
8387
db = updateDataBlob!(blobstore, de, blob)
8488
return de=>db
8589
end
@@ -170,6 +174,25 @@ function addDataBlob!(store::FolderStore{T}, entry::BlobStoreEntry, data::T) whe
170174
end
171175
end
172176

177+
function updateDataBlob!(store::FolderStore{T}, entry::BlobStoreEntry, data::T) where T
178+
blobfilename = joinpath(store.folder,"$(entry.id).dat")
179+
entryfilename = joinpath(store.folder,"$(entry.id).json")
180+
if !isfile(blobfilename)
181+
error("Key '$(id)' doesn't exist.")
182+
elseif !isfile(entryfilename)
183+
error("Key '$(id)' doesn't exist.")
184+
else
185+
open(blobfilename, "w") do f
186+
write(f, data)
187+
end
188+
open(entryfilename, "w") do f
189+
JSON.print(f, entry)
190+
end
191+
return data
192+
end
193+
end
194+
195+
173196
function deleteDataBlob!(store::FolderStore{T}, entry::BlobStoreEntry) where T
174197
blobfilename = joinpath(store.folder,"$(entry.id).dat")
175198
entryfilename = joinpath(store.folder,"$(entry.id).json")

src/DataBlobs/services/InMemoryDataEntryBlob.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export InMemoryDataEntry
55
"""
66
$(TYPEDEF)
77
Store data temporary in memory.
8-
NOTE: Neigher Entry nor Blob will be persisted.
8+
NOTE: Neither Entry nor Blob will be persisted.
99
"""
1010
struct InMemoryDataEntry{T} <: AbstractDataEntry
1111
label::Symbol

src/DistributedFactorGraphs.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ export getBlobStore,
5454
addBlobStore!,
5555
updateBlobStore!,
5656
deleteBlobStore!,
57-
emptyBlobStore!
57+
emptyBlobStore!,
58+
listBlobStores
5859

5960
# TODO Not sure these are needed or should work everywhere, implement in cloud?
6061
export updateUserData!, updateRobotData!, updateSessionData!, deleteUserData!, deleteRobotData!, deleteSessionData!

src/services/AbstractDFG.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ addBlobStore!(dfg::AbstractDFG, bs::AbstractBlobStore) = push!(dfg.blobStores, g
196196
updateBlobStore!(dfg::AbstractDFG, bs::AbstractBlobStore) = push!(dfg.blobStores, getKey(bs)=>bs)
197197
deleteBlobStore!(dfg::AbstractDFG, key::Symbol) = pop!(dfg.blobStores, key)
198198
emptyBlobStore!(dfg::AbstractDFG) = empty!(dfg.blobStores)
199+
listBlobStores(dfg::AbstractDFG) = collect(keys(dfg.blobStores))
199200

200201
##==============================================================================
201202
## CRUD Interfaces

0 commit comments

Comments
 (0)