001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.preferences;
020
021import icy.common.Version;
022import icy.math.MathUtil;
023import icy.network.NetworkUtil;
024import icy.system.SystemUtil;
025
026/**
027 * @author Stephane
028 */
029public class ApplicationPreferences
030{
031    /**
032     * id
033     */
034    private static final String PREF_ID = "icy";
035
036    public static final String ID_ICY_ID = "id";
037    public static final String ID_OS = "os";
038    public static final String ID_UPDATE_REPOSITORY_BASE = "updateRepositoryBase";
039    public static final String ID_UPDATE_REPOSITORY_FILE = "updateRepositoryFile";
040    public static final String ID_MAX_MEMORY = "maxMemory";
041    public static final String ID_STACK_SIZE = "stackSize";
042    public static final String ID_CACHE_MEMORY_PERCENT = "cacheMemoryPercent";
043    public static final String ID_CACHE_PATH = "cacheMemoryPath";
044    public static final String ID_EXTRA_VMPARAMS = "extraVMParams";
045    public static final String ID_OS_EXTRA_VMPARAMS = "osExtraVMParams";
046    public static final String ID_APP_FOLDER = "appFolder";
047    public static final String ID_APP_PARAMS = "appParams";
048    public static final String ID_VERSION = "version";
049    public static final String ID_SINGLE_INSTANCE = "singleInstance";
050
051    private final static String DEFAULT_UPDATE_REPOSITORY_BASE = NetworkUtil.WEBSITE_URL + "update/";
052    // private final static String DEFAULT_UPDATE_REPOSITORY_BASE = "https://icy.yhello.co/update/";
053    private final static String DEFAULT_UPDATE_REPOSITORY_FILE = "update.php";
054
055    /**
056     * preferences
057     */
058    private static XMLPreferences preferences;
059
060    public static void load()
061    {
062        // load preference
063        preferences = IcyPreferences.root().node(PREF_ID);
064
065        // set here settings which need to be initialized
066        setMaxMemoryMB(getMaxMemoryMB());
067    }
068
069    /**
070     * @return the preferences
071     */
072    public static XMLPreferences getPreferences()
073    {
074        return preferences;
075    }
076
077    public static String getOs()
078    {
079        return preferences.get(ID_OS, "");
080    }
081
082    public static void setOs(String value)
083    {
084        preferences.put(ID_OS, value);
085    }
086
087    /**
088     * Return Icy unique Id (-1 if not yet set)
089     */
090    public static int getId()
091    {
092        return preferences.getInt(ID_ICY_ID, -1);
093    }
094
095    public static void setId(int value)
096    {
097        preferences.putInt(ID_ICY_ID, value);
098    }
099
100    public static String getUpdateRepositoryBase()
101    {
102        return preferences.get(ID_UPDATE_REPOSITORY_BASE, DEFAULT_UPDATE_REPOSITORY_BASE);
103    }
104
105    public static void setUpdateRepositoryBase(String value)
106    {
107        preferences.put(ID_UPDATE_REPOSITORY_BASE, value);
108    }
109
110    public static String getUpdateRepositoryFile()
111    {
112        return preferences.get(ID_UPDATE_REPOSITORY_FILE, DEFAULT_UPDATE_REPOSITORY_FILE);
113    }
114
115    public static void setUpdateRepositoryFile(String value)
116    {
117        preferences.put(ID_UPDATE_REPOSITORY_FILE, value);
118    }
119
120    static int memoryAlign(int memMB)
121    {
122        // arrange to get multiple of 32 MB
123        return (int) MathUtil.prevMultiple(memMB, 32);
124    }
125
126    static int checkMem(int memMB)
127    {
128        // check we can allocate that much
129        return Math.min(getMaxMemoryMBLimit(), memoryAlign(memMB));
130    }
131
132    /**
133     * Get max memory (in MB)
134     */
135    public static int getMaxMemoryMB()
136    {
137        int result = preferences.getInt(ID_MAX_MEMORY, -1);
138
139        // no value ?
140        if (result == -1)
141            result = getDefaultMemoryMB();
142
143        // arrange to get multiple of 32 MB
144        return checkMem(result);
145    }
146
147    public static int getDefaultMemoryMB()
148    {
149        final long freeMemory = SystemUtil.getFreeMemory();
150
151        // take system total memory / 2
152        long calculatedMaxMem = SystemUtil.getTotalMemory() / 2;
153        // current available memory is low ?
154        if (calculatedMaxMem > freeMemory)
155            // adjust max memory
156            calculatedMaxMem -= (calculatedMaxMem - freeMemory) / 2;
157
158        // get max memory in MB
159        return checkMem((int) (calculatedMaxMem / (1024 * 1000)));
160    }
161
162    public static int getMaxMemoryMBLimit()
163    {
164        int result = (int) (SystemUtil.getTotalMemory() / (1024 * 1000));
165
166        // limit maximum memory to 1024 MB for 32 bits system
167        if (SystemUtil.is32bits() && (result > 1024))
168            result = 1024;
169
170        return memoryAlign(result);
171    }
172
173    /**
174     * Get stack size (in KB)
175     */
176    public static int getStackSizeKB()
177    {
178        // 2MB by default for VTK
179        return preferences.getInt(ID_STACK_SIZE, 2048);
180    }
181
182    /**
183     * Get cache reserved memory (in % of max memory)
184     */
185    public static int getCacheMemoryPercent()
186    {
187        return preferences.getInt(ID_CACHE_MEMORY_PERCENT, 40);
188    }
189
190    /**
191     * Get cache reserved memory (in MB)
192     */
193    public static int getCacheMemoryMB()
194    {
195        return (int) (((SystemUtil.getJavaMaxMemory() / (1024 * 1024)) * getCacheMemoryPercent()) / 100L);
196    }
197
198    /**
199     * Get cache path (folder where to create cache data, better to use fast storage)
200     */
201    public static String getCachePath()
202    {
203        return preferences.get(ID_CACHE_PATH, SystemUtil.getTempDirectory());
204    }
205
206    /**
207     * Get extra JVM parameters string
208     */
209    public static String getExtraVMParams()
210    {
211        // we want a big perm gen space for the class loader
212        return preferences.get(ID_EXTRA_VMPARAMS, "-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:MaxPermSize=128M");
213    }
214
215    /**
216     * Get OS specific extra JVM parameters string
217     */
218    public static String getOSExtraVMParams()
219    {
220        final String os = SystemUtil.getOSNameId();
221
222        // we have different default extra VM parameters depending OS
223        if (os.equals(SystemUtil.SYSTEM_WINDOWS))
224            return preferences.get(ID_OS_EXTRA_VMPARAMS + SystemUtil.SYSTEM_WINDOWS, "");
225        if (os.equals(SystemUtil.SYSTEM_MAC_OS))
226            return preferences.get(ID_OS_EXTRA_VMPARAMS + SystemUtil.SYSTEM_MAC_OS, "-Xdock:name=Icy");
227        if (os.equals(SystemUtil.SYSTEM_UNIX))
228            return preferences.get(ID_OS_EXTRA_VMPARAMS + SystemUtil.SYSTEM_UNIX, "");
229
230        return "";
231    }
232
233    /**
234     * Get Icy application folder
235     */
236    public static String getAppFolder()
237    {
238        return preferences.get(ID_APP_FOLDER, "");
239    }
240
241    /**
242     * Get Icy application parameters string
243     */
244    public static String getAppParams()
245    {
246        return preferences.get(ID_APP_PARAMS, "");
247    }
248
249    /**
250     * Get the stored version number (used to detect new installed version).
251     */
252    public static Version getVersion()
253    {
254        return new Version(preferences.get(ID_VERSION, "1.0.0.0"));
255    }
256
257    /**
258     * Set max memory (in MB)
259     */
260    public static void setMaxMemoryMB(int value)
261    {
262        preferences.putInt(ID_MAX_MEMORY, Math.min(getMaxMemoryMBLimit(), value));
263    }
264
265    /**
266     * Set stack size (in KB)
267     */
268    public static void setStackSizeKB(int value)
269    {
270        preferences.putInt(ID_STACK_SIZE, value);
271    }
272
273    /**
274     * Set cache reserved memory (in % of max memory)
275     */
276    public static void setCacheMemoryPercent(int value)
277    {
278        // 10 <= value <= 80
279        preferences.putInt(ID_CACHE_MEMORY_PERCENT, Math.min(80, Math.max(10, value)));
280    }
281
282    /**
283     * Set cache path (folder where to create cache data, better to use fast storage)
284     */
285    public static void setCachePath(String value)
286    {
287        preferences.put(ID_CACHE_PATH, value);
288    }
289
290    /**
291     * Set extra JVM parameters string
292     */
293    public static void setExtraVMParams(String value)
294    {
295        preferences.put(ID_EXTRA_VMPARAMS, value);
296    }
297
298    /**
299     * Set OS specific extra JVM parameters string
300     */
301    public static void setOSExtraVMParams(String value)
302    {
303        preferences.put(ID_OS_EXTRA_VMPARAMS + SystemUtil.getOSNameId(), value);
304    }
305
306    /**
307     * Set Icy application folder
308     */
309    public static void setAppFolder(String value)
310    {
311        preferences.put(ID_APP_FOLDER, value);
312    }
313
314    /**
315     * Set ICY application parameters string
316     */
317    public static void setAppParams(String value)
318    {
319        preferences.put(ID_APP_PARAMS, value);
320    }
321
322    /**
323     * Set the stored version number (used to detect new installed version)
324     */
325    public static void setVersion(Version value)
326    {
327        preferences.put(ID_VERSION, value.toString());
328    }
329
330}