Search in sources :

Example 6 with LogicalDataWrapped

use of nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped in project lobcder by skoulouzis.

the class WorkerServlet method processRequest.

/**
 * Process the actual request.
 *
 * @param request The request to be processed.
 * @param response The response to be created.
 * @param content Whether the request body should be written (GET) or not
 * (HEAD).
 * @throws IOException If something fails at I/O level.
 */
private void processRequest(HttpServletRequest request, HttpServletResponse response, boolean content) throws IOException, InterruptedException, URISyntaxException, VlException, JAXBException {
    long startTime = System.currentTimeMillis();
    // Get requested file by path info.
    String requestedFile = request.getPathInfo();
    // Check if file is actually supplied to the request URL.
    PDRI pdri = null;
    if (requestedFile == null || requestedFile.split("/").length < 2) {
        // Do your thing if the file is not supplied to the request URL.
        // Throw an exception, or send 404, or show default/warning page, or just ignore it.
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    Path pathAndToken = Path.path(requestedFile);
    // token = pathAndToken.getName();
    fileUID = pathAndToken.getParent().toString().replaceAll("/", "");
    // Logger.getLogger(WorkerServlet.class.getName()).log(Level.FINE, "token: {0} fileUID: {1}", new Object[]{token, fileUID});
    pdri = cat.getPDRI(fileUID);
    fileLogicalName = cat.getLogicalDataWrapped(fileUID).getLogicalData().getName();
    // Check if file actually exists in filesystem.
    if (pdri == null) {
        // Do your thing if the file appears to be non-existing.
        // Throw an exception, or send 404, or show default/warning page, or just ignore it.
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // Prepare some variables. The ETag is an unique identifier of the file.
    long length = pdri.getLength();
    LogicalDataWrapped ldw = Catalogue.logicalDataCache.get(fileUID);
    long lastModified;
    if (ldw != null) {
        LogicalData ld = ldw.getLogicalData();
        lastModified = ld.getModifiedDate();
    } else {
        lastModified = System.currentTimeMillis();
    }
    String eTag = fileLogicalName + "_" + length + "_" + lastModified;
    long expires = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;
    // Validate request headers for caching ---------------------------------------------------
    // If-None-Match header should contain "*" or ETag. If so, then return 304.
    String ifNoneMatch = request.getHeader("If-None-Match");
    if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        // Required in 304.
        response.setHeader("ETag", eTag);
        // Postpone cache with 1 week.
        response.setDateHeader("Expires", expires);
        return;
    }
    // If-Modified-Since header should be greater than LastModified. If so, then return 304.
    // This header is ignored if any If-None-Match header is specified.
    long ifModifiedSince = request.getDateHeader("If-Modified-Since");
    if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        // Required in 304.
        response.setHeader("ETag", eTag);
        // Postpone cache with 1 week.
        response.setDateHeader("Expires", expires);
        return;
    }
    // Validate request headers for resume ----------------------------------------------------
    // If-Match header should contain "*" or ETag. If not, then return 412.
    String ifMatch = request.getHeader("If-Match");
    if (ifMatch != null && !matches(ifMatch, eTag)) {
        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
        return;
    }
    // If-Unmodified-Since header should be greater than LastModified. If not, then return 412.
    long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
    if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) {
        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
        return;
    }
    // Validate and process range -------------------------------------------------------------
    // Prepare some variables. The full Range represents the complete file.
    Range full = new Range(0, length - 1, length);
    List<Range> ranges = new ArrayList<>();
    // Validate and process Range and If-Range headers.
    String range = request.getHeader("Range");
    if (range != null) {
        // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
        if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
            // Required in 416.
            response.setHeader("Content-Range", "bytes */" + length);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return;
        }
        // If-Range header should either match ETag or be greater then LastModified. If not,
        // then return full file.
        String ifRange = request.getHeader("If-Range");
        if (ifRange != null && !ifRange.equals(eTag)) {
            try {
                // Throws IAE if invalid.
                long ifRangeTime = request.getDateHeader("If-Range");
                if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
                    ranges.add(full);
                }
            } catch (IllegalArgumentException ignore) {
                ranges.add(full);
            }
        }
        // If any valid If-Range header, then process each part of byte range.
        if (ranges.isEmpty()) {
            for (String part : range.substring(6).split(",")) {
                // Assuming a file with length of 100, the following examples returns bytes at:
                // 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
                long start = sublong(part, 0, part.indexOf("-"));
                long end = sublong(part, part.indexOf("-") + 1, part.length());
                if (start == -1) {
                    start = length - end;
                    end = length - 1;
                } else if (end == -1 || end > length - 1) {
                    end = length - 1;
                }
                // Check if Range is syntactically valid. If not, then return 416.
                if (start > end) {
                    // Required in 416.
                    response.setHeader("Content-Range", "bytes */" + length);
                    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return;
                }
                // Add range.
                ranges.add(new Range(start, end, length));
            }
        }
    }
    // Prepare and initialize response --------------------------------------------------------
    // Get content type by file name and set default GZIP support and content disposition.
    String contentType = getServletContext().getMimeType(fileLogicalName);
    ldw = Catalogue.logicalDataCache.get(fileUID);
    if (contentType == null && ldw != null) {
        contentType = ldw.getLogicalData().getContentTypesAsString();
    } else {
        contentType = "application/octet-stream";
    }
    boolean acceptsGzip = false;
    String disposition = "inline";
    // To add new content types, add new mime-mapping entry in web.xml.
    if (contentType == null) {
        contentType = "application/octet-stream";
    }
    // the browser and expand content type with the one and right character encoding.
    if (contentType.startsWith("text")) {
        String acceptEncoding = request.getHeader("Accept-Encoding");
        acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");
        contentType += ";charset=UTF-8";
    } else // the browser, then set to inline, else attachment which will pop a 'save as' dialogue.
    if (!contentType.startsWith("image")) {
        String accept = request.getHeader("Accept");
        disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment";
    }
    // Initialize response.
    response.reset();
    if (setResponseBufferSize) {
        response.setBufferSize(bufferSize);
    }
    response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileLogicalName + "\"");
    response.setHeader("Accept-Ranges", "bytes");
    response.setHeader("ETag", eTag);
    response.setDateHeader("Last-Modified", lastModified);
    response.setDateHeader("Expires", expires);
    ldw = Catalogue.logicalDataCache.get(fileUID);
    if (ldw != null) {
        response.setContentLength(safeLongToInt(ldw.getLogicalData().getLength()));
    }
    // Send requested file (part(s)) to client ------------------------------------------------
    // Prepare streams.
    // RandomAccessFile input = null;
    OutputStream output = null;
    try {
        // Open streams.
        // input = new RandomAccessFile(file, "r");
        // input = pdri.getData()
        output = response.getOutputStream();
        if (ranges.isEmpty() || ranges.get(0) == full) {
            // Return full file.
            Range r = full;
            response.setContentType(contentType);
            response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
            if (content) {
                if (acceptsGzip) {
                    // The browser accepts GZIP, so GZIP the content.
                    response.setHeader("Content-Encoding", "gzip");
                    output = new GZIPOutputStream(output, bufferSize);
                } else {
                    // Content length is not directly predictable in case of GZIP.
                    // So only add it if there is no means of GZIP, else browser will hang.
                    response.setHeader("Content-Length", String.valueOf(r.length));
                }
                // Copy full range.
                copy(pdri, output, r.start, r.length, request);
            }
        } else if (ranges.size() == 1) {
            // Return single part of file.
            Range r = ranges.get(0);
            response.setContentType(contentType);
            response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
            response.setHeader("Content-Length", String.valueOf(r.length));
            // 206.
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            if (content) {
                // Copy single part range.
                copy(pdri, output, r.start, r.length, request);
            }
        } else {
            // Return multiple parts of file.
            response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
            // 206.
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            if (content) {
                // Cast back to ServletOutputStream to get the easy println methods.
                ServletOutputStream sos = (ServletOutputStream) output;
                // Copy multi part range.
                for (Range r : ranges) {
                    // Add multipart boundary and header fields for every range.
                    sos.println();
                    sos.println("--" + MULTIPART_BOUNDARY);
                    sos.println("Content-Type: " + contentType);
                    sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);
                    // Copy single part range of multi part range.
                    copy(pdri, output, r.start, r.length, request);
                }
                // End with multipart boundary.
                sos.println();
                sos.println("--" + MULTIPART_BOUNDARY + "--");
            }
        }
    } finally {
        // Gently close streams.
        close(output);
        if (in != null) {
            in.close();
        }
        long elapsed = System.currentTimeMillis() - startTime;
        if (elapsed <= 0) {
            elapsed = 1;
        }
        LogicalDataWrapped lwd = Catalogue.logicalDataCache.get(fileUID);
        if (lwd != null) {
            double speed = ((lwd.getLogicalData().getLength() * 8.0) * 1000.0) / (elapsed * 1000.0);
            Double oldSpeed = Catalogue.weightPDRIMap.get(pdri.getHost());
            if (oldSpeed == null) {
                oldSpeed = speed;
            }
            Integer numOfGets = numOfGetsMap.get(pdri.getHost());
            if (numOfGets == null) {
                numOfGets = 1;
            }
            double averagre = (speed + oldSpeed) / (double) numOfGets;
            numOfGetsMap.put(pdri.getHost(), numOfGets++);
            Catalogue.weightPDRIMap.put(pdri.getHost(), averagre);
            Stats stats = new Stats();
            stats.setSource(request.getLocalAddr());
            stats.setDestination(request.getRemoteAddr());
            stats.setSpeed(speed);
            stats.setSize(Catalogue.logicalDataCache.get(fileUID).getLogicalData().getLength());
            cat.setSpeed(stats);
            String speedMsg = "Source: " + request.getLocalAddr() + " Destination: " + request.getRemoteAddr() + " Tx_Speed: " + speed + " Kbites/sec Tx_Size: " + Catalogue.logicalDataCache.get(fileUID).getLogicalData().getLength() + " bytes";
            Logger.getLogger(WorkerServlet.class.getName()).log(Level.INFO, speedMsg);
            String averageSpeedMsg = "Average speed: Source: " + pdri.getHost() + " Destination: " + request.getLocalAddr() + " Rx_Speed: " + averagre + " Kbites/sec Rx_Size: " + Catalogue.logicalDataCache.get(fileUID).getLogicalData().getLength() + " bytes";
            if (Util.sendStats()) {
                stats.setSource(request.getLocalAddr());
                stats.setDestination(request.getRemoteAddr());
                stats.setSpeed(speed);
                stats.setSize(Catalogue.logicalDataCache.get(fileUID).getLogicalData().getLength());
                cat.setSpeed(stats);
            }
            Logger.getLogger(WorkerServlet.class.getName()).log(Level.INFO, averageSpeedMsg);
        }
    }
}
Also used : Path(io.milton.common.Path) ServletOutputStream(javax.servlet.ServletOutputStream) GZIPOutputStream(java.util.zip.GZIPOutputStream) ServletOutputStream(javax.servlet.ServletOutputStream) TeeOutputStream(org.apache.commons.io.output.TeeOutputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) ArrayList(java.util.ArrayList) LogicalDataWrapped(nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped) PDRI(nl.uva.cs.lobcder.resources.PDRI) LogicalData(nl.uva.cs.lobcder.resources.LogicalData) GZIPOutputStream(java.util.zip.GZIPOutputStream) Stats(nl.uva.cs.lobcder.rest.wrappers.Stats)

Example 7 with LogicalDataWrapped

use of nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped in project lobcder by skoulouzis.

the class Items method getXml.

/**
 * Gets the resource's properties (length, owner, permitions etc.)
 *
 * @return the resource's properties
 * @throws Exception
 */
@Path("query/")
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<LogicalDataWrapped> getXml() throws Exception {
    try (Connection cn = getCatalogue().getConnection()) {
        MyPrincipal mp = (MyPrincipal) request.getAttribute("myprincipal");
        List<LogicalDataWrapped> res = queryLogicalData(mp, cn);
        return res;
    } catch (SQLException ex) {
        Logger.getLogger(Items.class.getName()).log(Level.SEVERE, null, ex);
        throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    }
}
Also used : MyPrincipal(nl.uva.cs.lobcder.auth.MyPrincipal) WebApplicationException(javax.ws.rs.WebApplicationException) SQLException(java.sql.SQLException) Connection(java.sql.Connection) LogicalDataWrapped(nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET)

Example 8 with LogicalDataWrapped

use of nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped in project lobcder by skoulouzis.

the class Catalogue method getPDRI.

public PDRI getPDRI(String fileUID) throws InterruptedException, IOException, URISyntaxException {
    LogicalDataWrapped logicalData = getLogicalDataWrapped(fileUID);
    // new PDRIDescr();
    PDRIDescr pdriDesc = null;
    pdriDesc = selectBestPDRI(logicalData.getPdriList());
    Logger.getLogger(Catalogue.class.getName()).log(Level.FINE, "Selected pdri: {0}", pdriDesc.getResourceUrl());
    return new VPDRI(pdriDesc.getName(), pdriDesc.getId(), pdriDesc.getResourceUrl(), pdriDesc.getUsername(), pdriDesc.getPassword(), pdriDesc.getEncrypt(), pdriDesc.getKey(), false);
}
Also used : VPDRI(nl.uva.cs.lobcder.resources.VPDRI) PDRIDescr(nl.uva.cs.lobcder.resources.PDRIDescr) LogicalDataWrapped(nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped)

Aggregations

LogicalDataWrapped (nl.uva.cs.lobcder.rest.wrappers.LogicalDataWrapped)8 LogicalData (nl.uva.cs.lobcder.resources.LogicalData)4 PDRIDescr (nl.uva.cs.lobcder.resources.PDRIDescr)4 ArrayList (java.util.ArrayList)3 Permissions (nl.uva.cs.lobcder.auth.Permissions)3 WebResource (com.sun.jersey.api.client.WebResource)2 SQLException (java.sql.SQLException)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 Path (javax.ws.rs.Path)2 MyPrincipal (nl.uva.cs.lobcder.auth.MyPrincipal)2 GenericType (com.sun.jersey.api.client.GenericType)1 MultivaluedMapImpl (com.sun.jersey.core.util.MultivaluedMapImpl)1 Path (io.milton.common.Path)1 FileOutputStream (java.io.FileOutputStream)1 OutputStream (java.io.OutputStream)1 Connection (java.sql.Connection)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 GZIPOutputStream (java.util.zip.GZIPOutputStream)1