3428bce14ee55be73522a8df312a8eb911e47993
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onosproject.persistence.impl;
18
19 import org.apache.felix.scr.annotations.Activate;
20 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Deactivate;
22 import org.apache.felix.scr.annotations.Service;
23 import org.mapdb.DB;
24 import org.mapdb.DBMaker;
25 import org.onosproject.persistence.PersistenceService;
26 import org.onosproject.persistence.PersistentMapBuilder;
27 import org.onosproject.persistence.PersistentSetBuilder;
28 import org.slf4j.Logger;
29
30 import java.io.IOException;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.nio.file.Paths;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.Timer;
37 import java.util.TimerTask;
38
39 import static org.slf4j.LoggerFactory.getLogger;
40
41 /**
42  * Service that maintains local disk backed maps and sets.  This implementation automatically deletes empty structures
43  * on shutdown.
44  */
45 @Component(immediate = true)
46 @Service
47 public class PersistenceManager implements PersistenceService {
48
49     private static final String DATABASE_PATH = "../data/localDB";
50
51     private static final String ENCLOSING_FOLDER = "../data";
52
53     static final String MAP_PREFIX = "map:";
54
55     static final String SET_PREFIX = "set:";
56
57     private final Logger log = getLogger(getClass());
58
59     private DB localDB = null;
60
61     private static final int FLUSH_FREQUENCY_MILLIS = 3000;
62
63     private Timer timer;
64
65     private final CommitTask commitTask = new CommitTask();
66
67     @Activate
68     public void activate() {
69         timer = new Timer();
70         Path dbPath = Paths.get(DATABASE_PATH);
71         Path dbFolderPath = Paths.get(ENCLOSING_FOLDER);
72         //Make sure the directory exists, if it does not, make it.
73         if (!dbFolderPath.toFile().isDirectory()) {
74             log.info("The specified folder location for the database did not exist and will be created.");
75             try {
76                 Files.createDirectories(dbFolderPath);
77             } catch (IOException e) {
78                 log.error("Could not create the required folder for the database.");
79                 throw new PersistenceException("Database folder could not be created.");
80             }
81         }
82         //Notify if the database file does not exist.
83         boolean dbFound = Files.exists(dbPath);
84         if (!dbFound) {
85             log.info("The database file could not be located, a new database will be constructed.");
86
87         } else {
88             log.info("A previous database file has been found.");
89         }
90         localDB = DBMaker.newFileDB(dbPath.toFile())
91                 .asyncWriteEnable()
92                 .closeOnJvmShutdown()
93                 .make();
94         timer.schedule(commitTask, FLUSH_FREQUENCY_MILLIS, FLUSH_FREQUENCY_MILLIS);
95         log.info("Started");
96     }
97
98     @Deactivate
99     public void deactivate() {
100         timer.cancel();
101         for (Map.Entry<String, Object> entry : localDB.getAll().entrySet()) {
102             String key = entry.getKey();
103             Object value = entry.getValue();
104                 //This is a map implementation to be handled as such
105             if (value instanceof Map) {
106                 Map asMap = (Map) value;
107                 if (asMap.isEmpty()) {
108                     //the map is empty and may be deleted
109                     localDB.delete(key);
110                 }
111                 //This is a set implementation and can be handled as such
112             } else if (value instanceof Set) {
113                 Set asSet = (Set) value;
114                 if (asSet.isEmpty()) {
115                     //the set is empty and may be deleted
116                     localDB.delete(key);
117                 }
118             }
119         }
120         localDB.commit();
121         localDB.close();
122         log.info("Stopped");
123     }
124
125     public <K, V> PersistentMapBuilder<K, V> persistentMapBuilder() {
126         return new DefaultPersistentMapBuilder<>(localDB);
127     }
128
129     public <E> PersistentSetBuilder<E> persistentSetBuilder() {
130         return new DefaultPersistentSetBuilder<>(localDB);
131     }
132
133     private class CommitTask extends TimerTask {
134
135         @Override
136         public void run() {
137             localDB.commit();
138         }
139     }
140 }