package org.opennms.netmgt.config;

import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

import org.opennms.core.utils.LogUtils;
import org.opennms.netmgt.snmp.SnmpAgentConfig;
import org.springframework.beans.factory.annotation.Autowired;

public class SnmpConfigAccessService {
    @Autowired
    private SnmpPeerFactory m_snmpPeerFactory;

    private final ExecutorService m_executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
        @Override
        public Thread newThread(final Runnable r) {
            return new Thread(r, "SnmpConfig-Accessor-Thread");
        }
    });

    public SnmpConfigAccessService() {
    }

    public void flushAll() {
        submitAndWait(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                SnmpPeerFactory.getInstance().saveCurrent();
                return null;
            }
        });
    }

    public SnmpAgentConfig getAgentConfig(final InetAddress addr) {
        flushAll();
        return submitAndWait(new Callable<SnmpAgentConfig>() {
            @Override public SnmpAgentConfig call() throws Exception {
                return SnmpPeerFactory.getInstance().getAgentConfig(addr);
            }
        });
    }

    public void define(final SnmpEventInfo eventInfo) {
        submitWriteOp(new Runnable() {
            @Override public void run() {
                SnmpPeerFactory.getInstance().define(eventInfo);
            }
        });
    }
    
    private <T> T submitAndWait(final Callable<T> callable) {
        try {
            return m_executor.submit(callable).get();
        } catch (final InterruptedException e) {
            throw new RuntimeException(e);
        } catch (final ExecutionException e) {
            if (e.getCause() instanceof RuntimeException) {
                throw ((RuntimeException) e.getCause());
            } else {
                throw new RuntimeException(e.getCause());
            }
        }
    }

    private Future<?> submitWriteOp(final Runnable r) {
        return m_executor.submit(r);
    }

}

@@ -33,36 +33,8 @@
 g;%0A%0A
-import java.io.IOException;%0A
 impo
@@ -148,53 +148,8 @@
 on;%0A
-import java.util.concurrent.ExecutorService;%0A
 impo
@@ -219,16 +219,70 @@
 Future;%0A
+import java.util.concurrent.ScheduledExecutorService;%0A
 import j
@@ -315,16 +315,54 @@
 Factory;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aimport
@@ -621,22 +621,68 @@
 private 
-final 
+boolean m_dirty = false;%0A    private final Scheduled
 Executor
@@ -727,16 +727,25 @@
 leThread
+Scheduled
 Executor
@@ -929,103 +929,50 @@
    p
-ublic SnmpConfigAccessService() %7B%0A    %7D%0A%0A    public void flushAll() %7B%0A        submitAndWait(new
+rivate final class SaveCallable implements
  Cal
@@ -982,18 +982,16 @@
 le%3CVoid%3E
-()
  %7B%0A     
@@ -985,36 +985,32 @@
 Void%3E %7B%0A        
-  
-  
 @Override%0A      
@@ -999,28 +999,24 @@
   @Override%0A
-    
         publ
@@ -1041,32 +1041,155 @@
 ows Exception %7B%0A
+            if (m_dirty) %7B%0A                LogUtils.debugf(this, %22SnmpPeerFactory has been updated. Persisting to disk.%22);%0A
                 
@@ -1233,24 +1233,67 @@
 rent();%0A    
+            m_dirty = false;%0A            %7D%0A
             
@@ -1309,39 +1309,218 @@
 ll;%0A        
+%7D%0A
     %7D%0A
+%0A
     
-    %7D
+public SnmpConfigAccessService() %7B%0A        m_executor.schedule(new SaveCallable(), 1, TimeUnit.SECONDS);%0A    %7D%0A%0A    public void flushAll() %7B%0A        submitAndWait(new SaveCallable()
 );%0A    %7D%0A%0A  
@@ -2049,16 +2049,48 @@
 tInfo);%0A
+                m_dirty = true;%0A
         

change to a scheduled executor to make sure writes persist if reads do not occur