/* * Copyright 2013 David Tinker * * 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. */ package io.qdb.server.queue; import io.qdb.server.Util; import io.qdb.server.model.Database; import io.qdb.server.model.Queue; import io.qdb.server.repo.Repository; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import java.io.File; import java.io.IOException; /** * Keeps track of where we can store queue data (one or more paths on the file system) and allocates storage * for queues. */ @Singleton public class QueueStorageManager { private final File[] queueDataDirs; private final Repository repository; @Inject public QueueStorageManager(@Named("dataDir") String dataDir, Repository repository) throws IOException { this.repository = repository; queueDataDirs = new File[]{new File(dataDir, "queues")}; for (File dir : queueDataDirs) Util.ensureDirectory(dir); } /** * If q already exists i.e. there is an existing directory for it then return that directory. Otherwise allocate * a new directory and return it. */ public File findDir(Queue q) throws IOException { Database db = repository.findDatabase(q.getDatabase()); if (db == null) { throw new IllegalStateException("database [" + q.getDatabase() + "] for queue [" + q.getId() + "] not found"); } String name = db.getQueueForQid(q.getId()); if (name == null) { throw new IllegalStateException("database [" + q.getDatabase() + "] does not have name for queue [" + q.getId() + "]"); } for (File dir : queueDataDirs) { File dbDir = new File(dir, q.getDatabase()); if (dbDir.isDirectory()) { File f = new File(dbDir, name); if (f.exists()) return f; } } return new File(Util.ensureDirectory(new File(allocateDataDir(q), q.getDatabase())), name); } private File allocateDataDir(Queue q) { if (queueDataDirs.length == 1) return queueDataDirs[0]; long maxUsableSpace = -1; File ans = null; for (File dir : queueDataDirs) { long usableSpace = dir.getUsableSpace(); if (usableSpace > maxUsableSpace) { ans = dir; maxUsableSpace = usableSpace; } } return ans; } }