/**
   * @param pConfig The physical source config for which the event producer is configured.
   * @param schemaRegistryService Schema registry to fetch schemas
   * @param dbusEventBuffer An event buffer to which the producer can write/append events.
   * @param statsCollector Reporting stats
   * @param maxScnReaderWriters To read/write the maxScn from maxScn file
   * @throws DatabusException
   */
  public GoldenGateEventProducer(
      PhysicalSourceStaticConfig pConfig,
      SchemaRegistryService schemaRegistryService,
      DbusEventBufferAppendable dbusEventBuffer,
      DbusEventsStatisticsCollector statsCollector,
      MaxSCNReaderWriter maxScnReaderWriters)
      throws DatabusException {
    super(dbusEventBuffer, maxScnReaderWriters, pConfig, null);
    _pConfig = pConfig;
    _schemaRegistryService = schemaRegistryService;
    _statsCollector = statsCollector;
    _currentState = State.INIT;
    _partitionFunctionHashMap = new HashMap<Integer, PartitionFunction>();
    _eventsLog = Logger.getLogger("com.linkedin.databus2.producers.db.events." + pConfig.getName());

    if (_pConfig != null) {
      long eventRatePerSec = pConfig.getEventRatePerSec();
      long maxThrottleDurationInSecs = pConfig.getMaxThrottleDurationInSecs();

      if ((eventRatePerSec > 0) && (maxThrottleDurationInSecs > 0)) {
        _rc = new RateControl(eventRatePerSec, maxThrottleDurationInSecs);
      } else {
        // Disable rate control
        _rc = new RateControl(Long.MIN_VALUE, Long.MIN_VALUE);
      }
    }

    final String MODULE = GoldenGateEventProducer.class.getName();
    _log = Logger.getLogger(MODULE + "." + getName());

    // Create a hashmap for logical source id ==> PartitionFunction, this will be used as the
    // logical partition Id for the event creation
    // also create a list(map) of MonitoredSourceInfo objects to monitor GGEventProducer progress
    for (int i = 0; i < _pConfig.getSources().length; i++) {
      LogicalSourceStaticConfig logicalSourceStaticConfig = _pConfig.getSources()[i];
      GGMonitoredSourceInfo source =
          buildGGMonitoredSourceInfo(logicalSourceStaticConfig, _pConfig);
      _monitoredSources.put(source.getSourceId(), source);
    }

    // get one fake global source for total stats
    LogicalSourceStaticConfig logicalSourceStaticConfig =
        new LogicalSourceStaticConfig(
            GLOBAL_SOURCE_ID,
            _pConfig.getName(),
            "",
            "constant:1",
            (short) 0,
            false,
            null,
            null,
            null);
    GGMonitoredSourceInfo source = buildGGMonitoredSourceInfo(logicalSourceStaticConfig, _pConfig);
    _monitoredSources.put(source.getSourceId(), source);

    // create stats collector for parser
    _ggParserStats = new GGParserStatistics(_pConfig.getName());
    registerParserMbean(_ggParserStats);
  }
  // register each source with the mbeanServer
  private void registerMbeans(GGMonitoredSourceInfo source) throws DatabusException {
    try {
      Hashtable<String, String> props = new Hashtable<String, String>();
      props.put("type", "SourceStatistics");
      props.put("name", source.getSourceName());
      ObjectName objectName = new ObjectName(ServerContainer.JMX_DOMAIN, props);

      if (_mbeanServer.isRegistered(objectName)) {
        _log.warn("Unregistering old gg-source statistics mbean: " + objectName);
        _mbeanServer.unregisterMBean(objectName);
      }

      _mbeanServer.registerMBean(source.getStatisticsBean(), objectName);
      _log.info("Registered gg-source statistics mbean: " + objectName);
      _registeredMbeans.add(objectName);
    } catch (Exception ex) {
      _log.error(
          "Failed to register the gg-source statistics mbean for source ("
              + source.getSourceName()
              + ") due to an exception.",
          ex);
      throw new DatabusException("Failed to initialize gg event statistics mbeans.", ex);
    }
  }