none
E2013 TA C# Windows: How do I use a configuration file with a TA RRS feed

  • Question

  • Hello,

    I'm building a transport agent for Exchange 2013 and I would like to use a configuration file for this agent.

    I do not want to read the configuration file each time a TA is created in order to avoid the IO and time needed, is there a way to have it memory for all instances of the agent?

    Thanks in advance,

    Christos

    Tuesday, September 27, 2016 7:46 PM

Answers

  • If you store the configuration in the Windows Registry that will be an InMemory store and avoid I/O otherwise and supports changes without restarting etc. But it really depends how big the configuration you want to read in is whether that is practical Exchange doesn't provide a way to do what you want but you can implement your own caching mechanism eg something like http://memcached.org/ etc

    Cheers
    Glen

    Wednesday, September 28, 2016 1:25 AM
  • So, I created a separate class for the configuration of the agent and I added some methods to read the configuration from the file, cache it and read it from there for the next reads.

    The configuration file is now red only the first time and one time after the cache expires. I've set it to expire every 5 minutes in order to apply changes without restarting the transport service.

    Thanks again Glen!

    Regards,

    Christos

    • Proposed as answer by Peter Nagl Monday, November 14, 2016 1:42 PM
    • Marked as answer by Christos Polydorou Monday, November 14, 2016 4:44 PM
    Wednesday, September 28, 2016 4:56 PM

All replies

  • If you store the configuration in the Windows Registry that will be an InMemory store and avoid I/O otherwise and supports changes without restarting etc. But it really depends how big the configuration you want to read in is whether that is practical Exchange doesn't provide a way to do what you want but you can implement your own caching mechanism eg something like http://memcached.org/ etc

    Cheers
    Glen

    Wednesday, September 28, 2016 1:25 AM
  • Thank you Glen, you've pointed me to the right direction. I won't be using memcached since I do not want to make any changes to the Exchange server but I'm thinking of giving System.Runtime.Caching a try.

    By the way, the configuration file is going to be a bit large since it will contain about 500 smtp addresses based on which I will take actions in the TA.

    Regards,

    Christos.

    Wednesday, September 28, 2016 6:38 AM
  • So, I created a separate class for the configuration of the agent and I added some methods to read the configuration from the file, cache it and read it from there for the next reads.

    The configuration file is now red only the first time and one time after the cache expires. I've set it to expire every 5 minutes in order to apply changes without restarting the transport service.

    Thanks again Glen!

    Regards,

    Christos

    • Proposed as answer by Peter Nagl Monday, November 14, 2016 1:42 PM
    • Marked as answer by Christos Polydorou Monday, November 14, 2016 4:44 PM
    Wednesday, September 28, 2016 4:56 PM
  • Hi Christos, 

    I have the same situation and your solution sounds promising. I need to check a whitelist for my TA.

    Can you share your code on how you implemented it?

    Your wrote that you implemented a cache (based on System.Runtime.Caching?).

    Where in the code do you call the Caching?

    kind Regards

    Peter


    Monday, November 14, 2016 1:51 PM
  • Hello Peter,

    First of all I would like to describe the solution in general.

    I have created a separate class for the configuration of the TA and a second class to implement something like a cache layer. I have used the functions from the cache layer in the constructors of the configuration class in order to get the data from a configuration file or the cache.

    Below is the CacheLayer class. It's been a while since I created it and I don't recall the article that helped me with the functions...

    public class CacheLayer
    {
        static readonly ObjectCache Cache = MemoryCache.Default;
    
        // Get an item from the cache
        public T Get<T>(string key) where T : class
        {
            try
            {
                return (T)Cache[key];
            }
            catch
            {
                return null;
            }
        }
    
        // Add an item to the cache
        public void Add<T>(T objectToCache, string key, int age) where T : class
        {
            Cache.Add(key, objectToCache, DateTime.Now.AddMinutes(age));
        }
    
        // Add an item to the cache
        public void Add(object objectToCache, string key, int age)
        {
            Cache.Add(key, objectToCache, DateTime.Now.AddMinutes(age));
        }
    
        // Remove an item from the cache
        public static void Clear(string key)
        {
            Cache.Remove(key);
        }
    
        // check if an item exists in cache
        public bool Exists(string key)
        {
            return Cache.Get(key) != null;
        }
    
        // Get all cached items as a list by their key.
        public static List<string> GetAll()
        {
            return Cache.Select(keyValuePair => keyValuePair.Key).ToList();
        }
    }

    As you can see, there are functions to add an item to the cache, remove it, check if it exists in cache and get it.

    Now, when a configuration class get's created, the constructor tries to get the individual items from the cache (such as a whitelist) and if the items are not there (the Exists method) it reads them from the file on disk.

    I would also suggest adding some configuration to the registry in order to be able to control the TA without restarting the Transport service. I added a DWORD that controls whether the TA acts on messages or not and a setting for the maximum cache age.

    I hope this helps,

    Christos.



    Monday, November 14, 2016 4:40 PM