Example #1
0
  @Override
  public void storeEvent(PersistableEvent pe, Connection connection) {
    // First populate the main event table
    byte[] basePayload = pe.getBasePayload();
    byte[] spillPayload = pe.getSpillPayload();
    boolean hasSpillPayload = (spillPayload != null);
    String channelName = pe.getChannelName();

    LOGGER.debug("Preparing insert event: " + pe);

    PreparedStatement baseEventStmt = null;
    PreparedStatement spillEventStmt = null;
    PreparedStatement baseHeaderStmt = null;
    PreparedStatement headerNameSpillStmt = null;
    PreparedStatement headerValueSpillStmt = null;
    try {
      baseEventStmt =
          connection.prepareStatement(STMT_INSERT_EVENT_BASE, Statement.RETURN_GENERATED_KEYS);
      baseEventStmt.setBytes(1, basePayload);
      baseEventStmt.setString(2, channelName);
      baseEventStmt.setBoolean(3, hasSpillPayload);

      int baseEventCount = baseEventStmt.executeUpdate();
      if (baseEventCount != 1) {
        throw new JdbcChannelException(
            "Invalid update count on base " + "event insert: " + baseEventCount);
      }
      // Extract event ID and set it
      ResultSet eventIdResult = baseEventStmt.getGeneratedKeys();

      if (!eventIdResult.next()) {
        throw new JdbcChannelException("Unable to retrieive inserted event-id");
      }

      long eventId = eventIdResult.getLong(1);
      pe.setEventId(eventId);

      // Persist the payload spill
      if (hasSpillPayload) {
        spillEventStmt = connection.prepareStatement(STMT_INSERT_EVENT_SPILL);
        spillEventStmt.setLong(1, eventId);
        spillEventStmt.setBinaryStream(
            2, new ByteArrayInputStream(spillPayload), spillPayload.length);
        int spillEventCount = spillEventStmt.executeUpdate();
        if (spillEventCount != 1) {
          throw new JdbcChannelException(
              "Invalid update count on spill " + "event insert: " + spillEventCount);
        }
      }

      // Persist the headers
      List<HeaderEntry> headers = pe.getHeaderEntries();
      if (headers != null && headers.size() > 0) {
        List<HeaderEntry> headerWithNameSpill = new ArrayList<HeaderEntry>();
        List<HeaderEntry> headerWithValueSpill = new ArrayList<HeaderEntry>();

        baseHeaderStmt =
            connection.prepareStatement(STMT_INSERT_HEADER_BASE, Statement.RETURN_GENERATED_KEYS);
        Iterator<HeaderEntry> it = headers.iterator();
        while (it.hasNext()) {
          HeaderEntry entry = it.next();
          SpillableString name = entry.getName();
          SpillableString value = entry.getValue();
          baseHeaderStmt.setLong(1, eventId);
          baseHeaderStmt.setString(2, name.getBase());
          baseHeaderStmt.setString(3, value.getBase());
          baseHeaderStmt.setBoolean(4, name.hasSpill());
          baseHeaderStmt.setBoolean(5, value.hasSpill());

          int updateCount = baseHeaderStmt.executeUpdate();
          if (updateCount != 1) {
            throw new JdbcChannelException("Unexpected update header count: " + updateCount);
          }
          ResultSet headerIdResultSet = baseHeaderStmt.getGeneratedKeys();
          if (!headerIdResultSet.next()) {
            throw new JdbcChannelException("Unable to retrieve inserted header id");
          }
          long headerId = headerIdResultSet.getLong(1);
          entry.setId(headerId);

          if (name.hasSpill()) {
            headerWithNameSpill.add(entry);
          }

          if (value.hasSpill()) {
            headerWithValueSpill.add(entry);
          }
        }

        // Persist header name spills
        if (headerWithNameSpill.size() > 0) {
          LOGGER.debug("Number of headers with name spill: " + headerWithNameSpill.size());

          headerNameSpillStmt = connection.prepareStatement(STMT_INSERT_HEADER_NAME_SPILL);

          for (HeaderEntry entry : headerWithNameSpill) {
            String nameSpill = entry.getName().getSpill();

            headerNameSpillStmt.setLong(1, entry.getId());
            headerNameSpillStmt.setString(2, nameSpill);
            headerNameSpillStmt.addBatch();
          }

          int[] nameSpillUpdateCount = headerNameSpillStmt.executeBatch();
          if (nameSpillUpdateCount.length != headerWithNameSpill.size()) {
            throw new JdbcChannelException(
                "Unexpected update count for header "
                    + "name spills: expected "
                    + headerWithNameSpill.size()
                    + ", "
                    + "found "
                    + nameSpillUpdateCount.length);
          }

          for (int i = 0; i < nameSpillUpdateCount.length; i++) {
            if (nameSpillUpdateCount[i] != 1) {
              throw new JdbcChannelException(
                  "Unexpected update count for "
                      + "header name spill at position "
                      + i
                      + ", value: "
                      + nameSpillUpdateCount[i]);
            }
          }
        }

        // Persist header value spills
        if (headerWithValueSpill.size() > 0) {
          LOGGER.debug("Number of headers with value spill: " + headerWithValueSpill.size());

          headerValueSpillStmt = connection.prepareStatement(STMT_INSERT_HEADER_VALUE_SPILL);

          for (HeaderEntry entry : headerWithValueSpill) {
            String valueSpill = entry.getValue().getSpill();

            headerValueSpillStmt.setLong(1, entry.getId());
            headerValueSpillStmt.setString(2, valueSpill);
            headerValueSpillStmt.addBatch();
          }

          int[] valueSpillUpdateCount = headerValueSpillStmt.executeBatch();
          if (valueSpillUpdateCount.length != headerWithValueSpill.size()) {
            throw new JdbcChannelException(
                "Unexpected update count for header "
                    + "value spills: expected "
                    + headerWithValueSpill.size()
                    + ", "
                    + "found "
                    + valueSpillUpdateCount.length);
          }

          for (int i = 0; i < valueSpillUpdateCount.length; i++) {
            if (valueSpillUpdateCount[i] != 1) {
              throw new JdbcChannelException(
                  "Unexpected update count for "
                      + "header value spill at position "
                      + i
                      + ", value: "
                      + valueSpillUpdateCount[i]);
            }
          }
        }
      }
    } catch (SQLException ex) {
      throw new JdbcChannelException("Unable to persist event: " + pe, ex);
    } finally {
      if (baseEventStmt != null) {
        try {
          baseEventStmt.close();
        } catch (SQLException ex) {
          LOGGER.error("Unable to close base event statement", ex);
        }
      }
      if (spillEventStmt != null) {
        try {
          spillEventStmt.close();
        } catch (SQLException ex) {
          LOGGER.error("Unable to close spill event statement", ex);
        }
      }
      if (baseHeaderStmt != null) {
        try {
          baseHeaderStmt.close();
        } catch (SQLException ex) {
          LOGGER.error("Unable to close base header statement", ex);
        }
      }
      if (headerNameSpillStmt != null) {
        try {
          headerNameSpillStmt.close();
        } catch (SQLException ex) {
          LOGGER.error("Unable to close header name spill statement", ex);
        }
      }
      if (headerValueSpillStmt != null) {
        try {
          headerValueSpillStmt.close();
        } catch (SQLException ex) {
          LOGGER.error("Unable to close header value spill statement", ex);
        }
      }
    }

    LOGGER.debug("Event persisted: " + pe);
  }