/******************************************************************************* * Copyright (c) 2014 EURA NOVA. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v2.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Aldemar Reynaga - initial API and implementation * Salim Jouili - initial API and implementation ******************************************************************************/ package com.steffi.storage; import java.io.BufferedWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.infinispan.Cache; import org.infinispan.distexec.DefaultExecutorService; import org.infinispan.distexec.DistributedExecutorService; import com.steffi.common.BigTextFile; import com.steffi.common.ImgLogger; import com.steffi.common.ImgLogger.LogLevel; import com.steffi.loader.LoadVertexInfo; import com.steffi.loader.ResponseProcessor; import com.steffi.model.Cell; import com.steffi.model.EdgeType; import com.steffi.model.SteffiVertex; import com.steffi.networking.ClientThread; import com.steffi.networking.messages.LoadMessage; import com.steffi.networking.messages.Message; import com.steffi.networking.messages.MessageType; import com.steffi.networking.messages.WriteFileReqMsg; import com.steffi.networking.messages.LoadMessage.LoadFileType; import com.tinkerpop.blueprints.TransactionalGraph.Conclusion; import com.tinkerpop.blueprints.impls.steffi.SteffiGraphDBGraph; import com.tinkerpop.blueprints.impls.steffi.SteffiGraphDBVertex; /** * @author Aldemar Reynaga * Functions to read and write text files using a format called IMGP which allows * faster batch loading. (Deprecated) */ public class SteffipFileTools implements ResponseProcessor { public static void loadVertexBlock(SteffiGraphDBGraph graph ,List<LoadVertexInfo> loadVertices) { SteffiVertex vertex; graph.startTransaction(); for (LoadVertexInfo loadVertex : loadVertices) { vertex = ((SteffiGraphDBVertex)graph.addVertex(loadVertex.getVertexId())).getRawVertex(); for (long outEdgeDest : loadVertex.getOutEdges()) vertex.addPartialEdge(outEdgeDest, EdgeType.OUT, ""); for (long inEdgeDest : loadVertex.getInEdges()) vertex.addPartialEdge(inEdgeDest, EdgeType.IN, ""); for (long undEdgeDest : loadVertex.getUndirectedEdges()) vertex.addPartialEdge(undEdgeDest, EdgeType.UNDIRECTED, ""); } graph.stopTransaction(Conclusion.SUCCESS); } private Map<String, String> clusterAddresses; private Map<String, ClientThread> clientThreads; private String id; private Integer blocksSent; private Integer pendingWriteRequests; private boolean loadingInProcess; private boolean writingInProcess; private boolean fileReadingDone; private Object lock; private boolean update1HNInProcess; private int pending1HNRequests; public SteffipFileTools(String id) { this.id = id; clusterAddresses = StorageTools.getAddressesIps(); initClientThreads(); } private void initClientThreads() { this.clientThreads = new HashMap<String, ClientThread>(); ClientThread clientThread = null; for (Entry<String, String> entry : clusterAddresses.entrySet()) { clientThread = new ClientThread(entry.getValue(), entry.getValue(), "loader_" + this.id, this); clientThreads.put(entry.getKey(), clientThread); new Thread(clientThread).start(); } } private void sendLoadBlock(Map<String, List<LoadVertexInfo>> addressVertices) { for (Entry<String, List<LoadVertexInfo>> entry : addressVertices.entrySet()) { LoadMessage loadMessage = new LoadMessage(); loadMessage.setVerticesInfo(entry.getValue()); loadMessage.setLoadFileType(LoadFileType.IMGP_FILE); clientThreads.get(entry.getKey()).addMsgToQueue(loadMessage); updateBlockCounter(1); } } private synchronized void updateBlockCounter(int difference) { blocksSent += difference; } private synchronized void verifyLoadComplete() { if (blocksSent == 0 && fileReadingDone) { synchronized (lock) { loadingInProcess = false; lock.notifyAll(); } } } public void registerLoadReponse() { updateBlockCounter(-1); verifyLoadComplete(); if (fileReadingDone) if (blocksSent % 20 == 0) System.out.println("Pending load blocks: " + blocksSent + "..."); } public void closeClientThreads() { if (clientThreads != null) for (ClientThread lt : clientThreads.values()) lt.stop(); } public static void updateLocal1HopNeighbors() throws InterruptedException, ExecutionException { DistributedExecutorService des = new DefaultExecutorService(CacheContainer.getCellCache()); Local2HopNeighborProcessor processor = new Local2HopNeighborProcessor(); List<Future<Integer>> results = des.submitEverywhere(processor); for (Future<Integer> future : results) { if (future.get() == 0) throw new RuntimeException("Error updating the local 1-Hop neighbors"); } } public void updateLocal1HopNeighborsV2() throws Exception { Message message = new Message(MessageType.UPD_2HOP_NEIGHBORS_REQ); update1HNInProcess = true; for (ClientThread ct : clientThreads.values()) ct.addMsgToQueue(message); pending1HNRequests = clientThreads.size(); lock = new String("UPDATE_2HN"); synchronized (lock) { while (update1HNInProcess) { lock.wait(); } } } private void addLoadVertexInfo(Map<String, List<LoadVertexInfo>> addressVertices, LoadVertexInfo loadVertexInfo) { String cellAddress = StorageTools.getCellAddress(loadVertexInfo.getVertexId()); List<LoadVertexInfo> vertices = addressVertices.get(cellAddress); if (vertices == null) { vertices = new ArrayList<LoadVertexInfo>(); addressVertices.put(cellAddress, vertices); } vertices.add(loadVertexInfo); } public void readFromFile(SteffiGraphDBGraph graph, String fileName) throws Exception { BigTextFile file = null; StringTokenizer tokenizer = null; int inEdgesCounter, outEdgesCounter, undEdgesCounter; Map<String, List<LoadVertexInfo>> addressVertices = new HashMap<String, List<LoadVertexInfo>>(); LoadVertexInfo loadVertexInfo = null; long counter=0; Date startDate, endDate; try { startDate = new Date(); file = new BigTextFile(fileName); loadingInProcess = true; fileReadingDone = false; lock = new String("LOAD"); blocksSent = 0 ; ImgLogger.log(LogLevel.INFO, "Starting loading of file " + fileName); System.out.print("Loading\n["); for (String line : file) { if (!line.trim().equals("")) { tokenizer = new StringTokenizer(line); loadVertexInfo = new LoadVertexInfo(Long.parseLong(tokenizer.nextToken())); inEdgesCounter = Integer.parseInt(tokenizer.nextToken()); for (int i=0; i<inEdgesCounter; i++) loadVertexInfo.addInEdge(Long.parseLong(tokenizer.nextToken())); outEdgesCounter = Integer.parseInt(tokenizer.nextToken()); for (int i=0; i<outEdgesCounter; i++) loadVertexInfo.addOutEdge(Long.parseLong(tokenizer.nextToken())); try { undEdgesCounter = Integer.parseInt(tokenizer.nextToken()); for (int i=0; i<undEdgesCounter; i++) loadVertexInfo.addUndirectedEdge(Long.parseLong(tokenizer.nextToken())); } catch (NoSuchElementException nse) { } addLoadVertexInfo(addressVertices, loadVertexInfo); counter++; if (counter%500==0) { System.out.print("."); System.out.flush(); sendLoadBlock(addressVertices); addressVertices.clear(); } } } fileReadingDone = true; if (!addressVertices.isEmpty()) { sendLoadBlock(addressVertices); } System.out.println("]"); synchronized (lock) { while (loadingInProcess) { lock.wait(); } } verifyLoadComplete(); Date subStartDate = new Date(); ImgLogger.log(LogLevel.INFO, "Calculating local 2-Hop neighbors"); updateLocal1HopNeighborsV2(); Date subEndDate = new Date(); ImgLogger.log(LogLevel.INFO, "2 Hop neighbors processed in " + (subEndDate.getTime() - subStartDate.getTime()) + " ms"); endDate = new Date(); ImgLogger.log(LogLevel.INFO, "File succesfully loaded in " + (endDate.getTime() - startDate.getTime()) + "ms. "+ counter + " vertices have been processed"); } finally { if (file != null) file.Close(); } } @Override public void processResponse(Message message) { if (message.getType().equals(MessageType.LOAD_REP)) { String response[] = message.getBody().split("::"); if (response[0].equals("OK")) registerLoadReponse(); else throw new RuntimeException("Error processing a load block, response: " + message.getBody()); } else if (message.getType().equals(MessageType.WRITE_TO_FILE_REP)) { if (message.getBody().equals("OK")) registerWriteResponse(); else throw new RuntimeException("Error processing a write file request"); } else if (message.getType().equals(MessageType.UPD_2HOP_NEIGHBORS_REP)) { if (message.getBody().equals("OK")) registerUpd1HNResponse(); else throw new RuntimeException("Error processing an update request for local 2-hop neighbors"); } } private synchronized void registerUpd1HNResponse() { pending1HNRequests--; System.out.println("Pending 2-hop neighbors requests: " + pending1HNRequests); if (pending1HNRequests == 0) { synchronized (lock) { update1HNInProcess = false; lock.notifyAll(); } } } private synchronized void registerWriteResponse() { pendingWriteRequests--; System.out.println("Pending write responses: " + pendingWriteRequests); if (pendingWriteRequests == 0) { synchronized (lock) { writingInProcess = false; lock.notifyAll(); } } } public void writeToFile(String fileNamePrefix, String directory) throws Exception { WriteFileReqMsg message = new WriteFileReqMsg(); message.setDirectory(directory); message.setFileNamePrefix(fileNamePrefix); writingInProcess = true; for (ClientThread ct : clientThreads.values()) ct.addMsgToQueue(message); pendingWriteRequests = clientThreads.size(); lock = new String("WRITE"); synchronized (lock) { while (writingInProcess) { lock.wait(); } } System.out.println("The files were written in the directory " + directory + " in each node with the prefix " + fileNamePrefix); } public static Message processWriteRequest(WriteFileReqMsg message) { Cache<Long, Cell> cache = CacheContainer.getCellCache(); BufferedWriter bufWriter = null; Message response = new Message(MessageType.WRITE_TO_FILE_REP); String fileName = message.getDirectory() + message.getFileNamePrefix() + "_" + cache.getCacheManager().getAddress().toString(); try { FileUtilities.writeToFile(fileName); response.setBody("OK"); System.out.println("$$$$$$$$Data write to " + fileName); } catch (Exception ex) { ex.printStackTrace(); response.setBody("ERROR: " + ex.getMessage()); } finally { if (bufWriter!=null){try{bufWriter.close();}catch(IOException ioe){}} } return response; } }