[mapguide-users] Saving session on database

Jackie Ng jumpinjackie at gmail.com
Thu Apr 23 00:09:39 PDT 2020


Hi Roberto,

There is no pre-defined solution for this problem out of the box, so here's
some pointers so you have some ideas of how to tackle this problem.

The main problem you are going to find is that session repositories (where
your session-related state resides) is not enumerable (ie. You cannot use
Resource Service EnumerateResources API against session repositories to list
resources/folders). This is by design.

Now what is normally in a session repository? If we assume this session id
(abcd1234) and your map name is (MyMap), then a session normally will have:

 - A blob of serialized MgMap state (session:abcd1234//MyMap.Map)
 - A blob of serialized MgSelection state
(session:abcd1234//MyMap.Selection)
 - 0 or more "temporary" Feature Sources and Layer Definitions that I am
assuming the common use case of being referenced and added to your
particular runtime map instance. Buffer/Redline layer are common examples of
temporary resources that would be created and stored in your session
repository.

So with this knowledge, here's how I suggest you implement "saving" a
session. This suggestion assumes your solution is .net based and so you will
be using the .net MapGuide API and the MapGuide Maestro API. Given a session
id and map name:

 1. Create and open a MgSiteConnection from the given session id
 2. MgMap.Open() the map with the given map name
 3. Walk through all the layers of this MgMap to look for any MgLayer
instances whose resource id is session-based.
 4. Follow through each session-based layer you find.
    4.1. Read the layer definition content by calling
MgResourceService.GetResourceContent() with the given session id. Also track
this resource id.
    4.2. Look for the referenced Feature Source ID in this layer definition
content. If it is session-based, track that resource id.
 5. You should now have tracked a full list of resources ids you need to
copy out of the session repository, so for each one of these resource ids:
    5.1. Read out the resource content with
MgResourceService.GetResourceContent() and save it to external storage (by
housing the returned MgByteReader into a MgByteSink and using one of its
methods to save out the content)
    5.2. If the resource id is a feature source, call
MgResourceService.EnumerateResourceData() to enumerate all the resource data
in the feature source. This is where the .sdf, .shp, .sqlite files backing
your temporary layers reside. For each enumerated data item, call
MgResourceService.GetResourceData() to get the binary content for that data
item. Again funnel that MgByteReader into a MgByteSink to save the content
out to external storage. Save this data out in a way that you know the
file/blob is associated with feature source file/blob that you also saved
out.
 6. Use the same MgResourceService APIs to read out the serialized MgMap
state and MgSelection state and use MgByteSink to dump their contents out to
external storage.
 
At this point you should have successfully "evacuated" all the contents of
your session repository. Assuming you have structured your external storage
intuitively, here's how you would restore such a session data into another
session repository. Given another session id and map name:

 1. Create and open a MgSiteConnection from the given session id
 2. Read the saved map/selection state from external storage. This is
probably the hardest part as you have to "rewrite" session-based layer
definition ids that contain the old session id into your new session id. You
can use the RuntimeMap/MgBinarySerializer class from the MapGuide Maestro
API to assist here. The implementation is something like the OpenMap method
here
(https://github.com/jumpinjackie/mapguide-maestro/blob/fdcd29d598125b04b3dea55315c47a42f3d8cfa7/OSGeo.MapGuide.MaestroAPI/PlatformConnectionBase.cs#L2225),
but instead of opening the map from an existing runtime map state id you
open from the System.IO.Stream instances obtained from your external storage
instead. Once you loaded a RuntimeMap with your old map/selection state,
walk through the layers in this map and for every session-based layer
resource id you find, replace the session id within with your new session
id. At this point, you can Save() the "fixed" map/selection state out to
your new session repository.
 3. For every other resource saved out to external storage, restore them and
their resource data items into this new session repository using the
resource service APIs, along the way, fixing up any references to the old
session id with the new session id.
 
This is rough overview of how you could approach this problem. One thing to
note that it goes slightly against what you stated here:

> This way in case 1 server goes down, the others can take the request
> without forcing the user to recreate a new session.

This approach still expects the user to have a new session, but with this
approach you have the means to "restore" this saved session elsewhere so the
user's new session can start off empty and you just restore the contents
into it, which I think is still the overall goal you're trying to achieve
unless I'm mistaken.

Hope this helps.

- Jackie




--
Sent from: http://osgeo-org.1560.x6.nabble.com/MapGuide-Users-f4182607.html


More information about the mapguide-users mailing list