Changeset 2698


Ignore:
Timestamp:
03/14/13 13:30:06 (11 years ago)
Author:
oschonef
Message:
  • buffer output as long as possible (helps to gracefully recover from error conditions with fatal diagnostic)
  • make buffer size a configuration parameter
  • more debugging information in case of (recoverable) error condition with fatal diagnostics
Location:
SRUServer/trunk/src/main/java/eu/clarin/sru/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUServer.java

    r2692 r2698  
    1717package eu.clarin.sru.server;
    1818
     19import java.io.FilterOutputStream;
    1920import java.io.IOException;
    2021import java.io.OutputStream;
     
    6566    static final String RESPONSE_ENCODING = "utf-8";
    6667    private static final String RESPONSE_CONTENT_TYPE = "application/xml";
    67     private static final int RESPONSE_BUFFER_SIZE = 64 * 1024;
    6868    private static final Logger logger =
    6969            LoggerFactory.getLogger(SRUServer.class);
     
    116116            response.setStatus(HttpServletResponse.SC_OK);
    117117            // make sure we can reset the stream later in case of error ...
    118             response.setBufferSize(RESPONSE_BUFFER_SIZE);
    119 
     118            response.setBufferSize(config.getResponseBufferSize());
    120119            try {
    121120                if (req.checkParameters()) {
     
    135134                    SRUXMLStreamWriter out =
    136135                        createXMLStreamWriter(response.getOutputStream(),
    137                                 SRURecordPacking.XML, req.getIndentResponse());
     136                                SRURecordPacking.XML, false,
     137                                req.getIndentResponse());
    138138                    writeFatalError(out, req, req.getDiagnostics());
    139139                }
     
    150150        } catch (SRUException e) {
    151151            if (!response.isCommitted()) {
     152                if (logger.isInfoEnabled()) {
     153                    final String message = e.getDiagnostic().getMessage();
     154                    if (message != null) {
     155                        logger.info("Sending fatal diagnostic '{}{}' with " +
     156                                "message '{}'",
     157                                new Object[] {
     158                                        SRUConstants.SRU_DIAGNOSTIC_URI_PREFIX,
     159                                        e.getDiagnostic().getCode(),
     160                                        message
     161                                });
     162                    } else {
     163                        logger.info("Sending fatal diagnostic '{}{}'",
     164                                SRUConstants.SRU_DIAGNOSTIC_URI_PREFIX,
     165                                e.getDiagnostic().getCode());
     166                    }
     167                    logger.debug("Fatal diagnostic was caused by " +
     168                            "this exception", e);
     169                }
    152170                response.resetBuffer();
    153171                try {
     
    160178                    SRUXMLStreamWriter out =
    161179                            createXMLStreamWriter(response.getOutputStream(),
    162                                     SRURecordPacking.XML,
     180                                    SRURecordPacking.XML, false,
    163181                                    req.getIndentResponse());
    164182                    writeFatalError(out, req, diagnostics);
     
    168186                }
    169187            } else {
     188                /*
     189                 * The servlet already flushed the output buffer, so cannot
     190                 * degrade gracefully anymore and, unfortunately, will produce
     191                 * ill-formed XML output.
     192                 * Increase the response buffer size, if you want to avoid
     193                 * this (at the cost of memory).
     194                 */
    170195                logger.error("A fatal error occurred, but the response was "
    171                         + "already committed", e);
     196                        + "already committed. Unable to recover gracefully.", e);
    172197            }
    173198        }
     
    188213                    createXMLStreamWriter(response.getOutputStream(),
    189214                                          request.getRecordPacking(),
     215                                          true,
    190216                                          request.getIndentResponse());
    191217
     
    238264                    createXMLStreamWriter(response.getOutputStream(),
    239265                                          request.getRecordPacking(),
     266                                          true,
    240267                                          request.getIndentResponse());
    241268
     
    364391                    createXMLStreamWriter(response.getOutputStream(),
    365392                                          request.getRecordPacking(),
     393                                          true,
    366394                                          request.getIndentResponse());
    367395
     
    10441072
    10451073    private SRUXMLStreamWriter createXMLStreamWriter(OutputStream out,
    1046             SRURecordPacking recordPacking, int indent) throws SRUException {
     1074            SRURecordPacking recordPacking, boolean skipFlush, int indent)
     1075            throws SRUException {
    10471076        try {
    1048             return new SRUXMLStreamWriter(out, writerFactory, recordPacking,
    1049                     indent);
     1077            if (skipFlush) {
     1078                /*
     1079                 * Add a FilterOutputStream to delay flush() as long as
     1080                 * possible. Doing so, enabled us to send an appropriate SRU
     1081                 * diagnostic in case an error occurs during the serialization
     1082                 * of the response.
     1083                 * Of course, if an error occurs when the Servlet response
     1084                 * buffer already had been flushed, because it was to large,
     1085                 * we cannot fail gracefully and we will produce ill-formed
     1086                 * XML output.
     1087                 */
     1088                out = new FilterOutputStream(out) {
     1089                    @Override
     1090                    public void flush() throws IOException {
     1091                    }
     1092
     1093
     1094                    @Override
     1095                    public void close() throws IOException {
     1096                        super.flush();
     1097                        super.close();
     1098                    }
     1099                };
     1100            }
     1101            return new SRUXMLStreamWriter(out, writerFactory,
     1102                    recordPacking, indent);
    10501103        } catch (Exception e) {
    10511104            throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUServerConfig.java

    r2683 r2698  
    224224            "eu.clarin.sru.server.allowOverrideIndentResponse";
    225225    /**
     226     * Parameter constant for configuring the size of response buffer size. The
     227     * servlet will buffer up to this amount of data before sending a response
     228     * to the client. The value if the response buffer in bytes.
     229     * <p>
     230     * Valid values: any positive integer (default 65536)
     231     * </p>
     232     */
     233    public static final String SRU_RESPONSE_BUFFER_SIZE =
     234            "eu.clarin.sru.server.responseBufferSize";
     235    /**
    226236     * @deprecated use {@link #SRU_TRANSPORT}
    227237     */
     
    283293    private static final String LEGACY_SRU_ALLOW_OVERRIDE_INDENT_RESPONSE =
    284294            "sru.allowOverrideIndentResponse";
    285     private static final int DEFAULT_NUMBER_OF_RECORDS = 100;
    286     private static final int DEFAULT_MAXIMUM_RECORDS   = 250;
    287     private static final int DEFAULT_NUMBER_OF_TERMS   = 250;
    288     private static final int DEFAULT_MAXIMUM_TERMS     = 500;
     295    private static final int DEFAULT_NUMBER_OF_RECORDS    = 100;
     296    private static final int DEFAULT_MAXIMUM_RECORDS      = 250;
     297    private static final int DEFAULT_NUMBER_OF_TERMS      = 250;
     298    private static final int DEFAULT_MAXIMUM_TERMS        = 500;
     299    private static final int DEFAULT_RESPONSE_BUFFER_SIZE = 64 * 1024;
    289300    private static final String CONFIG_FILE_NAMESPACE_URI =
    290301            "http://www.clarin.eu/sru-server/1.0/";
     
    626637    private final boolean echoRequests;
    627638    private final int indentResponse;
     639    private final int responseBufferSize;
    628640    private final boolean allowOverrideMaximumRecords;
    629641    private final boolean allowOverrideMaximumTerms;
     
    638650            String database, int numberOfRecords, int maximumRecords,
    639651            int numberOfTerms, int maximumTerms, boolean echoRequests,
    640             int indentResponse, boolean allowOverrideMaximumRecords,
     652            int indentResponse, int responseBufferSize,
     653            boolean allowOverrideMaximumRecords,
    641654            boolean allowOverrideMaximumTerms,
    642655            boolean allowOverrideIndentResponse, DatabaseInfo databaseinfo,
     
    652665        this.echoRequests                = echoRequests;
    653666        this.indentResponse              = indentResponse;
     667        this.responseBufferSize          = responseBufferSize;
    654668        this.allowOverrideMaximumRecords = allowOverrideMaximumRecords;
    655669        this.allowOverrideMaximumTerms   = allowOverrideMaximumTerms;
     
    751765    public boolean allowOverrideIndentResponse() {
    752766        return allowOverrideIndentResponse;
     767    }
     768
     769
     770    public int getResponseBufferSize() {
     771        return responseBufferSize;
    753772    }
    754773
     
    9881007                    SRU_ALLOW_OVERRIDE_INDENT_RESPONSE, false, false);
    9891008
     1009            int responseBufferSize = parseNumber(params,
     1010                    SRU_RESPONSE_BUFFER_SIZE, false,
     1011                    DEFAULT_RESPONSE_BUFFER_SIZE, 0, -1);
     1012
    9901013            return new SRUServerConfig(transport, host, port, database,
    9911014                    numberOfRecords, maximumRecords, numberOfTerms,
    9921015                    maximumTerms, echoRequests, indentResponse,
    993                     allowOverrideMaximumRecords, allowOverrideMaximumTerms,
    994                     allowOverrideIndentResponse, databaseInfo, indexInfo,
    995                     schemaInfo);
     1016                    responseBufferSize, allowOverrideMaximumRecords,
     1017                    allowOverrideMaximumTerms, allowOverrideIndentResponse,
     1018                    databaseInfo, indexInfo, schemaInfo);
    9961019        } catch (IOException e) {
    9971020            throw new SRUConfigException("error reading configuration file", e);
Note: See TracChangeset for help on using the changeset viewer.