问:
Elasticsearch transport client java client
I'm trying to rebuild a plugin that talks to elasticsearch 2.4 to work with Elasticsearch 5.

The code is from::
https://github.com/pentaho/pentaho-kettle/blob/master/plugins/elasticsearch-bulk-insert/src/org/pentaho/di/trans/steps/elasticsearchbulk/ElasticSearchBulk.java

Here is the code:

```<code>/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.pentaho.di.trans.steps.elasticsearchbulk;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexRequest.OpType;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.row.RowDataUtil;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;

/**
 * Does bulk insert of data into ElasticSearch
 *
 * @author webdetails
 * @since 16-02-2011
 */
public class ElasticSearchBulk extends BaseStep implements StepInterface {

  private static final String INSERT_ERROR_CODE = null;
  private static Class<?> PKG = ElasticSearchBulkMeta.class; // for i18n
  private ElasticSearchBulkMeta meta;
  private ElasticSearchBulkData data;

  TransportClient tc;

  private Node node;
  private Client client;
  private String index;
  private String type;

  BulkRequestBuilder currentRequest;

  private int batchSize = 2;

  private boolean isJsonInsert = false;
  private int jsonFieldIdx = 0;

  private String idOutFieldName = null;
  private Integer idFieldIndex = null;

  private Long timeout = null;
  private TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;

  // private long duration = 0L;
  private int numberOfErrors = 0;

  private List<IndexRequestBuilder> requestsBuffer;

  private boolean stopOnError = true;
  private boolean useOutput = true;

  private Map<String, String> columnsToJson;
  private boolean hasFields;

  private IndexRequest.OpType opType = OpType.CREATE;

  public ElasticSearchBulk( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
      Trans trans ) {
    super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
  }

  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {

    Object[] rowData = getRow();
    if ( rowData == null ) {
      if ( currentRequest != null && currentRequest.numberOfActions() > 0 ) {
        // didn't fill a whole batch
        processBatch( false );
      }
      setOutputDone();
      return false;
    }

    if ( first ) {
      first = false;
      setupData();
      currentRequest = client.prepareBulk();
      requestsBuffer = new ArrayList<IndexRequestBuilder>( this.batchSize );
      initFieldIndexes();
    }

    try {
      data.inputRowBuffer[data.nextBufferRowIdx++] = rowData;
      return indexRow( data.inputRowMeta, rowData ) || !stopOnError;
    } catch ( KettleStepException e ) {
      throw e;
    } catch ( Exception e ) {
      rejectAllRows( e.getLocalizedMessage() );
      String msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Log.Exception", e.getLocalizedMessage() );
      logError( msg );
      throw new KettleStepException( msg, e );
    }
  }

  /**
   * Initialize <code>this.data</code>
   *
   * @throws KettleStepException
   */
  private void setupData() throws KettleStepException {
    data.nextBufferRowIdx = 0;
    data.inputRowMeta = getInputRowMeta().clone(); // only available after first getRow();
    data.inputRowBuffer = new Object[batchSize][];
    data.outputRowMeta = data.inputRowMeta.clone();
    meta.getFields( data.outputRowMeta, getStepname(), null, null, this, repository, metaStore );
  }

  private void initFieldIndexes() throws KettleStepException {
    if ( isJsonInsert ) {
      Integer idx = getFieldIdx( data.inputRowMeta, environmentSubstitute( meta.getJsonField() ) );
      if ( idx != null ) {
        jsonFieldIdx = idx.intValue();
      } else {
        throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Error.NoJsonField" ) );
      }
    }

    idOutFieldName = environmentSubstitute( meta.getIdOutField() );

    if ( StringUtils.isNotBlank( meta.getIdInField() ) ) {
      idFieldIndex = getFieldIdx( data.inputRowMeta, environmentSubstitute( meta.getIdInField() ) );
      if ( idFieldIndex == null ) {
        throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Error.InvalidIdField" ) );
      }
    } else {
      idFieldIndex = null;
    }
  }

  private static Integer getFieldIdx( RowMetaInterface rowMeta, String fieldName ) {
    if ( fieldName == null ) {
      return null;
    }

    for ( int i = 0; i < rowMeta.size(); i++ ) {
      String name = rowMeta.getValueMeta( i ).getName();
      if ( fieldName.equals( name ) ) {
        return i;
      }
    }
    return null;
  }

  /**
   * @param rowMeta
   *          The metadata for the row to be indexed
   * @param row
   *          The data for the row to be indexed
   */

  private boolean indexRow( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
    try {

      IndexRequestBuilder requestBuilder = client.prepareIndex( index, type );
      requestBuilder.setOpType( this.opType );

      if ( idFieldIndex != null ) {
        requestBuilder.setId( "" + row[idFieldIndex] ); // "" just in case field isn't string
      }

      if ( isJsonInsert ) {
        addSourceFromJsonString( row, requestBuilder );
      } else {
        addSourceFromRowFields( requestBuilder, rowMeta, row );
      }

      currentRequest.add( requestBuilder );
      requestsBuffer.add( requestBuilder );

      if ( currentRequest.numberOfActions() >= batchSize ) {
        return processBatch( true );
      } else {
        return true;
      }

    } catch ( KettleStepException e ) {
      throw e;
    } catch ( NoNodeAvailableException e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulkDialog.Error.NoNodesFound" ) );
    } catch ( Exception e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Log.Exception", e
          .getLocalizedMessage() ), e );
    }
  }

  /**
   * @param row
   * @param requestBuilder
   */
  private void addSourceFromJsonString( Object[] row, IndexRequestBuilder requestBuilder ) throws KettleStepException {
    Object jsonString = row[jsonFieldIdx];
    if ( jsonString instanceof byte[] ) {
      requestBuilder.setSource( (byte[]) jsonString );
    } else if ( jsonString instanceof String ) {
      requestBuilder.setSource( ( (String) jsonString ).getBytes() );
    } else {
      throw new KettleStepException( BaseMessages.getString( "ElasticSearchBulk.Error.NoJsonFieldFormat" ) );
    }
  }

  /**
   * @param requestBuilder
   * @param rowMeta
   * @param row
   * @throws IOException
   */
  private void addSourceFromRowFields( IndexRequestBuilder requestBuilder, RowMetaInterface rowMeta, Object[] row )
    throws IOException {
    XContentBuilder jsonBuilder = XContentFactory.jsonBuilder().startObject();

    for ( int i = 0; i < rowMeta.size(); i++ ) {
      if ( idFieldIndex != null && i == idFieldIndex ) { // skip id
        continue;
      }

      ValueMetaInterface valueMeta = rowMeta.getValueMeta( i );
      String name = hasFields ? columnsToJson.get( valueMeta.getName() ) : valueMeta.getName();
      Object value = row[i];
      if ( value instanceof Date && value.getClass() != Date.class ) {
        Date subDate = (Date) value;
        // create a genuine Date object, or jsonBuilder will not recognize it
        value = new Date( subDate.getTime() );
      }
      if ( StringUtils.isNotBlank( name ) ) {
        jsonBuilder.field( name, value );
      }
    }

    jsonBuilder.endObject();
    requestBuilder.setSource( jsonBuilder );
  }

  public boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (ElasticSearchBulkMeta) smi;
    data = (ElasticSearchBulkData) sdi;

    if ( super.init( smi, sdi ) ) {

      try {

        numberOfErrors = 0;

        initFromMeta();
        initClient();

        return true;

      } catch ( Exception e ) {
        logError( BaseMessages.getString( PKG, "ElasticSearchBulk.Log.ErrorOccurredDuringStepInitialize" )
            + e.getMessage() );
      }
      return true;
    }
    return false;
  }

  private void initFromMeta() {
    index = environmentSubstitute( meta.getIndex() );
    type = environmentSubstitute( meta.getType() );
    batchSize = meta.getBatchSizeInt( this );
    try {
      timeout = Long.parseLong( environmentSubstitute( meta.getTimeOut() ) );
    } catch ( NumberFormatException e ) {
      timeout = null;
    }
    timeoutUnit = meta.getTimeoutUnit();
    isJsonInsert = meta.isJsonInsert();
    useOutput = meta.isUseOutput();
    stopOnError = meta.isStopOnError();

    columnsToJson = meta.getFieldsMap();
    this.hasFields = columnsToJson.size() > 0;

    this.opType =
        StringUtils.isNotBlank( meta.getIdInField() ) && meta.isOverWriteIfSameId() ? OpType.INDEX : OpType.CREATE;

  }

  private boolean processBatch( boolean makeNew ) throws KettleStepException {

    ListenableActionFuture<BulkResponse> actionFuture = currentRequest.execute();
    boolean responseOk = false;

    BulkResponse response = null;
    try {
      if ( timeout != null && timeoutUnit != null ) {
        response = actionFuture.actionGet( timeout, timeoutUnit );
      } else {
        response = actionFuture.actionGet();
      }
    } catch ( ElasticsearchException e ) {
      String msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Error.BatchExecuteFail", e.getLocalizedMessage() );
      if ( e instanceof ElasticsearchTimeoutException ) {
        msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Error.Timeout" );
      }
      logError( msg );
      rejectAllRows( msg );
    }

    if ( response != null ) {
      responseOk = handleResponse( response );
      requestsBuffer.clear();
    } else { // have to assume all failed
      numberOfErrors += currentRequest.numberOfActions();
      setErrors( numberOfErrors );
    }
    // duration += response.getTookInMillis(); //just in trunk..

    if ( makeNew ) {
      currentRequest = client.prepareBulk();
      data.nextBufferRowIdx = 0;
      data.inputRowBuffer = new Object[batchSize][];
    } else {
      currentRequest = null;
      data.inputRowBuffer = null;
    }

    return responseOk;
  }

  /**
   * @param response
   * @return <code>true</code> if no errors
   */
  private boolean handleResponse( BulkResponse response ) {

    boolean hasErrors = response.hasFailures();

    if ( hasErrors ) {
      logError( response.buildFailureMessage() );
    }

    int errorsInBatch = 0;

    if ( hasErrors || useOutput ) {
      for ( BulkItemResponse item : response ) {
        if ( item.isFailed() ) {
          // log
          logDetailed( item.getFailureMessage() );
          errorsInBatch++;
          if ( getStepMeta().isDoingErrorHandling() ) {
            rejectRow( item.getItemId(), item.getFailureMessage() );
          }
        } else if ( useOutput ) {
          if ( idOutFieldName != null ) {
            addIdToRow( item.getId(), item.getItemId() );
          }
          echoRow( item.getItemId() );
        }
      }
    }

    numberOfErrors += errorsInBatch;
    setErrors( numberOfErrors );
    int linesOK = currentRequest.numberOfActions() - errorsInBatch;

    if ( useOutput ) {
      setLinesOutput( getLinesOutput() + linesOK );
    } else {
      setLinesWritten( getLinesWritten() + linesOK );
    }

    return !hasErrors;
  }

  private void addIdToRow( String id, int rowIndex ) {

    data.inputRowBuffer[rowIndex] =
        RowDataUtil.resizeArray( data.inputRowBuffer[rowIndex], getInputRowMeta().size() + 1 );
    data.inputRowBuffer[rowIndex][getInputRowMeta().size()] = id;

  }

  /**
   * Send input row to output
   *
   * @param rowIndex
   */
  private void echoRow( int rowIndex ) {
    try {

      putRow( data.outputRowMeta, data.inputRowBuffer[rowIndex] );

    } catch ( KettleStepException e ) {
      logError( e.getLocalizedMessage() );
    } catch ( ArrayIndexOutOfBoundsException e ) {
      logError( e.getLocalizedMessage() );
    }
  }

  /**
   * Send input row to error.
   *
   * @param index
   * @param errorMsg
   */
  private void rejectRow( int index, String errorMsg ) {
    try {

      putError( getInputRowMeta(), data.inputRowBuffer[index], 1, errorMsg, null, INSERT_ERROR_CODE );

    } catch ( KettleStepException e ) {
      logError( e.getLocalizedMessage() );
    } catch ( ArrayIndexOutOfBoundsException e ) {
      logError( e.getLocalizedMessage() );
    }
  }

  private void rejectAllRows( String errorMsg ) {
    for ( int i = 0; i < data.nextBufferRowIdx; i++ ) {
      rejectRow( i, errorMsg );
    }
  }

  private void initClient() throws UnknownHostException {
    Settings.Builder settingsBuilder = Settings.builder();
    settingsBuilder.put( Settings.Builder.EMPTY_SETTINGS ); // keep default classloader
    settingsBuilder.put( meta.getSettingsMap() );
    // Settings settings = settingsBuilder.build();
    TransportClient.Builder tClientBuilder = TransportClient.builder().settings( settingsBuilder );

    if ( !meta.servers.isEmpty() ) {
      node = null;
      TransportClient tClient = tClientBuilder.build();
      for ( ElasticSearchBulkMeta.Server s : meta.servers ) {
        tClient.addTransportAddress( s.getAddr() );
      }
      client = tClient;
    } else {
      NodeBuilder nodeBuilder = NodeBuilder.nodeBuilder();
      nodeBuilder.settings( settingsBuilder );
      node = nodeBuilder.client( true ).node(); // this node will not hold data
      client = node.client();
      node.start();
    }
  }

  private void disposeClient() {

    if ( client != null ) {
      client.close();
    }
    if ( node != null ) {
      node.close();
    }

  }

  public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (ElasticSearchBulkMeta) smi;
    data = (ElasticSearchBulkData) sdi;
    try {
      disposeClient();
    } catch ( Exception e ) {
      logError( e.getLocalizedMessage(), e );
    }
    super.dispose( smi, sdi );
  }
}
</code>```

I understand that Elastic have move the transport client to a new module with Elastic 5. I'm fairly new to JAVA, although I have years of experience with other languages, so I'm hoping that this is not too complicated.

When I try to build the code with ant I get the following errors:

```<code>TranportClient.Builder tclientbuilder = TransportClient.build.()settings(settingsBuilder);

symbol not found pointing to the builder method for TransportClient
</code>```

What does this mean? Does it mean that the transport client was not imported in the imports?

I've tried to understand that elasticsearch documentation on this:

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html

It appears that I need to use the new:

```<code>PreBuiltTransportClient(settings);
</code>```

However this also gives a symbol not found error related to the  PreBuiltTransportClient.

This is using the latest elastic-5.2.1 jar source.

Any ideas how I can get this to build?

Thanks!

答:
You have the period in the wrong position.
It should be:

TranportClient.Builder tclientbuilder = TransportClient.build().settings(settingsBuilder);

Body:
I'm trying to rebuild a plugin that talks to elasticsearch 2.4 to work with Elasticsearch 5.

The code is from::
https://github.com/pentaho/pentaho-kettle/blob/master/plugins/elasticsearch-bulk-insert/src/org/pentaho/di/trans/steps/elasticsearchbulk/ElasticSearchBulk.java

Here is the code:

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.pentaho.di.trans.steps.elasticsearchbulk;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.action.ListenableActionFuture;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexRequest.OpType;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.row.RowDataUtil;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;

/**
 * Does bulk insert of data into ElasticSearch
 *
 * @author webdetails
 * @since 16-02-2011
 */
public class ElasticSearchBulk extends BaseStep implements StepInterface {

  private static final String INSERT_ERROR_CODE = null;
  private static Class<?> PKG = ElasticSearchBulkMeta.class; // for i18n
  private ElasticSearchBulkMeta meta;
  private ElasticSearchBulkData data;

  TransportClient tc;

  private Node node;
  private Client client;
  private String index;
  private String type;

  BulkRequestBuilder currentRequest;

  private int batchSize = 2;

  private boolean isJsonInsert = false;
  private int jsonFieldIdx = 0;

  private String idOutFieldName = null;
  private Integer idFieldIndex = null;

  private Long timeout = null;
  private TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;

  // private long duration = 0L;
  private int numberOfErrors = 0;

  private List<IndexRequestBuilder> requestsBuffer;

  private boolean stopOnError = true;
  private boolean useOutput = true;

  private Map<String, String> columnsToJson;
  private boolean hasFields;

  private IndexRequest.OpType opType = OpType.CREATE;

  public ElasticSearchBulk( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
      Trans trans ) {
    super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
  }

  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {

    Object[] rowData = getRow();
    if ( rowData == null ) {
      if ( currentRequest != null && currentRequest.numberOfActions() > 0 ) {
        // didn't fill a whole batch
        processBatch( false );
      }
      setOutputDone();
      return false;
    }

    if ( first ) {
      first = false;
      setupData();
      currentRequest = client.prepareBulk();
      requestsBuffer = new ArrayList<IndexRequestBuilder>( this.batchSize );
      initFieldIndexes();
    }

    try {
      data.inputRowBuffer[data.nextBufferRowIdx++] = rowData;
      return indexRow( data.inputRowMeta, rowData ) || !stopOnError;
    } catch ( KettleStepException e ) {
      throw e;
    } catch ( Exception e ) {
      rejectAllRows( e.getLocalizedMessage() );
      String msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Log.Exception", e.getLocalizedMessage() );
      logError( msg );
      throw new KettleStepException( msg, e );
    }
  }

  /**
   * Initialize this.data
   *
   * @throws KettleStepException
   */
  private void setupData() throws KettleStepException {
    data.nextBufferRowIdx = 0;
    data.inputRowMeta = getInputRowMeta().clone(); // only available after first getRow();
    data.inputRowBuffer = new Object[batchSize][];
    data.outputRowMeta = data.inputRowMeta.clone();
    meta.getFields( data.outputRowMeta, getStepname(), null, null, this, repository, metaStore );
  }

  private void initFieldIndexes() throws KettleStepException {
    if ( isJsonInsert ) {
      Integer idx = getFieldIdx( data.inputRowMeta, environmentSubstitute( meta.getJsonField() ) );
      if ( idx != null ) {
        jsonFieldIdx = idx.intValue();
      } else {
        throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Error.NoJsonField" ) );
      }
    }

    idOutFieldName = environmentSubstitute( meta.getIdOutField() );

    if ( StringUtils.isNotBlank( meta.getIdInField() ) ) {
      idFieldIndex = getFieldIdx( data.inputRowMeta, environmentSubstitute( meta.getIdInField() ) );
      if ( idFieldIndex == null ) {
        throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Error.InvalidIdField" ) );
      }
    } else {
      idFieldIndex = null;
    }
  }

  private static Integer getFieldIdx( RowMetaInterface rowMeta, String fieldName ) {
    if ( fieldName == null ) {
      return null;
    }

    for ( int i = 0; i < rowMeta.size(); i++ ) {
      String name = rowMeta.getValueMeta( i ).getName();
      if ( fieldName.equals( name ) ) {
        return i;
      }
    }
    return null;
  }

  /**
   * @param rowMeta
   *          The metadata for the row to be indexed
   * @param row
   *          The data for the row to be indexed
   */

  private boolean indexRow( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
    try {

      IndexRequestBuilder requestBuilder = client.prepareIndex( index, type );
      requestBuilder.setOpType( this.opType );

      if ( idFieldIndex != null ) {
        requestBuilder.setId( "" + row[idFieldIndex] ); // "" just in case field isn't string
      }

      if ( isJsonInsert ) {
        addSourceFromJsonString( row, requestBuilder );
      } else {
        addSourceFromRowFields( requestBuilder, rowMeta, row );
      }

      currentRequest.add( requestBuilder );
      requestsBuffer.add( requestBuilder );

      if ( currentRequest.numberOfActions() >= batchSize ) {
        return processBatch( true );
      } else {
        return true;
      }

    } catch ( KettleStepException e ) {
      throw e;
    } catch ( NoNodeAvailableException e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulkDialog.Error.NoNodesFound" ) );
    } catch ( Exception e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "ElasticSearchBulk.Log.Exception", e
          .getLocalizedMessage() ), e );
    }
  }

  /**
   * @param row
   * @param requestBuilder
   */
  private void addSourceFromJsonString( Object[] row, IndexRequestBuilder requestBuilder ) throws KettleStepException {
    Object jsonString = row[jsonFieldIdx];
    if ( jsonString instanceof byte[] ) {
      requestBuilder.setSource( (byte[]) jsonString );
    } else if ( jsonString instanceof String ) {
      requestBuilder.setSource( ( (String) jsonString ).getBytes() );
    } else {
      throw new KettleStepException( BaseMessages.getString( "ElasticSearchBulk.Error.NoJsonFieldFormat" ) );
    }
  }

  /**
   * @param requestBuilder
   * @param rowMeta
   * @param row
   * @throws IOException
   */
  private void addSourceFromRowFields( IndexRequestBuilder requestBuilder, RowMetaInterface rowMeta, Object[] row )
    throws IOException {
    XContentBuilder jsonBuilder = XContentFactory.jsonBuilder().startObject();

    for ( int i = 0; i < rowMeta.size(); i++ ) {
      if ( idFieldIndex != null && i == idFieldIndex ) { // skip id
        continue;
      }

      ValueMetaInterface valueMeta = rowMeta.getValueMeta( i );
      String name = hasFields ? columnsToJson.get( valueMeta.getName() ) : valueMeta.getName();
      Object value = row[i];
      if ( value instanceof Date && value.getClass() != Date.class ) {
        Date subDate = (Date) value;
        // create a genuine Date object, or jsonBuilder will not recognize it
        value = new Date( subDate.getTime() );
      }
      if ( StringUtils.isNotBlank( name ) ) {
        jsonBuilder.field( name, value );
      }
    }

    jsonBuilder.endObject();
    requestBuilder.setSource( jsonBuilder );
  }

  public boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (ElasticSearchBulkMeta) smi;
    data = (ElasticSearchBulkData) sdi;

    if ( super.init( smi, sdi ) ) {

      try {

        numberOfErrors = 0;

        initFromMeta();
        initClient();

        return true;

      } catch ( Exception e ) {
        logError( BaseMessages.getString( PKG, "ElasticSearchBulk.Log.ErrorOccurredDuringStepInitialize" )
            + e.getMessage() );
      }
      return true;
    }
    return false;
  }

  private void initFromMeta() {
    index = environmentSubstitute( meta.getIndex() );
    type = environmentSubstitute( meta.getType() );
    batchSize = meta.getBatchSizeInt( this );
    try {
      timeout = Long.parseLong( environmentSubstitute( meta.getTimeOut() ) );
    } catch ( NumberFormatException e ) {
      timeout = null;
    }
    timeoutUnit = meta.getTimeoutUnit();
    isJsonInsert = meta.isJsonInsert();
    useOutput = meta.isUseOutput();
    stopOnError = meta.isStopOnError();

    columnsToJson = meta.getFieldsMap();
    this.hasFields = columnsToJson.size() > 0;

    this.opType =
        StringUtils.isNotBlank( meta.getIdInField() ) && meta.isOverWriteIfSameId() ? OpType.INDEX : OpType.CREATE;

  }

  private boolean processBatch( boolean makeNew ) throws KettleStepException {

    ListenableActionFuture<BulkResponse> actionFuture = currentRequest.execute();
    boolean responseOk = false;

    BulkResponse response = null;
    try {
      if ( timeout != null && timeoutUnit != null ) {
        response = actionFuture.actionGet( timeout, timeoutUnit );
      } else {
        response = actionFuture.actionGet();
      }
    } catch ( ElasticsearchException e ) {
      String msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Error.BatchExecuteFail", e.getLocalizedMessage() );
      if ( e instanceof ElasticsearchTimeoutException ) {
        msg = BaseMessages.getString( PKG, "ElasticSearchBulk.Error.Timeout" );
      }
      logError( msg );
      rejectAllRows( msg );
    }

    if ( response != null ) {
      responseOk = handleResponse( response );
      requestsBuffer.clear();
    } else { // have to assume all failed
      numberOfErrors += currentRequest.numberOfActions();
      setErrors( numberOfErrors );
    }
    // duration += response.getTookInMillis(); //just in trunk..

    if ( makeNew ) {
      currentRequest = client.prepareBulk();
      data.nextBufferRowIdx = 0;
      data.inputRowBuffer = new Object[batchSize][];
    } else {
      currentRequest = null;
      data.inputRowBuffer = null;
    }

    return responseOk;
  }

  /**
   * @param response
   * @return true if no errors
   */
  private boolean handleResponse( BulkResponse response ) {

    boolean hasErrors = response.hasFailures();

    if ( hasErrors ) {
      logError( response.buildFailureMessage() );
    }

    int errorsInBatch = 0;

    if ( hasErrors || useOutput ) {
      for ( BulkItemResponse item : response ) {
        if ( item.isFailed() ) {
          // log
          logDetailed( item.getFailureMessage() );
          errorsInBatch++;
          if ( getStepMeta().isDoingErrorHandling() ) {
            rejectRow( item.getItemId(), item.getFailureMessage() );
          }
        } else if ( useOutput ) {
          if ( idOutFieldName != null ) {
            addIdToRow( item.getId(), item.getItemId() );
          }
          echoRow( item.getItemId() );
        }
      }
    }

    numberOfErrors += errorsInBatch;
    setErrors( numberOfErrors );
    int linesOK = currentRequest.numberOfActions() - errorsInBatch;

    if ( useOutput ) {
      setLinesOutput( getLinesOutput() + linesOK );
    } else {
      setLinesWritten( getLinesWritten() + linesOK );
    }

    return !hasErrors;
  }

  private void addIdToRow( String id, int rowIndex ) {

    data.inputRowBuffer[rowIndex] =
        RowDataUtil.resizeArray( data.inputRowBuffer[rowIndex], getInputRowMeta().size() + 1 );
    data.inputRowBuffer[rowIndex][getInputRowMeta().size()] = id;

  }

  /**
   * Send input row to output
   *
   * @param rowIndex
   */
  private void echoRow( int rowIndex ) {
    try {

      putRow( data.outputRowMeta, data.inputRowBuffer[rowIndex] );

    } catch ( KettleStepException e ) {
      logError( e.getLocalizedMessage() );
    } catch ( ArrayIndexOutOfBoundsException e ) {
      logError( e.getLocalizedMessage() );
    }
  }

  /**
   * Send input row to error.
   *
   * @param index
   * @param errorMsg
   */
  private void rejectRow( int index, String errorMsg ) {
    try {

      putError( getInputRowMeta(), data.inputRowBuffer[index], 1, errorMsg, null, INSERT_ERROR_CODE );

    } catch ( KettleStepException e ) {
      logError( e.getLocalizedMessage() );
    } catch ( ArrayIndexOutOfBoundsException e ) {
      logError( e.getLocalizedMessage() );
    }
  }

  private void rejectAllRows( String errorMsg ) {
    for ( int i = 0; i < data.nextBufferRowIdx; i++ ) {
      rejectRow( i, errorMsg );
    }
  }

  private void initClient() throws UnknownHostException {
    Settings.Builder settingsBuilder = Settings.builder();
    settingsBuilder.put( Settings.Builder.EMPTY_SETTINGS ); // keep default classloader
    settingsBuilder.put( meta.getSettingsMap() );
    // Settings settings = settingsBuilder.build();
    TransportClient.Builder tClientBuilder = TransportClient.builder().settings( settingsBuilder );

    if ( !meta.servers.isEmpty() ) {
      node = null;
      TransportClient tClient = tClientBuilder.build();
      for ( ElasticSearchBulkMeta.Server s : meta.servers ) {
        tClient.addTransportAddress( s.getAddr() );
      }
      client = tClient;
    } else {
      NodeBuilder nodeBuilder = NodeBuilder.nodeBuilder();
      nodeBuilder.settings( settingsBuilder );
      node = nodeBuilder.client( true ).node(); // this node will not hold data
      client = node.client();
      node.start();
    }
  }

  private void disposeClient() {

    if ( client != null ) {
      client.close();
    }
    if ( node != null ) {
      node.close();
    }

  }

  public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
    meta = (ElasticSearchBulkMeta) smi;
    data = (ElasticSearchBulkData) sdi;
    try {
      disposeClient();
    } catch ( Exception e ) {
      logError( e.getLocalizedMessage(), e );
    }
    super.dispose( smi, sdi );
  }
}

I understand that Elastic have move the transport client to a new module with Elastic 5. I'm fairly new to JAVA, although I have years of experience with other languages, so I'm hoping that this is not too complicated.

When I try to build the code with ant I get the following errors:

TranportClient.Builder tclientbuilder = TransportClient.build.()settings(settingsBuilder);

symbol not found pointing to the builder method for TransportClient

What does this mean? Does it mean that the transport client was not imported in the imports?

I've tried to understand that elasticsearch documentation on this:

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html

It appears that I need to use the new:

PreBuiltTransportClient(settings);

However this also gives a symbol not found error related to the  PreBuiltTransportClient.

This is using the latest elastic-5.2.1 jar source.

Any ideas how I can get this to build?

Thanks!


来源: stackexchange

问:
Access ListView Item Data
I'm setting the ItemSource of a listview and trying to create multiple Labels within the listview DataTemplate based on the children of a property of that particular item (the items are gigs, and they have a list of band members and im trying to list the band members).

I'm not sure how to get the properties of the current item that's having it's template created, can someone help?

```<code>            ListView listView = new ListView {
            ItemsSource = viewModel.gigs,
                ItemTemplate = new DataTemplate (() => {

                    var grid = new Grid();
            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});

                    for(int x = 0;x<=viewModel.bandMembers.Count;x++) {
                        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
                    }

                    var venueName = new Label { Text = "Top Left" };
                    venueName.SetBinding (Label.TextProperty, "Venue");
                    grid.Children.Add(venueName, 0, 0);

                    for(int x = 0;x<THISITEM.bandMembers.Count;x++) {
                        grid.Children.Add(new Label() {Text="Test"},x,0);
                    }

        return new ViewCell { View = grid };

            });

            // Build the page.
            this.Content = new StackLayout {
                Children = {
                    header,
                    listView
                }
            };
</code>```

答: You can override OnBindingContextChnaged function in ViewCell and get the ItemData from BindingContext </p>

ContentLicense: CC BY-SA 3.0

Title: Access ListView Item Data

Body:
I'm setting the ItemSource of a listview and trying to create multiple Labels within the listview DataTemplate based on the children of a property of that particular item (the items are gigs, and they have a list of band members and im trying to list the band members).

I'm not sure how to get the properties of the current item that's having it's template created, can someone help?

            ListView listView = new ListView {
            ItemsSource = viewModel.gigs,
                ItemTemplate = new DataTemplate (() => {

                    var grid = new Grid();
            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});

                    for(int x = 0;x<=viewModel.bandMembers.Count;x++) {
                        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
                    }

                    var venueName = new Label { Text = "Top Left" };
                    venueName.SetBinding (Label.TextProperty, "Venue");
                    grid.Children.Add(venueName, 0, 0);

                    for(int x = 0;x<THISITEM.bandMembers.Count;x++) {
                        grid.Children.Add(new Label() {Text="Test"},x,0);
                    }

        return new ViewCell { View = grid };

            });

            // Build the page.
            this.Content = new StackLayout {
                Children = {
                    header,
                    listView
                }
            };


问:
How do I obtain SHOUTcast "now playing" Metadata from the stream?
Say, I am about to inquire about current broadcasting of the stream "http://streaming.shoutcast.com/80sPlanet" (online radio "A.0.0.00Radio:All 80s All The Time").
I can make a HTTP GET requist to this URL with header "icy-metadata" set to "1", and it returns including the following "icy-*" headers:

```<code>key = "icy-br"; value = "128"
key = "icy-genre"; value = "Decades,80s"
key = "icy-metaint"; value = "16000"
key = "icy-name"; value = "A.0.0.00Radio:All 80s All The Time"
key = "icy-notice1"; value = "<BR>This stream requires <a href="http://www.winamp.com">Winamp</a><BR>"
key = "icy-notice2"; value = "SHOUTcast DNAS/posix(linux x64) v2.5.1.725<BR>"
key = "icy-pub"; value = "1"
key = "icy-sr"; value = "44100"
key = "icy-url"; value = "http://a.0.00radio.com/80s/"
</code>```

But there is no info about what is currently broadcasting on the stream (I mean song/artist/album/etc). Though, on the stream homepage (http://80splanet.com) there is always up-to-date information.
I've been told that it is possible to get the "now playing" info by HTTP GET request to the stream URL adding "/7.html" or "/stats". And it works for some streams. For example:

```<code>http://198.100.125.242/7.html
<HTML><meta http-equiv="Pragma" content="no-cache"></head><body>383,1,541,30000,377,128,Man of the Hour - w/ Patrick and Sebastian </body></html>
</code>```

(The numbers are the stream statistics. They are explained in the SHOUTcast server documentation)
But most of the streams do not support this feature (not "/7.html" nor "/stats"). HTTP error 404 returns or similar.

It looks like SHOUTcast provides some API (wiki.shoutcast.com/wiki/SHOUTcast_Developer) to request it's Radio Catalog, get Top Stations Charts and so on. There is also "SHOUTcast XML Metadata Specification". And it seems that there is a way to get that Metadata from the stream somehow.

Also, there is a way to dig into the stream raw data and search for the metadata basing on the "icy-metaint" header value as it explained here: stackoverflow.com/a/4914538/8128293, but (first) I have no access to the raw data of the stream (the android.media.MediaPlayer class recieves only the stream URL and maintain connection within itself). (Second) I am not sure about this approach due it is not docummented anywhere. And (third) I'm not sure if it would work with non-mpeg audio streams (for ex: audio/aacp).

Also I heard that there is a way to get this kind of metadata via JSON request to the stream, but still have no example to look at.

答:
but (first) I have no access to the raw data of the stream (the android.media.MediaPlayer class recieves only the stream URL and maintain connection within itself)

You're going to have to request the stream data and demux the metadata from it yourself.  The built-in Android classes aren't going to care about in-band metadata.

I'm no Android developer, but it looks like you can make your own MediaDataSource.  https://developer.android.com/reference/android/media/MediaDataSource.html

(Second) I am not sure about this approach due it is not docummented anywhere.

It's the approach, the only reasonable way to do it.  It hasn't changed in 20 years.  Icecast servers support metadata in the container as well, but that's unrelated to what you're trying to do.

And (third) I'm not sure if it would work with non-mpeg audio streams (for ex: audio/aacp).

It works great.  It has absolutely nothing to do with the content type.  This ICY-style metadata handling doesn't know or care about what it's embedded with.  The metadata should be separated out from the stream before the stream is handled by the codec.

Also I heard that there is a way to get this kind of metadata via JSON request to the stream

There isn't.  At least, not if you want to be compatible with all the servers out there.

Though, on the stream homepage (http://80splanet.com) there is always up-to-date information.

There are lots of ways to do this.  Most every station does this out-of-band with their own system.  (There's almost any way to manager your music library and handle scheduling.  It's common to actually drive the encoder metadata from a web script, where your "now playing" database is updated in real time at the time of playback into the encoder.)  Another way is to get the metadata server-side using the methods in the answer you linked to.  I used to offer an API server that would do this.  (I still have the code, if you want to license it from me.  E-mail me at brad@audiopump.co.)  A modern way is to use MediaSource Extensions and handle the metadata demuxing in-browser before passing the stream off to the player.  Neither SHOUTcast nor Icecast support this as neither properly supports CORS.  My own CDN supports this method, and the code is available for licensing as well.

Body:
Say, I am about to inquire about current broadcasting of the stream "http://streaming.shoutcast.com/80sPlanet" (online radio "A.0.0.00Radio:All 80s All The Time").
I can make a HTTP GET requist to this URL with header "icy-metadata" set to "1", and it returns including the following "icy-*" headers:

key = "icy-br"; value = "128"
key = "icy-genre"; value = "Decades,80s"
key = "icy-metaint"; value = "16000"
key = "icy-name"; value = "A.0.0.00Radio:All 80s All The Time"
key = "icy-notice1"; value = "
This stream requires Winamp
"
key = "icy-notice2"; value = "SHOUTcast DNAS/posix(linux x64) v2.5.1.725
"
key = "icy-pub"; value = "1"
key = "icy-sr"; value = "44100"
key = "icy-url"; value = "http://a.0.00radio.com/80s/"

But there is no info about what is currently broadcasting on the stream (I mean song/artist/album/etc). Though, on the stream homepage (http://80splanet.com) there is always up-to-date information.
I've been told that it is possible to get the "now playing" info by HTTP GET request to the stream URL adding "/7.html" or "/stats". And it works for some streams. For example:

http://198.100.125.242/7.html
<meta http-equiv="Pragma" content="no-cache">383,1,541,30000,377,128,Man of the Hour - w/ Patrick and Sebastian

(The numbers are the stream statistics. They are explained in the SHOUTcast server documentation)
But most of the streams do not support this feature (not "/7.html" nor "/stats"). HTTP error 404 returns or similar.

It looks like SHOUTcast provides some API (wiki.shoutcast.com/wiki/SHOUTcast_Developer) to request it's Radio Catalog, get Top Stations Charts and so on. There is also "SHOUTcast XML Metadata Specification". And it seems that there is a way to get that Metadata from the stream somehow.

Also, there is a way to dig into the stream raw data and search for the metadata basing on the "icy-metaint" header value as it explained here: stackoverflow.com/a/4914538/8128293, but (first) I have no access to the raw data of the stream (the android.media.MediaPlayer class recieves only the stream URL and maintain connection within itself). (Second) I am not sure about this approach due it is not docummented anywhere. And (third) I'm not sure if it would work with non-mpeg audio streams (for ex: audio/aacp).

Also I heard that there is a way to get this kind of metadata via JSON request to the stream, but still have no example to look at.


问:
Benchmarking programs on Linux
for an assignment we need to benchmark our implementations with different optimizations and parameters. Is there a feasible way of benchmarking little programs on the linux command line (I know of time) with different parameters which gives me the time data as CSV or something similiar? Output could be something like:

```<code>Implementation      Time
A                    23s
B with -O3 2Threads  15s
B with -O3 4Threads  10s
</code>```

I'm pretty sure that I've seen something like that on some professors slides but I cant remember who or when it was...

答:
Why not using time command inside a bash script, something like :

```<code>#!/bin/bash

NPROG=`cat proglist | wc -l`
for i in `seq 1 ${NPROG}`
do
    PROG=`sed -n "${i}p" proglist`
    ARG=`sed -n "${i}p" arglist`
    TIME=`{ time ${PROG} ${ARG}; } 2>&1 | grep real | awk '{print $2}'`
    echo "${TIME} ${PROG} ${ARG}"
done
</code>```

where proglist is a text file containing the programs to execute

```<code>A
B
B
</code>```

and arglist is a text file containing the arguments, something like :

```<code>-a 1 -b 2
-f "foo"
-f "bar"
</code>```

The output of the script will look-like :

```<code> 0m32.000s A -a 1 -b 2
 1m12.000s B -f "foo"
 5m38.000s B -f "bar"
</code>```

ContentLicense: CC BY-SA 2.5

Title: Benchmarking programs on Linux

Body:
for an assignment we need to benchmark our implementations with different optimizations and parameters. Is there a feasible way of benchmarking little programs on the linux command line (I know of time) with different parameters which gives me the time data as CSV or something similiar? Output could be something like:

Implementation      Time
A                    23s
B with -O3 2Threads  15s
B with -O3 4Threads  10s

I'm pretty sure that I've seen something like that on some professors slides but I cant remember who or when it was...

Body:
Why not using time command inside a bash script, something like :

#!/bin/bash

NPROG=`cat proglist | wc -l`
for i in `seq 1 ${NPROG}`
do
    PROG=`sed -n "${i}p" proglist`
    ARG=`sed -n "${i}p" arglist`
    TIME=`{ time ${PROG} ${ARG}; } 2>&1 | grep real | awk '{print $2}'`
    echo "${TIME} ${PROG} ${ARG}"
done

where proglist is a text file containing the programs to execute

A
B
B

and arglist is a text file containing the arguments, something like :

-a 1 -b 2
-f "foo"
-f "bar"

The output of the script will look-like :

 0m32.000s A -a 1 -b 2
 1m12.000s B -f "foo"
 5m38.000s B -f "bar"


问:
Can't update to rails 5 because of ruby version
I am planning to run ruby 2.3.1 version with Rails 5 on Mac OSX.

1 I installed rbenv then install ruby version 2.3.1.

```<code>rbenv version
2.3.1 (set by /D/testProject/.ruby-version)
</code>```

2 Update gem

```<code>gem update --system
Latest version currently installed. Aborting.
</code>```

3 System ruby version:

```<code>ruby -v
ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin15]
</code>```

But when i run gem update rails, i got

```<code>ERROR:  Error installing rails:
    activesupport requires Ruby version >= 2.2.2.
</code>```

So my question is how to make the gem update rails according to rbenv ruby version, not system version? Then i can update to Rails 5.

or

Do i have to update my system version of ruby to update to Rails5.

EDIT

I have ran rbenv local 2.3.1 (.ruby-version was created) already. But still can't update to Rails5
Thank you!

EDIT

```<code>which ruby
/usr/bin/ruby
</code>```

答:
Assuming you have already updated ruby using something like

sudo gem update --system

You can then set the rvm gemset lst to use the global version(s) installed.

```<code> rvm gemset list

 rvm gemset use global -save
</code>```

Body:
I am planning to run ruby 2.3.1 version with Rails 5 on Mac OSX.

1 I installed rbenv then install ruby version 2.3.1.

rbenv version
2.3.1 (set by /D/testProject/.ruby-version)

2 Update gem

gem update --system
Latest version currently installed. Aborting.

3 System ruby version:

ruby -v
ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin15]

But when i run gem update rails, i got

ERROR:  Error installing rails:
    activesupport requires Ruby version >= 2.2.2.

So my question is how to make the gem update rails according to rbenv ruby version, not system version? Then i can update to Rails 5.

or

Do i have to update my system version of ruby to update to Rails5.

EDIT

I have ran rbenv local 2.3.1 (.ruby-version was created) already. But still can't update to Rails5
Thank you!

EDIT

which ruby
/usr/bin/ruby

Body:
Assuming you have already updated ruby using something like

sudo gem update --system

You can then set the rvm gemset lst to use the global version(s) installed.

 rvm gemset list

 rvm gemset use global -save


问:
Cognito setDeviceStatusRemembered
I am trying to set up a remember me checkbox using Cognito below is what I am using currently but when I do this it gives out the error:

MissingRequiredParameter: Missing required key 'DeviceKey' in params

I am unsure what I am doing wrong this also happens on getDevice I tried this thinking it would give me the device key but I get the same error.

```<code>rememberDevice(callback: CognitoCallback){
    let cognitoUser = this.getCurrentUser();

    if (cognitoUser != null) {

        cognitoUser.getSession(function (err, session) {

            cognitoUser.setDeviceStatusRemembered({
                onSuccess: function (result) {
                    callback.cognitoCallback('Device Saved',result);
                },
                onFailure: function(err) {
                    alert(err);
                }
            });

        });

    }
    else{
        callback.cognitoCallback('Session Error','User not valid');
    }

}
</code>```

I can log in fine if I leave the checkbox unchecked.

答: This problem was the cognitoUser did not have a deivceKey value. first I added that manually to see it working then you can get the actual value from the access token</p>

Title: Cognito setDeviceStatusRemembered

Body:
I am trying to set up a remember me checkbox using Cognito below is what I am using currently but when I do this it gives out the error:

MissingRequiredParameter: Missing required key 'DeviceKey' in params

I am unsure what I am doing wrong this also happens on getDevice I tried this thinking it would give me the device key but I get the same error.

rememberDevice(callback: CognitoCallback){
    let cognitoUser = this.getCurrentUser();

    if (cognitoUser != null) {

        cognitoUser.getSession(function (err, session) {

            cognitoUser.setDeviceStatusRemembered({
                onSuccess: function (result) {
                    callback.cognitoCallback('Device Saved',result);
                },
                onFailure: function(err) {
                    alert(err);
                }
            });

        });

    }
    else{
        callback.cognitoCallback('Session Error','User not valid');
    }

}

I can log in fine if I leave the checkbox unchecked.


问:
Ansible: How do I get IP address from only FQDN in Ansible?
So, here's the setup.

I am passing a list of FQDN's via extra vars to the playbook, but the key of control machine are copied with their corresponding IP addresses. Also their is no specific group of these in the inventory.

The host for this playbook is a server which may or may not be part of this list that I am passing via extra vars. So, the playbook doesn't have facts of these nodes whatsoever.

So, my question is how do I get the IP addresses of the respective hosts on the fly so that I can loop over them to do some checks for some properties that I have set using their FQDN's via another playbook/ role previously. (Note: I strictly need FQDN's to set these said properties)

I have used delegate_to module, and passing FQDN's and it works but it asks if I want to continue connecting(yes/ no) and waits for user input for the initial run (if given yes, It works as expected). Is their any other simpler, cleaner way to solve this?
  (Note: Bare in mind I cannot modify the contents of inventory like putting alias etc)

Here is the snippet of the code:

```<code>- name: Checks
  become_user: hdfs
  shell: hdfs dfsadmin –report
  delegate_to: "{{ item.host_name }}"
  with_items:
    - "{{rackDetails}}"
</code>```

Here is the snippet of the master yml file where the above role is called :

```<code>- name: Checks for the property
  hosts: servernode
  roles:
    - Checks
</code>```

Inventory code snippet looks like this:

[servernode]

  10.0.2.15 ansible_ssh_user=grant ansible_ssh_pass=grant

  [all]

  10.0.2.15 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.16 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.17 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.18 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.19 ansible_ssh_user=grant ansible_ssh_pass=grant

And finally, this is what I am passing via extra vars:

```<code>{"rackDetails":[{"host_name":"prod_node1.paas.com","rack_name":"/rack1"},{"host_name":"prod_node2.paas.com","rack_name":"/rack2"},{"host_name":"prod_node3.paas.com","rack_name":"/rack3"}]}
</code>```

答:
What I think you want, instead, is to convert those to FQDN's into IP addresses and put them into the -l (limit) to a playbook:

```<code>ansible-playbook my_playbook -l $( getent hosts $( cat fqdns.txt ) | cut -d' ' -f1 | tr '\n' ',' )
</code>```

Body:
So, here's the setup.

I am passing a list of FQDN's via extra vars to the playbook, but the key of control machine are copied with their corresponding IP addresses. Also their is no specific group of these in the inventory.

The host for this playbook is a server which may or may not be part of this list that I am passing via extra vars. So, the playbook doesn't have facts of these nodes whatsoever.

So, my question is how do I get the IP addresses of the respective hosts on the fly so that I can loop over them to do some checks for some properties that I have set using their FQDN's via another playbook/ role previously. (Note: I strictly need FQDN's to set these said properties)

I have used delegate_to module, and passing FQDN's and it works but it asks if I want to continue connecting(yes/ no) and waits for user input for the initial run (if given yes, It works as expected). Is their any other simpler, cleaner way to solve this?
  (Note: Bare in mind I cannot modify the contents of inventory like putting alias etc)

Here is the snippet of the code:

- name: Checks
  become_user: hdfs
  shell: hdfs dfsadmin –report
  delegate_to: "{{ item.host_name }}"
  with_items:
    - "{{rackDetails}}"

Here is the snippet of the master yml file where the above role is called :

- name: Checks for the property
  hosts: servernode
  roles:
    - Checks

Inventory code snippet looks like this:

[servernode]

  10.0.2.15 ansible_ssh_user=grant ansible_ssh_pass=grant

  [all]

  10.0.2.15 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.16 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.17 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.18 ansible_ssh_user=grant ansible_ssh_pass=grant

  10.0.2.19 ansible_ssh_user=grant ansible_ssh_pass=grant

And finally, this is what I am passing via extra vars:

{"rackDetails":[{"host_name":"prod_node1.paas.com","rack_name":"/rack1"},{"host_name":"prod_node2.paas.com","rack_name":"/rack2"},{"host_name":"prod_node3.paas.com","rack_name":"/rack3"}]}

Body:
What I think you want, instead, is to convert those to FQDN's into IP addresses and put them into the -l (limit) to a playbook:

ansible-playbook my_playbook -l $( getent hosts $( cat fqdns.txt ) | cut -d' ' -f1 | tr '\n' ',' )


问:
F# build fails to locate two packages after updating mono
I have an existing F# / Mono / paket / fake project under Linux that used to compile correctly.

I updated mono using apt-get and now my project won't compile.

It can't find the two referenced packages : MathNet.Numerics and Newtonsoft.Json.

Here's what I'm getting when building the project:

```<code>Primary reference "MathNet.Numerics".
/usr/lib/mono/msbuild/15.0/bin/Microsoft.Common.CurrentVersion.targets(1980,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "MathNet.Numerics". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [/home/bleakcabal/Documents/projects/genesis/genesis/genesis/genesis.fsproj]
          For SearchPath "{TargetFrameworkDirectory}".
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.exe", but it didn't exist.
          For SearchPath "{GAC}".
          Considered "MathNet.Numerics", which was not found in the GAC.
          For SearchPath "{RawFileName}".
          Considered treating "MathNet.Numerics" as a file name, but it didn't exist.
          For SearchPath "/home/bleakcabal/Documents/projects/genesis/build/".
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.dll", but it didn't exist.
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.exe", but it didn't exist.
</code>```

The file resides in a packages folder in my project (which I created using Ionide-fsharp with VS code using paket and fake) but this folder is not appearing in the error message.

I am getting the exact same message for Newtonsoft.Json.

Here is my paket.dependencies file:

```<code>source https://www.nuget.org/api/v2

nuget FAKE
nuget FSharp.Core
nuget MathNet.Numerics
nuget Newtonsoft.Json
</code>```

My paket.lock file is too long to post but here are the relevant parts:

```<code>MathNet.Numerics (3.19)
      TaskParallelLibrary (>= 1.0.2856) - framework: net35

Newtonsoft.Json (10.0.2)
      Microsoft.CSharp (>= 4.3) - framework: netstandard10, >= netstandard13
      NETStandard.Library (>= 1.6.1) - framework: netstandard10, >= netstandard13
      System.ComponentModel.TypeConverter (>= 4.3) - framework: netstandard10, >= netstandard13
      System.Runtime.Serialization.Formatters (>= 4.3) - framework: >= netstandard13
      System.Runtime.Serialization.Primitives (>= 4.3) - framework: netstandard10, >= netstandard13
      System.Xml.XmlDocument (>= 4.3) - framework: >= netstandard13
</code>```

Here is an excerpt from one of my multiple .fsproj files that reference these packages:

```<code>...
<Reference Include="MathNet.Numerics" />
<Reference Include="Newtonsoft.Json" />
...
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.5'">
  <ItemGroup>
    <Reference Include="MathNet.Numerics">
      <HintPath>..\..\packages\MathNet.Numerics\lib\net35\MathNet.Numerics.dll</HintPath>
      <Private>True</Private>
      <Paket>True</Paket>
    </Reference>
  </ItemGroup>
</When>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
  <ItemGroup>
    <Reference Include="MathNet.Numerics">
      <HintPath>..\..\packages\MathNet.Numerics\lib\net40\MathNet.Numerics.dll</HintPath>
      <Private>True</Private>
      <Paket>True</Paket>
    </Reference>
  </ItemGroup>
</When>
</code>```

If I do mono --version I get the following:

```<code>Mono JIT compiler version 5.0.1.1 (2017-02/5077205 Thu May 25 09:16:53 UTC 2017)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
</code>```

I tried using the following commands but to no avail: .paket/paket.exe restore, .paket/paket.exe install, .paket/paket.exe outdated.

答:
To run paket, you will need to run

```<code>$ mono paket.exe install
</code>```

If you still have trouble with missing assemblies or wonky references, try either

```<code>$ apt-get install mono-dev
</code>```

or

```<code>$ apt-get install mono-complete
</code>```

For more info on Mono installation, take a look at http://www.mono-project.com/download/#download-lin

Body:
I have an existing F# / Mono / paket / fake project under Linux that used to compile correctly.

I updated mono using apt-get and now my project won't compile.

It can't find the two referenced packages : MathNet.Numerics and Newtonsoft.Json.

Here's what I'm getting when building the project:

Primary reference "MathNet.Numerics".
/usr/lib/mono/msbuild/15.0/bin/Microsoft.Common.CurrentVersion.targets(1980,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "MathNet.Numerics". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [/home/bleakcabal/Documents/projects/genesis/genesis/genesis/genesis.fsproj]
          For SearchPath "{TargetFrameworkDirectory}".
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/xbuild-frameworks/.NETFramework/v4.5/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.exe", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.dll", but it didn't exist.
          Considered "/usr/lib/mono/4.5-api/Facades/MathNet.Numerics.exe", but it didn't exist.
          For SearchPath "{GAC}".
          Considered "MathNet.Numerics", which was not found in the GAC.
          For SearchPath "{RawFileName}".
          Considered treating "MathNet.Numerics" as a file name, but it didn't exist.
          For SearchPath "/home/bleakcabal/Documents/projects/genesis/build/".
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.winmd", but it didn't exist.
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.dll", but it didn't exist.
          Considered "/home/bleakcabal/Documents/projects/genesis/build/MathNet.Numerics.exe", but it didn't exist.

The file resides in a packages folder in my project (which I created using Ionide-fsharp with VS code using paket and fake) but this folder is not appearing in the error message.

I am getting the exact same message for Newtonsoft.Json.

Here is my paket.dependencies file:

source https://www.nuget.org/api/v2

nuget FAKE
nuget FSharp.Core
nuget MathNet.Numerics
nuget Newtonsoft.Json

My paket.lock file is too long to post but here are the relevant parts:

MathNet.Numerics (3.19)
      TaskParallelLibrary (>= 1.0.2856) - framework: net35

Newtonsoft.Json (10.0.2)
      Microsoft.CSharp (>= 4.3) - framework: netstandard10, >= netstandard13
      NETStandard.Library (>= 1.6.1) - framework: netstandard10, >= netstandard13
      System.ComponentModel.TypeConverter (>= 4.3) - framework: netstandard10, >= netstandard13
      System.Runtime.Serialization.Formatters (>= 4.3) - framework: >= netstandard13
      System.Runtime.Serialization.Primitives (>= 4.3) - framework: netstandard10, >= netstandard13
      System.Xml.XmlDocument (>= 4.3) - framework: >= netstandard13

Here is an excerpt from one of my multiple .fsproj files that reference these packages:

...
<Reference Include="MathNet.Numerics" />
<Reference Include="Newtonsoft.Json" />
...
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.5'">
  <ItemGroup>
    <Reference Include="MathNet.Numerics">
      <HintPath>..\..\packages\MathNet.Numerics\lib\net35\MathNet.Numerics.dll</HintPath>
      <Private>True</Private>
      <Paket>True</Paket>
    </Reference>
  </ItemGroup>
</When>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
  <ItemGroup>
    <Reference Include="MathNet.Numerics">
      <HintPath>..\..\packages\MathNet.Numerics\lib\net40\MathNet.Numerics.dll</HintPath>
      <Private>True</Private>
      <Paket>True</Paket>
    </Reference>
  </ItemGroup>
</When>

If I do mono --version I get the following:

Mono JIT compiler version 5.0.1.1 (2017-02/5077205 Thu May 25 09:16:53 UTC 2017)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com

I tried using the following commands but to no avail: .paket/paket.exe restore, .paket/paket.exe install, .paket/paket.exe outdated.

Body:
To run paket, you will need to run

$ mono paket.exe install

If you still have trouble with missing assemblies or wonky references, try either

$ apt-get install mono-dev

or

$ apt-get install mono-complete

For more info on Mono installation, take a look at http://www.mono-project.com/download/#download-lin


问:
Makefile recompiling unchanged files
I'm attempting to get my Makefile(s) to only recompile when files have changed and it works brilliantly for the Java target, but not for JS. There aren't any errors reported, but when I run make bundle the second time around, it still re-runs all of those commands.

The output of running find ... manually seems to produce exactly what is expected, with no extra or missing lines.

```<code>JAVA_SRC_DIR := .
JAVA_SOURCES := $(shell find $(JAVA_SRC_DIR) -name '*.java' -o -name '*pom.xml')

JS_SRC_DIR := ./ui-bundle
JS_EXCLUDE := \(node_modules\|coverage\)
JS_SOURCES := $(shell find $(JS_SRC_DIR) -name '*.js' -o -name '*.jsx' -o -name '.babelrc' -o -name 'package.json' | grep -v $(JS_EXCLUDE) | grep -v -e '^$')

bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package

service: $(JAVA_SOURCES)
    mvn clean install -pl "!integration"
</code>```

I'm guessing this has something to do with it, but when I try to find what files make thinks has changed with make -d | grep "\(older\|newer\)" it doesn't find anything, but make -d concludes with:

```<code> Finished prerequisites of target file `bundle'.
 Must remake target `bundle'.
</code>```

Additionally make -d seems to try to run some sort of npm command.

Where am I going wrong?

答:
The problem is that bundle is just a name for the rule, and the rule doesn't actually build a file named "bundle". No matter how new or old the prerequisites are, when you make bundle, Make sees that no such file exists, deduces that it must be built, and executes the rule.

If you want Make to refrain from executing the rule when the prerequisites have not changed, you must give it something to compare them to. If you can identify some file that the rule always modifies, you can make that file the target. I can't suggest a candidate because I don't know what npm, jest and gulp do, but suppose it's jest_output:

```<code>jest_output: $(JS_SOURCES)
    ...
</code>```

Or you could have an actual file called bundle, which serves as a marker for Make, an empty file that has a name and modification time and nothing else:

```<code>bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package
    touch bundle
</code>```

Title: Makefile recompiling unchanged files

Body:
I'm attempting to get my Makefile(s) to only recompile when files have changed and it works brilliantly for the Java target, but not for JS. There aren't any errors reported, but when I run make bundle the second time around, it still re-runs all of those commands.

The output of running find ... manually seems to produce exactly what is expected, with no extra or missing lines.

JAVA_SRC_DIR := .
JAVA_SOURCES := $(shell find $(JAVA_SRC_DIR) -name '*.java' -o -name '*pom.xml')

JS_SRC_DIR := ./ui-bundle
JS_EXCLUDE := \(node_modules\|coverage\)
JS_SOURCES := $(shell find $(JS_SRC_DIR) -name '*.js' -o -name '*.jsx' -o -name '.babelrc' -o -name 'package.json' | grep -v $(JS_EXCLUDE) | grep -v -e '^$')

bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package

service: $(JAVA_SOURCES)
    mvn clean install -pl "!integration"

I'm guessing this has something to do with it, but when I try to find what files make thinks has changed with make -d | grep "\(older\|newer\)" it doesn't find anything, but make -d concludes with:

 Finished prerequisites of target file `bundle'.
 Must remake target `bundle'.

Additionally make -d seems to try to run some sort of npm command.

Where am I going wrong?

Body:
The problem is that bundle is just a name for the rule, and the rule doesn't actually build a file named "bundle". No matter how new or old the prerequisites are, when you make bundle, Make sees that no such file exists, deduces that it must be built, and executes the rule.

If you want Make to refrain from executing the rule when the prerequisites have not changed, you must give it something to compare them to. If you can identify some file that the rule always modifies, you can make that file the target. I can't suggest a candidate because I don't know what npm, jest and gulp do, but suppose it's jest_output:

jest_output: $(JS_SOURCES)
    ...

Or you could have an actual file called bundle, which serves as a marker for Make, an empty file that has a name and modification time and nothing else:

bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package
    touch bundle


问:
Why number at end of loop prints twice
I'm confused on the results of this code.

I can't grasp why it prints 0, 1, 2, 3, 4, 4

```<code>num = 10
for num in range(5):
    print(num)
print(num)
</code>```

答:
First you assigned num to 10
num = 10 then you loop through 0 to 4 using the range function range(5): Because you are still using the same variable num it will change the value of num for each iteration.

the last value of the iteration is 4 so its going to print 4 again since you are printing the value of num after the whole loop

Title: Why number at end of loop prints twice

Body:
I'm confused on the results of this code.

I can't grasp why it prints 0, 1, 2, 3, 4, 4

num = 10
for num in range(5):
    print(num)
print(num)


问:
draw one or more plots in the same window
I want compare two curves, it's possible with R to draw a plot and then draw another plot over it ? how ?

thanks.

答:
Have a look at par</p>

```<code>> ?par
> plot(rnorm(100))
> par(new=T)
> plot(rnorm(100), col="red")
</code>```

Body:
Have a look at par

> ?par
> plot(rnorm(100))
> par(new=T)
> plot(rnorm(100), col="red")


问:
Solving in quadratic time?
Consider the following question: We have 3 tables,

Theatre  ( theatre_Id, thatre_name )

ShowTime ( showTimeId,  theatre_Id, movie_id )

Movies   ( movie_id, movie_name )
Now same movie name can also have different movieId's sort of dependent on the reel.

Eg: [1, HarryPotter], [2, HarryPotter], [3, Pirates of Carr]

This question was answered before.
How to solve the following nested query?

答:
using the same formula with no regard of the logic but using EXISTS instead of IN</p>

```<code>select distinct movie_name
from Movies m
where EXISTS (
    select 1
    from ShowTime t
    where m.movie_id = t.movie_id
    group by movie_id
    having count(distinct theatre_Id) = (select count(*) from Theatre))
</code>```

Title: Solving in quadratic time?

Body:
using the same formula with no regard of the logic but using EXISTS instead of IN

select distinct movie_name
from Movies m
where EXISTS (
    select 1
    from ShowTime t
    where m.movie_id = t.movie_id
    group by movie_id
    having count(distinct theatre_Id) = (select count(*) from Theatre))


问:
Laravel Form::Model Binding - PUT/PATCH Update Routing not working
I have routes set up to to create a person record as follows:

```<code>Route::get('bodymaker/create', 'BodyMakerController@create')->name('bodymaker.create');
Route::post('bodymaker', 'BodyMakerController@store')->name('bodymaker.store');
Route::get('bodymaker/{id}/edit', 'BodyMakerController@edit')->name('bodymaker.edit');
Route::put('bodymaker/{id}/update', 'BodyMakerController@update')->name('bodymaker.update');
Route::patch('bodymaker/{id}', 'BodyMakerController@update')->name('bodymaker.update');
</code>```

The controller methods to generate a new record works properly and look like this:

```<code>public function create()
{
    return View::make('bodymaker.create');
}

public function store(Request $request)
{
    $person = new Person;

    $person->first_name = $request->first_name;
    $person->last_name = $request->last_name;
    $person->save();

    return View::make('person.store', ['person'=>$person]);
}
</code>```

NOW... my problem is getting the edit/update form to bind properly...

```<code>public function edit($id)
{
    $person = Person::findOrFail($id);

    return View::make('person.edit', ['person'=>$person]);
}

public function update($id)
{
// This route fails when I pass in the Request $request like in the store method.
//But how does the update method receive the form values differently than the store method(?)
    $person = Person::findOrFail($id);

    $person->first_name = $request->first_name;
    $person->last_name = $request->last_name;
    $person->save();

    return View::make('person.update', ['person'=>$person]);
}
</code>```

The form for the update looks like this

```<code>{{ Form::model($person, ['route' => ['person.edit', $person->id], 'method' => 'PUT'] }}

        {{ csrf_field() }}
        {!!  Form::text('first_name'), Input::old('first_name')  !!}
        {!!  Form::text('last_name'), Input::old('last_name')  !!}
        {!! Form::submit('Update Person') !!}

{!!  Form::close()  !!}
</code>```

I can't seem to get the form to update the record, only been able to generate a new record.  Something about the syntax for the Form::model binding that I'm not understanding. The PUT request is failing when I pass in the Request as an argument so I don't understand the difference between POST & PUT as used inside Laravel either, though I'm not sure that's my problem

Here is my artisan route:list

```<code>| web,auth |||GET|HEAD| bodymaker/{id}/edit  | bodymaker.edit  | App\Http\Controllers\BodyMakerController@edit
| web,auth |||PUT     | bodymaker/{id}/update| bodymaker.update| App\Http\Controllers\BodyMakerController@update
</code>```

答:
I guess you are a little bit confused. First of all, you should be clear about how routes and resource controller work.

You can find important information to your undestanding here:
Resource Controllers

You can try this:

routes.php

```<code>Route::put('bodymaker/{id}', 'BodyMakerController@update')->name('bodymaker.update');
</code>```

controller.php

```<code>public function update($id, Request $request)
{
    $person = Person::findOrFail($id);
    $person->update($request->all());

    return view('person.edit', compact('person'));
}
</code>```

form.blade.php

```<code>{!!Form::model($person,['url'=> ['bodymaker',$person->id],'method'=>'PUT'])!!}

.... your form

{!!Form::close()!!}
</code>```

As I can see you are only using the resource methods, therefore, I recommend to use a resourceful route with the same actions as listed in the link above, like this:

Route::resource('bodymaker', 'BodyMakerController');

Also, don't confuse the views (person) with the routes (bodymaker), because you're doing a mix of those.

Body:
I have routes set up to to create a person record as follows:

Route::get('bodymaker/create', 'BodyMakerController@create')->name('bodymaker.create');
Route::post('bodymaker', 'BodyMakerController@store')->name('bodymaker.store');
Route::get('bodymaker/{id}/edit', 'BodyMakerController@edit')->name('bodymaker.edit');
Route::put('bodymaker/{id}/update', 'BodyMakerController@update')->name('bodymaker.update');
Route::patch('bodymaker/{id}', 'BodyMakerController@update')->name('bodymaker.update');

The controller methods to generate a new record works properly and look like this:

public function create()
{
    return View::make('bodymaker.create');
}

public function store(Request $request)
{
    $person = new Person;

    $person->first_name = $request->first_name;
    $person->last_name = $request->last_name;
    $person->save();

    return View::make('person.store', ['person'=>$person]);
}

NOW... my problem is getting the edit/update form to bind properly...

public function edit($id)
{
    $person = Person::findOrFail($id);

    return View::make('person.edit', ['person'=>$person]);
}

public function update($id)
{
// This route fails when I pass in the Request $request like in the store method.
//But how does the update method receive the form values differently than the store method(?)
    $person = Person::findOrFail($id);

    $person->first_name = $request->first_name;
    $person->last_name = $request->last_name;
    $person->save();

    return View::make('person.update', ['person'=>$person]);
}

The form for the update looks like this

{{ Form::model($person, ['route' => ['person.edit', $person->id], 'method' => 'PUT'] }}

        {{ csrf_field() }}
        {!!  Form::text('first_name'), Input::old('first_name')  !!}
        {!!  Form::text('last_name'), Input::old('last_name')  !!}
        {!! Form::submit('Update Person') !!}

{!!  Form::close()  !!}

I can't seem to get the form to update the record, only been able to generate a new record.  Something about the syntax for the Form::model binding that I'm not understanding. The PUT request is failing when I pass in the Request as an argument so I don't understand the difference between POST & PUT as used inside Laravel either, though I'm not sure that's my problem

Here is my artisan route:list

| web,auth |||GET|HEAD| bodymaker/{id}/edit  | bodymaker.edit  | App\Http\Controllers\BodyMakerController@edit
| web,auth |||PUT     | bodymaker/{id}/update| bodymaker.update| App\Http\Controllers\BodyMakerController@update

Body:
I guess you are a little bit confused. First of all, you should be clear about how routes and resource controller work.

You can find important information to your undestanding here:
Resource Controllers

You can try this:

routes.php

Route::put('bodymaker/{id}', 'BodyMakerController@update')->name('bodymaker.update');

controller.php

public function update($id, Request $request)
{
    $person = Person::findOrFail($id);
    $person->update($request->all());

    return view('person.edit', compact('person'));
}

form.blade.php

{!!Form::model($person,['url'=> ['bodymaker',$person->id],'method'=>'PUT'])!!}

.... your form

{!!Form::close()!!}

As I can see you are only using the resource methods, therefore, I recommend to use a resourceful route with the same actions as listed in the link above, like this:

Route::resource('bodymaker', 'BodyMakerController');

Also, don't confuse the views (person) with the routes (bodymaker), because you're doing a mix of those.


问:
stop preventing HTML code rendering with Return and Die function in php
As you know in a php script when you call Return or Die it prevents the rest of HTML codes from rendering.

In an occasion when I just want to stop the php script but not whole the page what would I do?

Ex:

```<code><?php
if(!isset($_POST['txt_username']))
{
    echo "Please enter your username";
    return;
}
?>
<i want="this html">to be rendered</i>
</code>```

I want my HTML codes to be rendered afterward.
Thanks for reading.

答:
Use the conditional statement to include more PHP is needed. The HTML can then be rendered regardless of the PHP's if/else statement. Example:</p>

```<code><?php
if( !isset($_POST['txt_username']) )
{
 echo "Please enter your username";
}
else
{
    //Some dditional PHP functions
}
?>
<i want="this html">to be rendered</i>
</code>```

Body:
As you know in a php script when you call Return or Die it prevents the rest of HTML codes from rendering.

In an occasion when I just want to stop the php script but not whole the page what would I do?

Ex:

<?php
if(!isset($_POST['txt_username']))
{
    echo "Please enter your username";
    return;
}
?>
to be rendered

I want my HTML codes to be rendered afterward.
Thanks for reading.

Body:
Use the conditional statement to include more PHP is needed. The HTML can then be rendered regardless of the PHP's if/else statement. Example:

<?php
if( !isset($_POST['txt_username']) )
{
 echo "Please enter your username";
}
else
{
    //Some dditional PHP functions
}
?>
<i want="this html">to be rendered</i>


问:
Can anyone tell me how can I relate timegettime time with epochtime
I am working on a project where we are collecting data from various sensors and logging various logs.

Mostly all the sensors are logged using TimeGetTime in millisecs which is time measured from start time of PC. But I have one sensor that has data logged in epoch time which is in millisecs .

Now how can I relate the epoch time with TimeGetTime if I had to synchronize all sensor datas together?

答:
One way to convert the epoch time (I assume it's the number of milliseconds (ms) elapsed since [Wikipedia]: Unix time or ([MAN]: time)* 1000) to ms elapsed since Win started, you have to:

Get the number of ms since Win started, using (as you already mentioned) [MSDN]: timeGetTime function (as an alternative you could use [MSDN]: GetTickCount64 function; I didn't study the difference - in terms of precision - between the 2)

Get the current Win time, using [MSDN]: GetSystemTimeAsFileTime function

Since the time retrieved at previous step is (according to [MSDN]: FILETIME structure):

a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).

you need to convert it to Ux epoch style time. The conversion algorithm is quite straightforward, there are lots of examples on the web, here's one: [SO]: Convert Windows Filetime to second in Unix/Linux (since that result is in seconds, you'll need to multiply it by 1000). This represents the number of ms elapsed since Ux epoch time, til now

By subtracting the value from Step 1 (ms since Win started) from the one from Step 3 (ms since Ux epoch time), you'll get the number of ms between the Ux epoch time and the time Win started. This is the offset that you'll have to subtract from every timestamp that you get from the funky sensor, to be in sync with the timestamps got from all the other sensors.


问:
DOMDocument and UL tages
Folks, I'm trying to parse a HTML string and add a CDATA tag around any p tags, so
something
 would end up being
<!CDATA[
blah
]]
. This does what I want in that respect:

```<code>$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>';
$domdoc = new DOMDocument();
$domdoc->loadHTML($html_str);

foreach( $domdoc->getElementsByTagName("p") as $pnode ) {
    $cdata = $domdoc->createCDATASection('<p>'. $pnode->nodeValue .'</p>');
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0));
}
echo $domdoc->saveXML();
</code>```

The problem is there are some ul tags in the string that are not within p tags and I need to do the same thing with those; they need to be surrounded by CDATA within a p tag, like
<!CDATA[
blah
]]
.

I was hoping that I could just go through the string first and add a p tag in front of any ul and then just use the same above on a 2nd pass to get all the p tags to be within a CDATA, for example:

```<code>$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>';
$domdoc = new DOMDocument();
$domdoc->loadHTML($html_str);

foreach( $domdoc->getElementsByTagName("ul") as $ulnode ) {
    $cdata = $domdoc->createElement("p",$ulnode->nodeValue);
    $domdoc->replaceChild($cdata,$ulnode);
}

foreach( $domdoc->getElementsByTagName("p") as $pnode ) {
    $cdata = $domdoc->createCDATASection('<p>'. $pnode->nodeValue .'</p>');
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0));
}
echo $domdoc->saveXML();
</code>```

Obviously this didn't work, I ended up with just the content of the li items. Can I not do 2 passes like that or is it because the ul is a parent with children or something?

What I'm trying to end up with is this:

```<code><p><!CDATA[<p><strong>blah blah blah</strong></p>]]></p>
<p><!CDATA[<ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul>]]></p>
<p><!CDATA[<p>blah blah blah</p>]]></p>
</code>```

答:
First off all, you are trying to mix XML concepts with HTML, as <![CDATA[]]> is not a valid HTML construct. So, I think it's best to treat everything as XML. However, this mandates that your HTML fragment must be valid XML.

Then, since your HTML fragment does not have a root element, we use a DOMDocumentFragment (via DOMDocument::createDocumentFragment) to import the rootless fragment.

Then, we loop through the existing
 elements first, of course, because otherwise we would loop through the
 elements that we added, as well. Afterwards we loop through the existing
 elements.

As you noticed, DOMElement->nodeValue will merely give you the textContent of a node. So, instead, we use DOMDocument::saveXML( DOMNode $node ) to insert the XML string into the CDATA sections.

Lastly, we wrap our CDATA sections in newly created
 elements.

To wrap it all up, this is how you get your desired output:

$html_str = '
blah blah blah

blah blah blah

blah blah blah

blah blah blah

blah blah blah
';

$domdoc = new DOMDocument();

$domfrag = $domdoc->createDocumentFragment();
$domfrag->appendXML($html_str);

$domdoc->appendChild($domfrag);

foreach($domdoc->getElementsByTagName("p") as $pnode) {
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($pnode));
    $newPnode = $domdoc->createElement("p");
    $newPnode->appendChild($cdata);
    $pnode->parentNode->replaceChild($newPnode, $pnode);
}

foreach($domdoc->getElementsByTagName("ul") as $ulnode) {
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($ulnode));
    $newPnode = $domdoc->createElement("p");
    $newPnode->appendChild($cdata);
    $ulnode->parentNode->replaceChild($newPnode, $ulnode);
}

/**
 * unfortunately, LIBXML_NOXMLDECL is not supported
 * so $domdoc->saveXML( null, LIBXML_NOXMLDECL ) does not work
 * @see https://bugs.php.net/bug.php?id=50989
 */
echo $domdoc->saveXML();

/**
 * so, to drop the <?xml declaration line, you could do the following:
 */
foreach($domdoc->childNodes as $node) {
  echo $domdoc->saveXML($node) . PHP_EOL; // PHP_EOL is optional
}
```

You can view this example online.

Title: DOMDocument and UL tages

Body:
Folks, I'm trying to parse a HTML string and add a CDATA tag around any p tags, so
something
 would end up being
<!CDATA[
blah
]]
. This does what I want in that respect:

$html_str = '
blah blah blah

blah blah blah

blah blah blah

blah blah blah

blah blah blah
';
$domdoc = new DOMDocument();
$domdoc->loadHTML($html_str);

foreach( $domdoc->getElementsByTagName("p") as $pnode ) {
    $cdata = $domdoc->createCDATASection('
'. $pnode->nodeValue .'
');
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0));
}
echo $domdoc->saveXML();

The problem is there are some ul tags in the string that are not within p tags and I need to do the same thing with those; they need to be surrounded by CDATA within a p tag, like
<!CDATA[
blah
]]
.

I was hoping that I could just go through the string first and add a p tag in front of any ul and then just use the same above on a 2nd pass to get all the p tags to be within a CDATA, for example:

$html_str = '
blah blah blah

blah blah blah

blah blah blah

blah blah blah

blah blah blah
';
$domdoc = new DOMDocument();
$domdoc->loadHTML($html_str);

foreach( $domdoc->getElementsByTagName("ul") as $ulnode ) {
    $cdata = $domdoc->createElement("p",$ulnode->nodeValue);
    $domdoc->replaceChild($cdata,$ulnode);
}

foreach( $domdoc->getElementsByTagName("p") as $pnode ) {
    $cdata = $domdoc->createCDATASection('
'. $pnode->nodeValue .'
');
    $pnode->replaceChild($cdata, $pnode->childNodes->item(0));
}
echo $domdoc->saveXML();

Obviously this didn't work, I ended up with just the content of the li items. Can I not do 2 passes like that or is it because the ul is a parent with children or something?

What I'm trying to end up with is this:

<!CDATA[
blah blah blah
]]>

<!CDATA[

blah blah blah

blah blah blah

blah blah blah

]]>

<!CDATA[
blah blah blah
]]>

Body:
First off all, you are trying to mix XML concepts with HTML, as <![CDATA[]]> is not a valid HTML construct. So, I think it's best to treat everything as XML. However, this mandates that your HTML fragment must be valid XML.

Then, since your HTML fragment does not have a root element, we use a DOMDocumentFragment (via DOMDocument::createDocumentFragment) to import the rootless fragment.

Then, we loop through the existing <p> elements first, of course, because otherwise we would loop through the <p> elements that we added, as well. Afterwards we loop through the existing <ul> elements.

As you noticed, DOMElement->nodeValue will merely give you the textContent of a node. So, instead, we use DOMDocument::saveXML( DOMNode $node ) to insert the XML string into the CDATA sections.

Lastly, we wrap our CDATA sections in newly created <p> elements.

To wrap it all up, this is how you get your desired output:

$html_str = '<p><strong>blah blah blah</strong></p><ul><li>blah blah blah</li><li>blah blah blah</li><li>blah blah blah</li></ul><p>blah blah blah</p>';

$domdoc = new DOMDocument();

$domfrag = $domdoc->createDocumentFragment();
$domfrag->appendXML($html_str);

$domdoc->appendChild($domfrag);

foreach($domdoc->getElementsByTagName("p") as $pnode) {
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($pnode));
    $newPnode = $domdoc->createElement("p");
    $newPnode->appendChild($cdata);
    $pnode->parentNode->replaceChild($newPnode, $pnode);
}

foreach($domdoc->getElementsByTagName("ul") as $ulnode) {
    $cdata = $domdoc->createCDATASection($domdoc->saveXML($ulnode));
    $newPnode = $domdoc->createElement("p");
    $newPnode->appendChild($cdata);
    $ulnode->parentNode->replaceChild($newPnode, $ulnode);
}

/**
 * unfortunately, LIBXML_NOXMLDECL is not supported
 * so $domdoc->saveXML( null, LIBXML_NOXMLDECL ) does not work
 * @see https://bugs.php.net/bug.php?id=50989
 */
echo $domdoc->saveXML();

/**
 * so, to drop the <?xml declaration line, you could do the following:
 */
foreach($domdoc->childNodes as $node) {
  echo $domdoc->saveXML($node) . PHP_EOL; // PHP_EOL is optional
}

You can view this example online.


问:
Get image from Point Grey camera using PyCapture2 and OpenCV
I am trying to get image from Point Grey Camera using PyCapture2, provided by them as a python wrapper for FlyCapture2. I can take retrieve the image buffer but I am not able to get image as Mat datatype to be used in OpenCV.

For reference:

```<code>while not cv2.waitKey(100) & 0xFF == ord('q'):
    try:
        raw_object = camera.retrieveBuffer()
    except PyCapture2.Fc2error as fc2Err:
        print "Error retrieving buffer : ", fc2Err
        continue

    rgb_object = raw_object.convert(PyCapture2.PIXEL_FORMAT.BGR)
</code>```

How to convert this rgb_object into a Mat Image?

答:
This is what I did:

```<code>image = cam.retrieveBuffer()
row_bytes = float(len(image.getData()))/float(image.getRows());
cv_image = np.array(image.getData(), dtype="uint8").reshape( (image.getRows(), image.getCols()) );
cv2.imshow('frame',cv_image)
</code>```

And if you want color image:

```<code>color_cv_image = cv2.cvtColor(cv_image, cv2.COLOR_BAYER_BG2BGR)
</code>```

reference: http://answers.opencv.org/question/74788/point-grey-usb3-camera-pixel-color-format/

Body:
I am trying to get image from Point Grey Camera using PyCapture2, provided by them as a python wrapper for FlyCapture2. I can take retrieve the image buffer but I am not able to get image as Mat datatype to be used in OpenCV.

For reference:

while not cv2.waitKey(100) & 0xFF == ord('q'):
    try:
        raw_object = camera.retrieveBuffer()
    except PyCapture2.Fc2error as fc2Err:
        print "Error retrieving buffer : ", fc2Err
        continue

    rgb_object = raw_object.convert(PyCapture2.PIXEL_FORMAT.BGR)

How to convert this rgb_object into a Mat Image?

Body:
This is what I did:

image = cam.retrieveBuffer()
row_bytes = float(len(image.getData()))/float(image.getRows());
cv_image = np.array(image.getData(), dtype="uint8").reshape( (image.getRows(), image.getCols()) );
cv2.imshow('frame',cv_image)

And if you want color image:

color_cv_image = cv2.cvtColor(cv_image, cv2.COLOR_BAYER_BG2BGR)

reference: http://answers.opencv.org/question/74788/point-grey-usb3-camera-pixel-color-format/