Corporate Logo
Skip Navigation Links
Home
AboutExpand About
News
ProductsExpand Products
Purchase
DownloadsExpand Downloads
Account
Support
Contact
 

Code Examples
This page contains an assortment code snippets that serve to demonstrate how Persistore is actually used in application code.

C# - Creating a shared dictionary.

A shared dictionary is a managed .Net object that encapsulates a reference to a kernel managed collection. The shared dictionary class appears to be a conventional collection class, but the data in the collection is not stored in the managed heap. The data is stored in shared memory, within a datapool.

If the datapool is persistent, then all of the items that you add to the dictionary are persistent too. It is therefore extremely simple to rapidly persist data by persisting individual items. The design does not simply persist a dictionary, rather it persists items as and when they are added and provides a dictionary-like wrapper that allows your code to treat the data as a dictionary.

This snippet shows how a shared/persistent dictionary can be created, populated and modified. A shared dictionary element may also be accessed and modfied using express data access, although this is not part of this example.
    class Program
    {
        static void Main(string[] args)
        {

        Datapool                             pool;
        Dir                                  collections_dir;
        DataStruct                           test_item; 
        SharedDictionary<string, DataStruct> strucs;
	
        test_item = default(DataStruct);
	
        pool = new Datapool();
	
        pool.Load("test_dictionary_pool", 50000, FileMode.Create);
	
        if (pool.IsLoaded == false)
           throw 
           new 
           InvalidOperationException
           ("Unable to load the specified datapool.");
	
        collections_dir = pool.CreateDir("Collections");
	
        strucs = new SharedDictionary<string, DataStruct>(collections_dir, "test_dictionary");
	
        /* Add an item */
	
        test_item.Count = 1;
        test_item.Name  = "john";
	
        strucs.Add("first",test_item);
	
        /* Add an item */

	
        test_item.Count = 2;
        test_item.Name = "mike";
	
        strucs.Add("second",test_item);
	
        /* Add an item */
	
        test_item.Count = 3;
        test_item.Name = "mike";
	
        strucs.Add("third",test_item);
	
        /* Overwrite the first item */
	
        strucs["first"] = test_item;
        
        }
        
    }
        

C# - Loading and initializing a datapool

This snippet shows how straightfoward it is to create and load a new datapool. Once loaded it becomes possible to create directories, shared variables etc as well as persist objects. Simply by terminating the application, all data will be safely retained and visible when next loaded.

    {

    Datapool    pool;
    
    // Create a datapool object and specify an init delegate.
    
    pool = new Datapool(initialize_pool); 
    
    // Load (i.e. map and initialize) a 2 GB datapool
    // During this method call, the init handler will
    // be invoked.
    
    pool.Load(AllocationMode.Standard, 
              AccessMode.Unprotected, 
              BackingMode.Persistent, 
              StorageMode.DynamicCompressed, 
              datapool_path, 
              Sizing.GigaBytes(2), 
              FileMode.CreateNew, 
              false);
              
    }
    
    // If the pool is new and no other thread in any other
    // process is already doing an init, then this handler 
    // will be called before the call to 'Load' completes.
    
    private void initialize_pool (Datapool new_pool)
    {
    
    // The second arg below, is an info string. It is shown by a
    // tooltip when the mouse hovers over the dir node in the 
    // Datapool Explorer utility.
    
    new_pool.Root.CreateDir ("MyTestDir","A test dir for demo purposes");
    
    }
    
    

C# - Using express data access.

Express Data Access is a powerful feature built-in to Persistore. In essence, it provides a way for application code to "ask" for a .Net memory memory reference to a persisted item. Persistore then identifies, locates or searches for the item, if the item exists a memory reference to it is created and a user defined update handler is invoked and the reference passed in as an argument.

Because the item does not need to be copied, instantiated, moved, deserialized or reflected upon, the update handler can perform updates to the item's field or properties extremely rapidly.

This snippet shows how instances of persisted structs may be accessed and updated in real-time using Express Data Access. The reference that is passed to the updater method is a real reference that points to the persisted instance in the mapped datapool memory space.

        {

        ExpressAccessResult     status;
        
        // Define the express access update handler.
        // Express data access is supported by several classes
        // including cursors, dictionaries and shared variables.
        
        strucs.ItemAccessed += update_handler;

        // Find and update the required instance. This operation
        // will search the collection's index for the key
        // and if found, will set a write lock on the datum and
        // invoked the express update handler.
        
        status = strucs.ExpressAccess(SearchCriteria.Equal,
                                      "mike", 
                                      SpinlockType.WriteLock);
                                      
        if (status == ExpressAccessResult.NoMatchingItem)
           {
           // Error, no item was found with the specified key...
           }                                      
                             
        }
        
        // This update handler will be called by persistore and passed a 
        // reference to the persisted instance of a data structure. 
        // The ref is (in effect) a pointer to the actual persisted
        // item's memory block. Thus we are able to update the item in-situ and 
        // completely avoid the copying and moving of the data item.
        
        private static ExpressAccessResult update_handler (ref DataStruct item)
        {
            if (item.Flag == 0)
               {
               item.Flag = 1;
               item.Count = 1;
               return(ExpressAccessResult.BasicUpdatesMade);
               }
               
            // Tell the system that no updates were made.
            
            return (ExpressAccessResult.NoUpdatesMade);
        }
                                     

C# - Using index attributes and proxy fields.

This snippet shows how you can decorate a class or struct with attributes that direct persistore to create and populate indices. These indices can be used for subsequent high performance accessing and updating of your data. The snippet also shows how strings can be embedded in a type without restricting the type's supported persistence modes. In a real implementaion it is preferable to use partial structs for separating the member field defintions from the various access properties.

    /// <summary>
    /// A hypothetical fixed income bond defintion.
    /// </summary>
    /// <remarks>
    /// This structure is an example of a "pure" struct, one that contains
    /// no reference type instance fields. Because of this instances of it
    /// may be persisted rapdily and can be later updated using persistore's
    /// express data access (EDA) support.
    /// Despite not containing refernce fields, we can still store string
    /// data by using "proxy" fields and special properties.
    /// </remarks>
    public unsafe struct Bond
    {
        private decimal       accrued_interest;
        private decimal       coupon_rate;
        private decimal       current_yield;
        private decimal       current_ytm;
        private DateTime      maturity_date;
        private decimal       face_value;
        private decimal       redemption_value;
        
        /*-----------------------------------------------------------------------*/
        /* These two fields are referred to as "proxy" fields in persistore.     */
        /* They are the means by which strings (either ANSI or Unicode) may be   */
        /* exposed as properties by a class or struct, while internally being    */
        /* implemented as fixed buffers (either Byte or Char). This allows the   */
        /* system to employ high performance persistence modes that do not allow */
        /* reference types member fields.                                        */
        /*-----------------------------------------------------------------------*/
        
        private Byte_8        bond_symbol;  // a proxy field.
        private Byte_64       bond_name;    // a proxy field.

        public decimal AccruedInterest
        {
            get { return accrued_interest; }
        }

        public decimal CouponRate
        {
            get { return coupon_rate; }
        }

        public decimal CurrentYield
        {
            get { return current_yield; }
        }

        public decimal CurremtYtm
        {
            get { return current_ytm; }
        }

        public DateTime MaturityDate
        {
            get { return maturity_date; }
        }

        public decimal FaceValue
        {
            get { return face_value; }
        }

        public decimal MaturityValue
        {
            get { return redemption_value; }
        }

        /*----------------------------------------------------------------*/
        /* This property will be used by persistore to extract key values */
        /* for the symbol. This is done when instances of the struct are  */
        /* are written using a Cursor<Bond> object. This also allows      */
        /* other code to perform searches and updates on the item by      */
        /* using the "Symbol" to locate the persisted item.               */
        /*----------------------------------------------------------------*/
        
        [Indexed("Symbol", "Security Symbol", Disposition.NoDuplicates, Collation.Ascending)]
        public string Symbol
        {   
        // Create and return a managed string from the fixed buffer, or copy the data
        // in a string into the fixed buffer.
        
        get
        {
        fixed (byte* p = bond_symbol.buffer)
              return (StringWrapper.ANSIPtrToString(p, Marshal.SizeOf(bond_symbol)));
        }
        
        set
        {
        fixed (byte* p = bond_symbol.buffer)
              StringWrapper.StringToANSIPtr(value, p, Marshal.SizeOf(bond_symbol));
        }
        }

        [Indexed("Name", "Security Name", Disposition.Duplicates, Collation.Ascending)]
        public string Name
        {   
        // Create and return a managed string from the fixed buffer, or copy the data
        // in a string into the fixed buffer.

        get
        {
        fixed (byte* p = bond_name.buffer)
              return (StringWrapper.ANSIPtrToString(p, Marshal.SizeOf(bond_name)));
        }
        
        set
        {
        fixed (byte* p = bond_name.buffer)
              StringWrapper.StringToANSIPtr(value, p, Marshal.SizeOf(bond_name));
        }
        }

    }

    /// 
    /// Helper types for simplifying proxy field coding.
    /// 
    public unsafe struct Byte_8  { internal fixed byte buffer[8]; }
    public unsafe struct Byte_64 { internal fixed byte buffer[64];}
    
                                         
Get more information about Persistore below.
Product Data Sheet
Technology Summary
Introduction For Developers
Get more information about Forse below.
Coming Soon
Coming Soon
   
Persistore
All content copyright © 2006 - 2010 Morantex Information Systems, Inc.
Morantex™, Persistore™, MAQS™ and NoIO™ are trademarks of
Morantex Information Systems, Inc.
 
AMD Opteron
Number of site visits:  5125