class AOStorage extends StorageBase {

    public static final String SUFFIX_AO_FILE = ".db";
    public static final int SUFFIX_AO_FILE_LENGTH = SUFFIX_AO_FILE.length();

    AOStorage(Map<String, Object> config) {
        super(config);
        if (config.containsKey(StorageSetting.IN_MEMORY.name()))
            return;
        String storagePath = getStoragePath();
        DataUtils.checkNotNull(storagePath, "storage path");
        if (!FileUtils.exists(storagePath))
            FileUtils.createDirectories(storagePath);
        FilePath dir = FilePath.get(storagePath);
        for (FilePath fp : dir.newDirectoryStream()) {
            String mapFullName = fp.getName();
            if (mapFullName.startsWith(TEMP_NAME_PREFIX)) {
                fp.delete();
            }
        }
    }

    @Override
    protected InputStream getInputStream(String mapName, FilePath file) {
        return openBTreeMap(mapName).getInputStream(file);
    }

    @Override
    public String getStorageName() {
        return AOStorageEngine.NAME;
    }

    public boolean isReadOnly() {
        return config.containsKey(DbSetting.READ_ONLY.name());
    }

    @Override
    public <K, V> StorageMap<K, V> openMap(String name, StorageDataType keyType,
            StorageDataType valueType, Map<String, String> parameters) {
        String mapType = parameters == null ? null : parameters.get(StorageSetting.MAP_TYPE.name());
        return openMap(name, mapType, keyType, valueType, parameters);
    }

    public <K, V> StorageMap<K, V> openMap(String name, String mapType, StorageDataType keyType,
            StorageDataType valueType, Map<String, String> parameters) {
        if (mapType == null || mapType.equalsIgnoreCase("BTreeMap")) {
            return openBTreeMap(name, keyType, valueType, parameters);
        } else {
            throw DataUtils.newIllegalArgumentException("Unknow map type: {0}", mapType);
        }
    }

    public <K, V> BTreeMap<K, V> openBTreeMap(String name) {
        return openBTreeMap(name, null, null, null);
    }

    @SuppressWarnings("unchecked")
    public <K, V> BTreeMap<K, V> openBTreeMap(String name, StorageDataType keyType,
            StorageDataType valueType, Map<String, String> parameters) {<FILL_FUNCTION_BODY>}
}

        StorageMap<?, ?> map = maps.get(name);
        if (map == null) {
            synchronized (this) {
                map = maps.get(name);
                if (map == null) {
                    CaseInsensitiveMap<Object> c = new CaseInsensitiveMap<>(config);
                    if (parameters != null)
                        c.putAll(parameters);
                    map = new BTreeMap<>(name, keyType, valueType, c, this);
                    for (StorageEventListener listener : listeners.values())
                        listener.afterStorageMapOpen(map);
                    // 执行完afterStorageMapOpen后再put，确保其他线程拿到的是一个就绪后的map
                    maps.put(name, map);
                }
            }
        }
        return (BTreeMap<K, V>) map;
    
<methods>public void <init>(Map<java.lang.String,java.lang.Object>) ,public void backupTo(java.lang.String, java.lang.Long) ,public void backupTo(java.lang.String, java.util.zip.ZipOutputStream, java.lang.Long) ,public void close() ,public void closeImmediately() ,public void closeMap(java.lang.String) ,public static java.util.zip.ZipOutputStream createZipOutputStream(java.lang.String) throws java.io.IOException,public void drop() ,public long getDiskSpaceUsed() ,public StorageMap<?,?> getMap(java.lang.String) ,public Set<java.lang.String> getMapNames() ,public long getMemorySpaceUsed() ,public com.lealone.db.scheduler.SchedulerFactory getSchedulerFactory() ,public java.lang.String getStoragePath() ,public boolean hasMap(java.lang.String) ,public boolean isClosed() ,public boolean isInMemory() ,public java.lang.String nextTemporaryMapName() ,public void registerEventListener(com.lealone.storage.StorageEventListener) ,public void save() ,public void setSchedulerFactory(com.lealone.db.scheduler.SchedulerFactory) ,public void unregisterEventListener(com.lealone.storage.StorageEventListener) <variables>protected static final java.lang.String TEMP_NAME_PREFIX,protected boolean closed,protected final non-sealed Map<java.lang.String,java.lang.Object> config,protected final Map<com.lealone.storage.StorageEventListener,com.lealone.storage.StorageEventListener> listeners,protected final Map<java.lang.String,StorageMap<?,?>> maps,protected com.lealone.db.scheduler.SchedulerFactory schedulerFactory