/* * * * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com) * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * * For more information: http://www.orientechnologies.com * */ package com.orientechnologies.orient.core.config; import com.orientechnologies.common.log.OLogManager; import com.orientechnologies.orient.core.Orient; import com.orientechnologies.orient.core.conflict.ORecordConflictStrategyFactory; import com.orientechnologies.orient.core.exception.OSerializationException; import com.orientechnologies.orient.core.exception.OStorageException; import com.orientechnologies.orient.core.id.OImmutableRecordId; import com.orientechnologies.orient.core.id.ORecordId; import com.orientechnologies.orient.core.metadata.schema.OType; import com.orientechnologies.orient.core.metadata.schema.clusterselection.ORoundRobinClusterSelectionStrategy; import com.orientechnologies.orient.core.record.impl.OBlob; import com.orientechnologies.orient.core.serialization.OSerializableStream; import com.orientechnologies.orient.core.sql.parser.OStatement; import com.orientechnologies.orient.core.storage.OStorage; import com.orientechnologies.orient.core.storage.impl.local.paginated.OLocalPaginatedStorage; import java.io.IOException; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Versions: * <ul> * <li>3 = introduced file directory in physical segments and data-segment id in clusters</li> * <li>4 = ??</li> * <li>5 = ??</li> * <li>6 = ??</li> * <li>7 = ??</li> * <li>8 = introduced cluster selection strategy as string</li> * <li>9 = introduced minimumclusters as string</li> * <li>12 = introduced record conflict strategy as string in both storage and paginated clusters</li> * <li>13 = introduced cluster status to manage cluster as "offline" with the new command "alter cluster status offline". Removed * data segments</li> * <li>14 = no changes, but version was incremented</li> * <li>15 = introduced encryption and encryptionKey</li> * </ul> * * @author Luca Garulli (l.garulli--at--orientechnologies.com) */ @SuppressWarnings("serial") public class OStorageConfiguration implements OSerializableStream { public static final ORecordId CONFIG_RID = new OImmutableRecordId(0, 0); public static final String DEFAULT_CHARSET = "UTF-8"; public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; private String charset; public static final int CURRENT_VERSION = 17; public static final int CURRENT_BINARY_FORMAT_VERSION = 12; private final List<OStorageEntryConfiguration> properties = new ArrayList<OStorageEntryConfiguration>(); protected final transient OStorage storage; private volatile OContextConfiguration configuration; public volatile int version; public volatile String name; public volatile String schemaRecordId; public volatile String dictionaryRecordId; public volatile String indexMgrRecordId; public volatile String dateFormat; public volatile String dateTimeFormat; public volatile int binaryFormatVersion; public volatile OStorageSegmentConfiguration fileTemplate; public volatile List<OStorageClusterConfiguration> clusters; private volatile String localeLanguage; private volatile String localeCountry; private volatile TimeZone timeZone; private transient volatile Locale localeInstance; private transient volatile DecimalFormatSymbols unusualSymbols; private volatile String clusterSelection; private volatile String conflictStrategy; private volatile String recordSerializer; private volatile int recordSerializerVersion; private volatile boolean strictSQL; private volatile Map<String, Object> loadProperties; private volatile ConcurrentMap<String, IndexEngineData> indexEngines; private volatile transient boolean validation = true; private volatile boolean txRequiredForSQLGraphOperations; public OStorageConfiguration(final OStorage iStorage) { storage = iStorage; initConfiguration(); clear(); } public void initConfiguration() { configuration = new OContextConfiguration(); } public void clear() { fileTemplate = new OStorageSegmentConfiguration(); charset = DEFAULT_CHARSET; synchronized (properties) { properties.clear(); } version = -1; name = null; schemaRecordId = null; dictionaryRecordId = null; indexMgrRecordId = null; dateFormat = DEFAULT_DATE_FORMAT; dateTimeFormat = DEFAULT_DATETIME_FORMAT; binaryFormatVersion = 0; clusters = Collections.synchronizedList(new ArrayList<OStorageClusterConfiguration>()); localeLanguage = Locale.getDefault().getLanguage(); localeCountry = Locale.getDefault().getCountry(); timeZone = TimeZone.getDefault(); localeInstance = null; unusualSymbols = null; clusterSelection = null; conflictStrategy = null; getContextConfiguration().setValue(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS, OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS.getValueAsInteger()); // 0 = AUTOMATIC autoInitClusters(); recordSerializer = null; recordSerializerVersion = 0; strictSQL = false; txRequiredForSQLGraphOperations = true; indexEngines = new ConcurrentHashMap<String, IndexEngineData>(); validation = OGlobalConfiguration.DB_VALIDATION.getValueAsBoolean(); binaryFormatVersion = CURRENT_BINARY_FORMAT_VERSION; txRequiredForSQLGraphOperations = OGlobalConfiguration.SQL_GRAPH_CONSISTENCY_MODE.getValueAsString().equalsIgnoreCase("tx"); } private void autoInitClusters() { if (getContextConfiguration().getValueAsInteger(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS) == 0) { final int cpus = Runtime.getRuntime().availableProcessors(); getContextConfiguration().setValue(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS, cpus > 64 ? 64 : cpus); } } public String getConflictStrategy() { return conflictStrategy; } public void setConflictStrategy(String conflictStrategy) { this.conflictStrategy = conflictStrategy; } public OContextConfiguration getContextConfiguration() { return configuration; } /** * This method load the record information by the internal cluster segment. It's for compatibility with older database than * 0.9.25. * * @param iProperties * @return * @throws OSerializationException * @compatibility 0.9.25 */ public OStorageConfiguration load(final Map<String, Object> iProperties) throws OSerializationException { initConfiguration(); final String compressionMethod = (String) iProperties .get(OGlobalConfiguration.STORAGE_COMPRESSION_METHOD.getKey().toLowerCase()); if (compressionMethod != null) // SAVE COMPRESSION METHOD IN CONFIGURATION configuration.setValue(OGlobalConfiguration.STORAGE_COMPRESSION_METHOD, compressionMethod); final String encryptionMethod = (String) iProperties.get(OGlobalConfiguration.STORAGE_ENCRYPTION_METHOD.getKey().toLowerCase()); if (encryptionMethod != null) // SAVE ENCRYPTION METHOD IN CONFIGURATION configuration.setValue(OGlobalConfiguration.STORAGE_ENCRYPTION_METHOD, encryptionMethod); final String encryptionKey = (String) iProperties.get(OGlobalConfiguration.STORAGE_ENCRYPTION_KEY.getKey().toLowerCase()); if (encryptionKey != null) // SAVE ENCRYPTION KEY IN CONFIGURATION configuration.setValue(OGlobalConfiguration.STORAGE_ENCRYPTION_KEY, encryptionKey); final byte[] record = storage.readRecord(CONFIG_RID, null, false, false, null).getResult().buffer; if (record == null) throw new OStorageException("Cannot load database configuration. The database seems corrupted"); fromStream(record); this.loadProperties = new HashMap<String, Object>(iProperties); return this; } public Map<String, Object> getLoadProperties() { if (loadProperties == null) return Collections.emptyMap(); return Collections.unmodifiableMap(loadProperties); } public void update() throws OSerializationException { final byte[] record = toStream(); storage.updateRecord(CONFIG_RID, true, record, -1, OBlob.RECORD_TYPE, 0, null); } public boolean isEmpty() { return clusters.isEmpty(); } public String getDirectory() { return fileTemplate.location != null ? fileTemplate.getLocation() : ((OLocalPaginatedStorage) storage).getStoragePath(); } public Locale getLocaleInstance() { if (localeInstance == null) localeInstance = new Locale(localeLanguage, localeCountry); return localeInstance; } public void resetLocaleInstance() { localeInstance = null; } public SimpleDateFormat getDateFormatInstance() { final SimpleDateFormat dateFormatInstance = new SimpleDateFormat(dateFormat); dateFormatInstance.setLenient(false); dateFormatInstance.setTimeZone(timeZone); return dateFormatInstance; } public SimpleDateFormat getDateTimeFormatInstance() { final SimpleDateFormat dateTimeFormatInstance = new SimpleDateFormat(dateTimeFormat); dateTimeFormatInstance.setLenient(false); dateTimeFormatInstance.setTimeZone(timeZone); return dateTimeFormatInstance; } public DecimalFormatSymbols getUnusualSymbols() { if (unusualSymbols == null) unusualSymbols = new DecimalFormatSymbols(getLocaleInstance()); return unusualSymbols; } public void fromStream(final byte[] stream, int offset, int length) { clear(); final String[] values = new String(stream, offset, length).split("\\|"); int index = 0; version = Integer.parseInt(read(values[index++])); name = read(values[index++]); schemaRecordId = read(values[index++]); dictionaryRecordId = read(values[index++]); if (version > 0) indexMgrRecordId = read(values[index++]); else // @COMPATIBILITY indexMgrRecordId = null; localeLanguage = read(values[index++]); localeCountry = read(values[index++]); dateFormat = read(values[index++]); dateTimeFormat = read(values[index++]); // @COMPATIBILITY 1.2.0 if (version >= 4) { timeZone = TimeZone.getTimeZone(read(values[index++])); charset = read(values[index++]); } final ORecordConflictStrategyFactory conflictStrategyFactory = Orient.instance().getRecordConflictStrategy(); if (version >= 12) conflictStrategy = conflictStrategyFactory.getStrategy(read(values[index++])).getName(); else conflictStrategy = conflictStrategyFactory.getDefaultStrategy(); // @COMPATIBILITY if (version > 1) index = phySegmentFromStream(values, index, fileTemplate); int size = Integer.parseInt(read(values[index++])); // PREPARE THE LIST OF CLUSTERS clusters.clear(); String determineStorageCompression = null; for (int i = 0; i < size; ++i) { final int clusterId = Integer.parseInt(read(values[index++])); if (clusterId == -1) continue; final String clusterName = read(values[index++]); final int targetDataSegmentId = version >= 3 ? Integer.parseInt(read(values[index++])) : 0; final String clusterType = read(values[index++]); final OStorageClusterConfiguration currentCluster; if (clusterType.equals("d")) { final boolean cc = Boolean.valueOf(read(values[index++])); final float bb = Float.valueOf(read(values[index++])); final float aa = Float.valueOf(read(values[index++])); final String clusterCompression = read(values[index++]); if (determineStorageCompression == null) // TRY TO DETERMINE THE STORAGE COMPRESSION. BEFORE VERSION 11 IT WASN'T STORED IN STORAGE CFG, SO GET FROM THE FIRST // CLUSTER determineStorageCompression = clusterCompression; String clusterEncryption = null; if (version >= 15) clusterEncryption = read(values[index++]); final String clusterConflictStrategy; if (version >= 12) clusterConflictStrategy = read(values[index++]); else // INHERIT THE STRATEGY IN STORAGE clusterConflictStrategy = null; OStorageClusterConfiguration.STATUS status = OStorageClusterConfiguration.STATUS.ONLINE; if (version >= 13) status = OStorageClusterConfiguration.STATUS.valueOf(read(values[index++])); currentCluster = new OStoragePaginatedClusterConfiguration(this, clusterId, clusterName, null, cc, bb, aa, clusterCompression, clusterEncryption, configuration.getValueAsString(OGlobalConfiguration.STORAGE_ENCRYPTION_KEY), clusterConflictStrategy, status); } else if (clusterType.equals("p")) // PHYSICAL CLUSTER throw new IllegalArgumentException("Cluster of storage 'local' are not supported since 2.0"); else throw new IllegalArgumentException("Unsupported cluster type: " + clusterType); // MAKE ROOMS, EVENTUALLY FILLING EMPTIES ENTRIES for (int c = clusters.size(); c <= clusterId; ++c) clusters.add(null); clusters.set(clusterId, currentCluster); } if (version < 13) { // OLD: READ DATA-SEGMENTS size = Integer.parseInt(read(values[index++])); for (int i = 0; i < size; ++i) { int dataId = Integer.parseInt(read(values[index++])); if (dataId == -1) continue; read(values[index++]); read(values[index++]); read(values[index++]); read(values[index++]); } // READ TX_SEGMENT STUFF read(values[index++]); read(values[index++]); read(values[index++]); read(values[index++]); read(values[index++]); } size = Integer.parseInt(read(values[index++])); clearProperties(); for (int i = 0; i < size; ++i) setProperty(read(values[index++]), read(values[index++])); if (version >= 7) binaryFormatVersion = Integer.parseInt(read(values[index++])); else if (version == 6) binaryFormatVersion = 9; else binaryFormatVersion = 8; if (version >= 8) clusterSelection = read(values[index++]); else // DEFAULT = ROUND-ROBIN clusterSelection = ORoundRobinClusterSelectionStrategy.NAME; if (version >= 9) setMinimumClusters(Integer.parseInt(read(values[index++]))); else // DEFAULT = 1 setMinimumClusters(1); autoInitClusters(); if (version >= 10) { recordSerializer = read(values[index++]); recordSerializerVersion = Integer.parseInt(read(values[index++])); } if (version >= 11) { // READ THE CONFIGURATION final int cfgSize = Integer.parseInt(read(values[index++])); for (int i = 0; i < cfgSize; ++i) { final String key = read(values[index++]); final Object value = read(values[index++]); final OGlobalConfiguration cfg = OGlobalConfiguration.findByKey(key); if (cfg != null) { if (value != null) configuration.setValue(key, OType.convert(value, cfg.getType())); } else OLogManager.instance().warn(this, "Ignored storage configuration because not supported: %s=%s", key, value); } } else // SAVE STORAGE COMPRESSION METHOD AS PROPERTY configuration.setValue(OGlobalConfiguration.STORAGE_COMPRESSION_METHOD, determineStorageCompression); if (version > 15) { final int enginesSize = Integer.parseInt(read(values[index++])); for (int i = 0; i < enginesSize; i++) { final String name = read(values[index++]); final String algorithm = read(values[index++]); final String indexType; if (version > 16) indexType = read(values[index++]); else indexType = ""; final byte valueSerializerId = Byte.parseByte(read(values[index++])); final byte keySerializerId = Byte.parseByte(read(values[index++])); final boolean isAutomatic = Boolean.parseBoolean(read((values[index++]))); final Boolean durableInNonTxMode; if (read(values[index]) == null) { durableInNonTxMode = null; index++; } else durableInNonTxMode = Boolean.parseBoolean(read(values[index++])); final int version = Integer.parseInt(read(values[index++])); final boolean nullValuesSupport = Boolean.parseBoolean(read((values[index++]))); final int keySize = Integer.parseInt(read(values[index++])); final int typesLength = Integer.parseInt(read(values[index++])); final OType[] types = new OType[typesLength]; for (int n = 0; n < types.length; n++) { final OType type = OType.valueOf(read(values[index++])); types[n] = type; } final int propertiesSize = Integer.parseInt(read(values[index++])); final Map<String, String> engineProperties; if (propertiesSize == 0) engineProperties = null; else { engineProperties = new HashMap<String, String>(propertiesSize); for (int n = 0; n < propertiesSize; n++) { final String key = read(values[index++]); final String value = read(values[index++]); engineProperties.put(key, value); } } final IndexEngineData indexEngineData = new IndexEngineData(name, algorithm, indexType, durableInNonTxMode, version, valueSerializerId, keySerializerId, isAutomatic, types, nullValuesSupport, keySize, engineProperties); indexEngines.put(name.toLowerCase(getLocaleInstance()), indexEngineData); } } } public OSerializableStream fromStream(final byte[] iStream) throws OSerializationException { fromStream(iStream, 0, iStream.length); return this; } public byte[] toStream() throws OSerializationException { return toStream(Integer.MAX_VALUE); } /** * Added version used for managed Network Versioning. * * @param iNetworkVersion * @return * @throws OSerializationException */ public byte[] toStream(final int iNetworkVersion) throws OSerializationException { final StringBuilder buffer = new StringBuilder(8192); write(buffer, CURRENT_VERSION); write(buffer, name); write(buffer, schemaRecordId); write(buffer, dictionaryRecordId); write(buffer, indexMgrRecordId); write(buffer, localeLanguage); write(buffer, localeCountry); write(buffer, dateFormat); write(buffer, dateTimeFormat); write(buffer, timeZone.getID()); write(buffer, charset); if (iNetworkVersion > 24) write(buffer, conflictStrategy); phySegmentToStream(buffer, fileTemplate); write(buffer, clusters.size()); for (OStorageClusterConfiguration c : clusters) { if (c == null) { write(buffer, -1); continue; } write(buffer, c.getId()); write(buffer, c.getName()); write(buffer, c.getDataSegmentId()); if (c instanceof OStoragePaginatedClusterConfiguration) { write(buffer, "d"); final OStoragePaginatedClusterConfiguration paginatedClusterConfiguration = (OStoragePaginatedClusterConfiguration) c; write(buffer, paginatedClusterConfiguration.useWal); write(buffer, paginatedClusterConfiguration.recordOverflowGrowFactor); write(buffer, paginatedClusterConfiguration.recordGrowFactor); write(buffer, paginatedClusterConfiguration.compression); if (iNetworkVersion >= 31) write(buffer, paginatedClusterConfiguration.encryption); if (iNetworkVersion > 24) write(buffer, paginatedClusterConfiguration.conflictStrategy); if (iNetworkVersion > 25) write(buffer, paginatedClusterConfiguration.getStatus().name().toString()); } } if (iNetworkVersion <= 25) { // dataSegment array write(buffer, 0); // tx Segment File write(buffer, ""); write(buffer, ""); write(buffer, 0); // tx segment flags write(buffer, false); write(buffer, false); } synchronized (properties) { write(buffer, properties.size()); for (OStorageEntryConfiguration e : properties) entryToStream(buffer, e); } write(buffer, binaryFormatVersion); write(buffer, clusterSelection); write(buffer, getMinimumClusters()); if (iNetworkVersion > 24) { write(buffer, recordSerializer); write(buffer, recordSerializerVersion); // WRITE CONFIGURATION write(buffer, configuration.getContextSize()); for (String k : configuration.getContextKeys()) { final OGlobalConfiguration cfg = OGlobalConfiguration.findByKey(k); write(buffer, k); write(buffer, cfg.isHidden() ? null : configuration.getValueAsString(cfg)); } } write(buffer, indexEngines.size()); for (IndexEngineData engineData : indexEngines.values()) { write(buffer, engineData.name); write(buffer, engineData.algorithm); write(buffer, engineData.indexType == null ? "" : engineData.indexType); write(buffer, engineData.valueSerializerId); write(buffer, engineData.keySerializedId); write(buffer, engineData.isAutomatic); write(buffer, engineData.durableInNonTxMode); write(buffer, engineData.version); write(buffer, engineData.nullValuesSupport); write(buffer, engineData.keySize); if (engineData.keyTypes != null) { write(buffer, engineData.keyTypes.length); for (OType type : engineData.keyTypes) { write(buffer, type.name()); } } else { write(buffer, 0); } if (engineData.engineProperties == null) { write(buffer, 0); } else { write(buffer, engineData.engineProperties.size()); for (Map.Entry<String, String> property : engineData.engineProperties.entrySet()) { write(buffer, property.getKey()); write(buffer, property.getValue()); } } } // PLAIN: ALLOCATE ENOUGH SPACE TO REUSE IT EVERY TIME buffer.append("|"); return buffer.toString().getBytes(); } public void lock() throws IOException { } public void unlock() throws IOException { } public void create() throws IOException { storage.createRecord(CONFIG_RID, new byte[] { 0, 0, 0, 0 }, 0, OBlob.RECORD_TYPE, (byte) 0, null); } public void synch() throws IOException { } public void setSoftlyClosed(boolean softlyClosed) throws IOException { } public void delete() throws IOException { close(); } public void close() throws IOException { clear(); initConfiguration(); } public void dropCluster(final int iClusterId) { if (iClusterId < clusters.size()) { clusters.set(iClusterId, null); update(); } } public void addIndexEngine(String name, IndexEngineData engineData) { final IndexEngineData oldEngine = indexEngines.putIfAbsent(name, engineData); if (oldEngine != null) OLogManager.instance().warn(this, "Index engine with name '" + engineData.name + "' already contained in database configuration"); update(); } public void deleteIndexEngine(String name) { indexEngines.remove(name); update(); } public Set<String> indexEngines() { return Collections.unmodifiableSet(indexEngines.keySet()); } public IndexEngineData getIndexEngine(String name) { return indexEngines.get(name); } public void setClusterStatus(final int clusterId, final OStorageClusterConfiguration.STATUS iStatus) { final OStorageClusterConfiguration clusterCfg = clusters.get(clusterId); if (clusterCfg != null) clusterCfg.setStatus(iStatus); update(); } public TimeZone getTimeZone() { return timeZone; } public void setTimeZone(final TimeZone timeZone) { this.timeZone = timeZone; } public String getLocaleLanguage() { return localeLanguage; } public void setLocaleLanguage(final String iValue) { localeLanguage = iValue; localeInstance = null; } public String getLocaleCountry() { return localeCountry; } public void setLocaleCountry(final String iValue) { localeCountry = iValue; localeInstance = null; } public String getCharset() { return charset; } public void setCharset(String charset) { this.charset = charset; } public String getDateFormat() { return dateFormat; } public String getDateTimeFormat() { return dateTimeFormat; } public String getClusterSelection() { return clusterSelection; } public void setClusterSelection(final String clusterSelection) { this.clusterSelection = clusterSelection; } public int getMinimumClusters() { final int mc = getContextConfiguration().getValueAsInteger(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS); if (mc == 0) { autoInitClusters(); return (Integer) getContextConfiguration().getValue(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS); } return mc; } public void setMinimumClusters(final int minimumClusters) { getContextConfiguration().setValue(OGlobalConfiguration.CLASS_MINIMUM_CLUSTERS, minimumClusters); autoInitClusters(); } public String getRecordSerializer() { return recordSerializer; } public void setRecordSerializer(String recordSerializer) { this.recordSerializer = recordSerializer; } public int getRecordSerializerVersion() { return recordSerializerVersion; } public void setRecordSerializerVersion(int recordSerializerVersion) { this.recordSerializerVersion = recordSerializerVersion; } public boolean isStrictSql() { return strictSQL; } public boolean isTxRequiredForSQLGraphOperations() { return txRequiredForSQLGraphOperations; } public List<OStorageEntryConfiguration> getProperties() { return Collections.unmodifiableList(properties); } public void setProperty(final String iName, final String iValue) { if (OStatement.CUSTOM_STRICT_SQL.equalsIgnoreCase(iName)) // SET STRICT SQL VARIABLE strictSQL = "true".equalsIgnoreCase(iValue); if ("txRequiredForSQLGraphOperations".equalsIgnoreCase(iName)) // SET TX SQL GRAPH OPERATIONS txRequiredForSQLGraphOperations = "true".equalsIgnoreCase(iValue); if ("txRequiredForSQLGraphOperations".equalsIgnoreCase(iName)) // SET TX SQL GRAPH OPERATIONS txRequiredForSQLGraphOperations = "true".equalsIgnoreCase(iValue); if ("validation".equalsIgnoreCase(iName)) validation = "true".equalsIgnoreCase(iValue); synchronized (properties) { for (Iterator<OStorageEntryConfiguration> it = properties.iterator(); it.hasNext();) { final OStorageEntryConfiguration e = it.next(); if (e.name.equalsIgnoreCase(iName)) { // FOUND: OVERWRITE IT e.value = iValue; return; } } // NOT FOUND: CREATE IT properties.add(new OStorageEntryConfiguration(iName, iValue)); } } public String getProperty(final String iName) { synchronized (properties) { for (Iterator<OStorageEntryConfiguration> it = properties.iterator(); it.hasNext();) { final OStorageEntryConfiguration e = it.next(); if (e.name.equalsIgnoreCase(iName)) return e.value; } return null; } } public boolean existsProperty(final String iName) { synchronized (properties) { for (Iterator<OStorageEntryConfiguration> it = properties.iterator(); it.hasNext();) { final OStorageEntryConfiguration e = it.next(); if (e.name.equalsIgnoreCase(iName)) return true; } return false; } } public void removeProperty(final String iName) { synchronized (properties) { for (Iterator<OStorageEntryConfiguration> it = properties.iterator(); it.hasNext();) { final OStorageEntryConfiguration e = it.next(); if (e.name.equalsIgnoreCase(iName)) { it.remove(); break; } } } } public void clearProperties() { synchronized (properties) { properties.clear(); } } public boolean isValidationEnabled() { return validation; } public void setValidation(final boolean validation) { setProperty("validation", validation ? "true" : "false"); } protected void bindPropertiesToContext(final Map<String, Object> iProperties) { final String compressionMethod = iProperties != null ? (String) iProperties.get(OGlobalConfiguration.STORAGE_COMPRESSION_METHOD.getKey().toLowerCase()) : null; if (compressionMethod != null) // SAVE COMPRESSION METHOD IN CONFIGURATION getContextConfiguration().setValue(OGlobalConfiguration.STORAGE_COMPRESSION_METHOD, compressionMethod); final String encryptionMethod = iProperties != null ? (String) iProperties.get(OGlobalConfiguration.STORAGE_ENCRYPTION_METHOD.getKey().toLowerCase()) : null; if (encryptionMethod != null) // SAVE ENCRYPTION METHOD IN CONFIGURATION getContextConfiguration().setValue(OGlobalConfiguration.STORAGE_ENCRYPTION_METHOD, encryptionMethod); final String encryptionKey = iProperties != null ? (String) iProperties.get(OGlobalConfiguration.STORAGE_ENCRYPTION_KEY.getKey().toLowerCase()) : null; if (encryptionKey != null) // SAVE ENCRYPTION KEY IN CONFIGURATION getContextConfiguration().setValue(OGlobalConfiguration.STORAGE_ENCRYPTION_KEY, encryptionKey); } private int phySegmentFromStream(final String[] values, int index, final OStorageSegmentConfiguration iSegment) { iSegment.location = version > 2 ? read(values[index++]) : null; iSegment.maxSize = read(values[index++]); iSegment.fileType = read(values[index++]); iSegment.fileStartSize = read(values[index++]); iSegment.fileMaxSize = read(values[index++]); iSegment.fileIncrementSize = read(values[index++]); iSegment.defrag = read(values[index++]); final int size = Integer.parseInt(read(values[index++])); iSegment.infoFiles = new OStorageFileConfiguration[size]; String fileName; for (int i = 0; i < size; ++i) { fileName = read(values[index++]); if (!fileName.contains("$")) { // @COMPATIBILITY 0.9.25 int pos = fileName.indexOf("/databases"); if (pos > -1) { fileName = "${" + Orient.ORIENTDB_HOME + "}" + fileName.substring(pos); } } iSegment.infoFiles[i] = new OStorageFileConfiguration(iSegment, fileName, read(values[index++]), read(values[index++]), iSegment.fileIncrementSize); } return index; } private void phySegmentToStream(final StringBuilder iBuffer, final OStorageSegmentConfiguration iSegment) { write(iBuffer, iSegment.location); write(iBuffer, iSegment.maxSize); write(iBuffer, iSegment.fileType); write(iBuffer, iSegment.fileStartSize); write(iBuffer, iSegment.fileMaxSize); write(iBuffer, iSegment.fileIncrementSize); write(iBuffer, iSegment.defrag); write(iBuffer, iSegment.infoFiles.length); for (OStorageFileConfiguration f : iSegment.infoFiles) fileToStream(iBuffer, f); } private void fileToStream(final StringBuilder iBuffer, final OStorageFileConfiguration iFile) { write(iBuffer, iFile.path); write(iBuffer, iFile.type); write(iBuffer, iFile.maxSize); } private void entryToStream(final StringBuilder iBuffer, final OStorageEntryConfiguration iEntry) { write(iBuffer, iEntry.name); write(iBuffer, iEntry.value); } private String read(final String iValue) { if (iValue.equals(" ")) return null; return iValue; } private void write(final StringBuilder iBuffer, final Object iValue) { if (iBuffer.length() > 0) iBuffer.append('|'); iBuffer.append(iValue != null ? iValue.toString() : ' '); } public static final class IndexEngineData { private final String name; private final String algorithm; private final String indexType; private final Boolean durableInNonTxMode; private final int version; private final byte valueSerializerId; private final byte keySerializedId; private final boolean isAutomatic; private final OType[] keyTypes; private final boolean nullValuesSupport; private final int keySize; private final Map<String, String> engineProperties; public IndexEngineData(final String name, final String algorithm, String indexType, final Boolean durableInNonTxMode, final int version, final byte valueSerializerId, final byte keySerializedId, final boolean isAutomatic, final OType[] keyTypes, final boolean nullValuesSupport, final int keySize, final Map<String, String> engineProperties) { this.name = name; this.algorithm = algorithm; this.indexType = indexType; this.durableInNonTxMode = durableInNonTxMode; this.version = version; this.valueSerializerId = valueSerializerId; this.keySerializedId = keySerializedId; this.isAutomatic = isAutomatic; this.keyTypes = keyTypes; this.nullValuesSupport = nullValuesSupport; this.keySize = keySize; if (engineProperties == null) this.engineProperties = null; else this.engineProperties = new HashMap<String, String>(engineProperties); } public int getKeySize() { return keySize; } public String getName() { return name; } public String getAlgorithm() { return algorithm; } public Boolean getDurableInNonTxMode() { return durableInNonTxMode; } public int getVersion() { return version; } public byte getValueSerializerId() { return valueSerializerId; } public byte getKeySerializedId() { return keySerializedId; } public boolean isAutomatic() { return isAutomatic; } public OType[] getKeyTypes() { return keyTypes; } public boolean isNullValuesSupport() { return nullValuesSupport; } public Map<String, String> getEngineProperties() { if (engineProperties == null) return null; return Collections.unmodifiableMap(engineProperties); } public String getIndexType() { return indexType; } } }