com.qwazr.database.TableManager.java Source code

Java tutorial

Introduction

Here is the source code for com.qwazr.database.TableManager.java

Source

/**
 * Copyright 2015-2016 Emmanuel Keller / QWAZR
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 com.qwazr.database;

import com.qwazr.database.model.ColumnDefinition;
import com.qwazr.database.model.TableRequest;
import com.qwazr.database.model.TableRequestResult;
import com.qwazr.database.store.*;
import com.qwazr.utils.LockUtils;
import com.qwazr.utils.server.ServerException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.roaringbitmap.RoaringBitmap;

import javax.ws.rs.core.Response;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;

public class TableManager {

    public final static String SERVICE_NAME_TABLE = "table";

    private final LockUtils.ReadWriteLock rwl = new LockUtils.ReadWriteLock();

    static volatile TableManager INSTANCE = null;

    public File directory;

    public final ExecutorService executor;

    public static Class<? extends TableServiceInterface> load(ExecutorService executor, File dataDirectory)
            throws IOException {
        if (INSTANCE != null)
            throw new IOException("Already loaded");
        File tableDir = new File(dataDirectory, SERVICE_NAME_TABLE);
        if (!tableDir.exists())
            tableDir.mkdir();
        try {
            INSTANCE = new TableManager(executor, tableDir);
            return TableServiceImpl.class;
        } catch (ServerException e) {
            throw new RuntimeException(e);
        }
    }

    public static TableManager getInstance() {
        if (INSTANCE == null)
            throw new RuntimeException("The table service is not enabled");
        return INSTANCE;
    }

    private TableManager(ExecutorService executor, File directory) throws ServerException, IOException {
        this.directory = directory;
        this.executor = executor;
    }

    private Table getTable(String tableName) throws IOException, ServerException, DatabaseException {
        File dbDirectory = new File(directory, tableName);
        if (!dbDirectory.exists())
            throw new ServerException(Response.Status.NOT_FOUND, "Table not found: " + tableName);
        return Tables.getInstance(dbDirectory, true);
    }

    public void createTable(String tableName) throws ServerException, IOException, DatabaseException {
        rwl.w.lock();
        try {
            File dbDirectory = new File(directory, tableName);
            if (dbDirectory.exists())
                throw new ServerException(Response.Status.CONFLICT, "The table already exists: " + tableName);
            dbDirectory.mkdir();
            if (!dbDirectory.exists())
                throw new ServerException(Response.Status.INTERNAL_SERVER_ERROR,
                        "The directory cannot be created: " + dbDirectory.getAbsolutePath());
            Tables.getInstance(dbDirectory, true);
        } finally {
            rwl.w.unlock();
        }
    }

    public Set<String> getNameSet() {
        rwl.r.lock();
        try {
            LinkedHashSet<String> names = new LinkedHashSet<String>();
            for (File file : directory.listFiles((FileFilter) FileFilterUtils.directoryFileFilter()))
                if (!file.isHidden())
                    names.add(file.getName());
            return names;
        } finally {
            rwl.r.unlock();
        }
    }

    public Map<String, ColumnDefinition> getColumns(String tableName)
            throws ServerException, DatabaseException, IOException {
        rwl.r.lock();
        try {
            return getTable(tableName).getColumns();
        } finally {
            rwl.r.unlock();
        }
    }

    public void addColumn(String tableName, String columnName, ColumnDefinition columnDefinition)
            throws IOException, ServerException {
        rwl.w.lock();
        try {
            Table table = getTable(tableName);
            table.addColumn(columnName, columnDefinition);
        } catch (Exception e) {
            throw ServerException.getServerException(e);
        } finally {
            rwl.w.unlock();
        }
    }

    public void removeColumn(String tableName, String columnName) throws IOException, ServerException {
        rwl.w.lock();
        try {
            Table table = getTable(tableName);
            table.removeColumn(columnName);
        } catch (Exception e) {
            throw ServerException.getServerException(e);
        } finally {
            rwl.w.unlock();
        }
    }

    public void deleteTable(String tableName) throws ServerException, IOException, DatabaseException {
        rwl.w.lock();
        try {
            File dbDirectory = new File(directory, tableName);
            Table table = Tables.getInstance(dbDirectory, false);
            if (table != null)
                table.close();
            if (!dbDirectory.exists())
                throw new ServerException(Response.Status.NOT_FOUND, "Table not found: " + tableName);
            FileUtils.deleteDirectory(dbDirectory);
        } finally {
            rwl.w.unlock();
        }
    }

    public void upsertRow(String tableName, String row_id, Map<String, Object> nodeMap)
            throws IOException, ServerException, DatabaseException {
        rwl.r.lock();
        try {
            Table table = getTable(tableName);
            table.upsertRow(row_id, nodeMap);
        } finally {
            rwl.r.unlock();
        }
    }

    public int upsertRows(String tableName, List<Map<String, Object>> rows)
            throws IOException, ServerException, DatabaseException {
        rwl.r.lock();
        try {
            Table table = getTable(tableName);
            return table.upsertRows(rows);
        } finally {
            rwl.r.unlock();
        }
    }

    public LinkedHashMap<String, Object> getRow(String tableName, String key, Set<String> columns)
            throws IOException, ServerException, DatabaseException {
        rwl.r.lock();
        try {
            Table table = getTable(tableName);
            LinkedHashMap<String, Object> row = table.getRow(key, columns);
            if (row == null)
                throw new ServerException(Response.Status.NOT_FOUND, "Row not found: " + key);
            return row;
        } finally {
            rwl.r.unlock();
        }
    }

    public boolean deleteRow(String tableName, String key) throws IOException, ServerException, DatabaseException {
        rwl.r.lock();
        try {
            Table table = getTable(tableName);
            return table.deleteRow(key);
        } finally {
            rwl.r.unlock();
        }
    }

    public TableRequestResult query(String tableName, TableRequest request)
            throws ServerException, DatabaseException, IOException {
        rwl.r.lock();
        try {

            long start = request.start == null ? 0 : request.start;
            long rows = request.rows == null ? Long.MAX_VALUE : request.rows;

            Table table = getTable(tableName);

            if (request.query == null)
                throw new ServerException(Response.Status.NOT_ACCEPTABLE, "The query part is missing");

            Map<String, Map<String, CollectorInterface.LongCounter>> counters = null;
            if (request.counters != null && !request.counters.isEmpty()) {
                counters = new LinkedHashMap<String, Map<String, CollectorInterface.LongCounter>>();
                for (String col : request.counters) {
                    Map<String, CollectorInterface.LongCounter> termCount = new HashMap<String, CollectorInterface.LongCounter>();
                    counters.put(col, termCount);
                }
            }

            Query query = Query.prepare(request.query, null);

            RoaringBitmap docBitset = table.query(query, counters).finalBitmap;

            if (docBitset == null || docBitset.isEmpty())
                return new TableRequestResult(null);

            long count = docBitset.getCardinality();
            TableRequestResult result = new TableRequestResult(count);

            table.getRows(docBitset, request.columns, start, rows, result.rows);

            if (counters != null) {
                for (Map.Entry<String, Map<String, CollectorInterface.LongCounter>> countersEntry : counters
                        .entrySet()) {
                    LinkedHashMap<String, Long> counter = new LinkedHashMap<String, Long>();
                    for (Map.Entry<String, CollectorInterface.LongCounter> counterEntry : countersEntry.getValue()
                            .entrySet())
                        counter.put(counterEntry.getKey(), counterEntry.getValue().count);
                    result.counters.put(countersEntry.getKey(), counter);
                }
            }

            return result;
        } finally {
            rwl.r.unlock();
        }

    }

}