Hi guys,
Ok, I have read many chapters of both guides, programming and admin. But it is a bit overwhelming... so please allow me some questions. My scenario is the following... say I have some "database" that holds a client's account info, transactions, etc... I need many "instances" of the same "database"....actually one "db instance" per client..
So far, what I was doing is that I have a dictionary (persisted) in which keys are databaseIDs and values are the real DB (another dictionary). Also, the "code" or application is the same for each DB..
So far so good. Now, problem is that I want that each DB is completely isolated / secured / private to only that client. So even if my code makes sure that for client XXX I grab the database associated to it...I really want that client XXX has only access to that DB.
So I am trying to think how can I use multi-use capabilities of GemStone here. 1) So first thing I thought is to create a GemStone user per client so that each client has its own UserGlobals running each seaside and running one particular DB instance.
2) If I understand right, for each GemStone user I will have all seaside / my app classes installed / duplicated in each UserGlobals. So I thought that maybe all my app code could be shared among all users. Still, each DB should be separated and only visible/writable for the client's GemStone user.
Is there a common approach for this? which sounds better? any recommendation? Thanks in advance, |
From: "Mariano Martinez Peck" <[hidden email]>This is probably the best approach if you need "guaranteed" isolation ... It isn't absolutely necessary to install all of glass on a per user basis ... you can arrange to share the code in DataCurator with multiple GemStone users by manipulating each user's SymbolList to include DataCurator's UserGlobals SymbolDictionary ... there are some details that will have to be worked out with regards to shared state (i.e., class variables in the common code like Seaside session state, etc.), but there are a handful of solutions that can be brought to bear ... let me know when you are ready to experiment in this area and we can get into specifics... Dale |
Hi all!
I do have the same situation here, and I also took the dictionary route. The reason why I took it is that I was told that there is just a limited amount of GemstoneUsers available. "15" or so,... is that right? Sebastian Am 05.12.2013 13:34, schrieb Dale K. Henrichs:
|
From: "Sebastian Heidbrink" <[hidden email]>Good point, that I neglected to mention. I think the number is closer to 2000, but still in internet terms thats not too many users ...
|
Hi!
Thanks for claryfying this Dale! That opens some new options to me. One other solution that I decided to try are the following two approaches. I have my data model class and I subclass it for every user by adding a pre- and or postfix to the class name identifying the relationship to a specific user. The other option I was thinking about is having this one data model class and putting the instances into different UserGlobals defined collections with the pre-/postfix userName added names. And yes, Dale,... web users and the potential posibillity of user groups makes it all quite challanging ,.... at least for a newcomer :-D Good luck to all beginners! And thank you Mariano for sharing your trip! Sebastian Am 06.12.2013 07:18, schrieb Dale K. Henrichs:
|
Ciao,
My solutions, as already written in another e-mail is : In my GLASS system i create a ApplicationSystem class with some instance variables to manage the data i need for one specific application problem name Name of the environment rfrDb Dictionary for specific DataBase instance ( Costumer - Items ...... any with a specific dictionary of the relative keys) rfr..... rfrGlobal for global data relative to the specific Application After i define UserGlobals instances with the name of the specific environment. EnvironmentA -> anApplicationSystem EnvironmentB -> anApplicationSystem I create a WASession subclass DTRWASession with a 'applicationSystem' instance variable. When i open a new web session i understand from the pathString request ( or from the user login ) the relative environment name ( EnvironmentA or Environment...... ) and then i set the aDTRWASession applicationSystem instance to the specific anApplicationSystem. A this time my superclass DTRDataBase ( superclass of all my database definitions ) in the methods intercept the session with the code: | session | session := WACurrentRequestContext value session. and return the specific dictionary ^ session applicationSystem rfrDbFor: className ( Costumer - Items ...... ) Or a specific other request for example : ^ session applicationSystem rfrGlobalFor: anSymbol. Can you understand the explanation of my solution? Dario
|
Dario,
This looks like a good way to isolate customer data with a higher degree of confidence than simply "good discipline":) Thanks, Dale From: "Dario Trussardi" <[hidden email]> |
In reply to this post by dario trussardi
Hi Dario,
I think I do understand it is fairly close to the first idea I had. Since I am not using Seaside and my server does not provide any sessions right now, I might need to add such preselector. Another reason why I did not go with this "one mega Dictionary approach" is due to the 2GB cache limit of GLASS.... I thought it might make a difference SharedCache-wise (2GB limit in GLASS) if I have the users collections apart from each other. But maybe that is a wrong interpretation of things I have... I will have a look at this idea! Thanks, Dario. Sebastian Am 06.12.2013 07:59, schrieb Dario Trussardi: Ciao, |
Ciao Sebastian,
i'm non sure but i think the 2GB cache limit of GLASS is for the database instance ( extend0.dbf ) If you define more GemStone users with specific SymbolList in the database instance, all use the same cache. Or i wrong ? Dario
|
In reply to this post by SebastianHC
From: "Sebastian Heidbrink" <[hidden email]>We do not load entire object graphs into the SPC ... we only load the working set portion of an object graph ... so a if you are looking up anassociation in a dictionary only the objects that you actually touch along the way (collision buckets, etc.) are loaded into the SPC.
|
Hi Dale,
"We do not load entire object graphs into
the SPC ... we only load the working set portion of an object
graph ... so a if you are looking up anassociation in a dictionary
only the objects that you actually touch along the way (collision
buckets, etc.) are loaded into the SPC. "
So I will need to introduce object clusters if I want to make sure that I handle objects as "buckets". So what you are saying is that I do not need to worry about performance issues while having a DBDictionary with e.g. 4GB of data. Or should I still try to divide this as far as possible into several dictionaries... Sebastian |
Sebastian,
I think that the message should be that you don't want to get wrapped up premature optimization when it comes to the SPC ... In the end disk i/o is expensive, but there are no hard and fast rules about avoiding disk i/o with an SPC that is smaller than your data base, because it all depends upon the nature of your working set of data ... Obviously you should avoid scanning your entire object graph to find things, but beyond that it will come down to characterizing your performance issues and applying remedies to those problems ... there are techniques available to cut down on i/o (clustering, using indexes, etc.) but for these techniques aren't necessarily remedies in and of themselves (indexing is probably a good idea in general for large collections) and should be used once you've characterized a particular problem ... So I think that you should design your data structures to best solve your application problems if and when you find a particular problem, you might amend your data structures to provide better performance ... Dale From: "Sebastian Heidbrink" <[hidden email]> |
Free forum by Nabble | Edit this page |