Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.vxquery.runtime.functions.index.indexCentralizer; import java.io.DataOutput; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.apache.commons.io.FileUtils; import org.apache.hyracks.data.std.util.ArrayBackedValueStorage; import org.apache.vxquery.datamodel.builders.atomic.StringValueBuilder; import org.apache.vxquery.datamodel.builders.sequence.SequenceBuilder; import org.apache.vxquery.datamodel.values.ValueTag; /** * Class for maintaining the centralized index information file. * Index centralization procedure. * User can specify the collection directory in VXQuery.java, ncConfig.ioDevices = < index_directory > . * Then all the indexes will be created in that particular directory in sub-folders corresponding to collections. * There will be a single xml file, located in the directory specified in local.xml, which contains all information * about the existing indexes. * This class can be used to read, add, delete, modify the entries and write the file back to the disk. */ public class IndexCentralizerUtil { private final String FILE_NAME = "VXQuery-Index-Directory.xml"; private final List<String> collections = new ArrayList<>(); private final Logger LOGGER = Logger.getLogger("IndexCentralizerUtil"); private File XML_FILE; private String INDEX_LOCATION; private static ConcurrentHashMap<String, IndexLocator> indexCollectionMap = new ConcurrentHashMap<>(); public IndexCentralizerUtil(File index) { this.INDEX_LOCATION = index.getPath(); if (!index.exists()) { try { FileUtils.forceMkdir(index); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Could not create the index directory for path: " + INDEX_LOCATION + " " + e); } } XML_FILE = new File(index.getPath() + "/" + FILE_NAME); } /** * Get the index directory containing index of the given collection * * @param collection : Collection folder * @return Index folder. */ public String getIndexForCollection(String collection) { return indexCollectionMap.get(collection).getIndex(); } /** * Put the index location corresponding to given collection. * Index location is created by using the last 100 characters of collection. * * @param collection : Collection directory * @return index */ public String putIndexForCollection(String collection) { int length = collection.replaceAll("/", "").length(); String index = collection.replaceAll("/", ""); index = INDEX_LOCATION + "/" + (length > 100 ? index.substring(length - 100) : index); IndexLocator il = new IndexLocator(); il.setCollection(collection); il.setIndex(index); if (indexCollectionMap.get(collection) != null) { return index; } indexCollectionMap.put(collection, il); return index; } /** * Remove the entry for given collection directory. * * @param collection : Collection directory */ public void deleteEntryForCollection(String collection) { indexCollectionMap.remove(collection); } /** * Prints all collections which have an index created. * @param sb : The output is stored in a sequence * @throws IOException : If writing the dataOutput generates {@link IOException} */ public void getAllCollections(SequenceBuilder sb) throws IOException { for (String s : collections) { StringValueBuilder svb = new StringValueBuilder(); ArrayBackedValueStorage abvs = new ArrayBackedValueStorage(); DataOutput output = abvs.getDataOutput(); output.write(ValueTag.XS_STRING_TAG); svb.write(s, output); sb.addItem(abvs); } } /** * Read the collection, index directory file and populate the HashMap. */ public void readIndexDirectory() { if (this.XML_FILE.exists()) { try { JAXBContext jaxbContext = JAXBContext.newInstance(IndexDirectory.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); IndexDirectory indexDirectory = (IndexDirectory) jaxbUnmarshaller.unmarshal(this.XML_FILE); for (IndexLocator il : indexDirectory.getDirectory()) { indexCollectionMap.put(il.getCollection(), il); this.collections.add(il.getCollection()); } } catch (JAXBException e) { LOGGER.log(Level.SEVERE, "Could not read the XML file due to " + e); } } } /** * Write back the contents of the HashMap to the file. */ public void writeIndexDirectory() { IndexDirectory id = new IndexDirectory(); List<IndexLocator> indexLocators = new ArrayList<>(indexCollectionMap.values()); id.setDirectory(indexLocators); try { FileOutputStream fileOutputStream = new FileOutputStream(this.XML_FILE); JAXBContext context = JAXBContext.newInstance(IndexDirectory.class); Marshaller jaxbMarshaller = context.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(id, fileOutputStream); } catch (JAXBException | FileNotFoundException e) { LOGGER.log(Level.SEVERE, "Could not read the XML file due to " + e); } } }