text:
<?php

namespace Drupal\Tests\workflows\Functional;

use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;

/**
 * Tests workflow creation UI.
 *
 * @group workflows
 */
class WorkflowUiTest extends BrowserTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  protected static $modules = ['workflows', 'workflow_type_test', 'block'];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    // We're testing local actions.
    $this->drupalPlaceBlock('local_actions_block');
  }

  /**
   * Tests route access/permissions.
   */
  public function testAccess() {
    // Create a minimal workflow for testing.
    $workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_test', 'label' => 'Test']);
    $workflow
      ->getTypePlugin()
      ->addState('draft', 'Draft')
      ->addState('published', 'Published')
      ->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
    $workflow->save();

    $paths = [
      'admin/config/workflow/workflows',
      'admin/config/workflow/workflows/add',
      'admin/config/workflow/workflows/manage/test',
      'admin/config/workflow/workflows/manage/test/delete',
      'admin/config/workflow/workflows/manage/test/add_state',
      'admin/config/workflow/workflows/manage/test/state/published',
      'admin/config/workflow/workflows/manage/test/state/published/delete',
      'admin/config/workflow/workflows/manage/test/add_transition',
      'admin/config/workflow/workflows/manage/test/transition/publish',
      'admin/config/workflow/workflows/manage/test/transition/publish/delete',
    ];

    foreach ($paths as $path) {
      $this->drupalGet($path);
      // No access.
      $this->assertSession()->statusCodeEquals(403);
    }
    $this->drupalLogin($this->createUser(['administer workflows']));
    foreach ($paths as $path) {
      $this->drupalGet($path);
      // User has access.
      $this->assertSession()->statusCodeEquals(200);
    }

    // Ensure that default states can not be deleted.
    \Drupal::state()->set('workflow_type_test.required_states', ['published']);
    $this->drupalGet('admin/config/workflow/workflows/manage/test/state/published/delete');
    $this->assertSession()->statusCodeEquals(403);
    \Drupal::state()->set('workflow_type_test.required_states', []);

    // Delete one of the states and ensure the other test cannot be deleted.
    $this->drupalGet('admin/config/workflow/workflows/manage/test/state/published/delete');
    $this->submitForm([], 'Delete');
    $this->drupalGet('admin/config/workflow/workflows/manage/test/state/draft/delete');
    $this->assertSession()->statusCodeEquals(403);
  }

  /**
   * Tests the machine name validation of the state add form.
   */
  public function testStateMachineNameValidation() {
    Workflow::create([
      'id' => 'test_workflow',
      'type' => 'workflow_type_test',
    ])->save();

    $this->drupalLogin($this->createUser(['administer workflows']));

    $this->drupalGet('admin/config/workflow/workflows/manage/test_workflow/add_state');
    $this->submitForm([
      'label' => 'Test State',
      'id' => 'Invalid ID',
    ], 'Save');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('The machine-readable name must contain only lowercase letters, numbers, and underscores.');

    $this->drupalGet('admin/config/workflow/workflows/manage/test_workflow/add_transition');
    $this->submitForm([
      'label' => 'Test Transition',
      'id' => 'Invalid ID',
    ], 'Save');
    $this->assertSession()->pageTextContains('The machine-readable name must contain only lowercase letters, numbers, and underscores.');
  }

  /**
   * Tests the creation of a workflow through the UI.
   */
  public function testWorkflowCreation() {
    $workflow_storage = $this->container->get('entity_type.manager')->getStorage('workflow');
    /** @var \Drupal\workflows\WorkflowInterface $workflow */
    $this->drupalLogin($this->createUser(['access administration pages', 'administer workflows']));
    $this->drupalGet('admin/config/workflow');
    $this->assertSession()->linkByHrefExists('admin/config/workflow/workflows');
    $this->clickLink('Workflows');
    $this->assertSession()->pageTextContains('Workflows');
    $this->assertSession()->pageTextContains('There are no workflows yet.');
    $this->clickLink('Add workflow');
    $this->submitForm(['label' => 'Test', 'id' => 'test', 'workflow_type' => 'workflow_type_test'], 'Save');
    $this->assertSession()->pageTextContains('Created the Test Workflow.');
    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test/add_state');
    $this->drupalGet('/admin/config/workflow/workflows/manage/test');
    $this->assertSession()->pageTextContains('This workflow has no states and will be disabled until there is at least one, add a new state.');
    $this->assertSession()->pageTextContains('There are no states yet.');
    $this->clickLink('Add a new state');
    $this->submitForm(['label' => 'Published', 'id' => 'published'], 'Save');
    $this->assertSession()->pageTextContains('Created Published state.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertFalse($workflow->getTypePlugin()->getState('published')->canTransitionTo('published'), 'No default transition from published to published exists.');

    $this->clickLink('Add a new state');
    // Don't create a draft to draft transition by default.
    $this->submitForm(['label' => 'Draft', 'id' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('Created Draft state.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertFalse($workflow->getTypePlugin()->getState('draft')->canTransitionTo('draft'), 'Can not transition from draft to draft');

    $this->clickLink('Add a new transition');
    $this->submitForm(['id' => 'publish', 'label' => 'Publish', 'from[draft]' => 'draft', 'to' => 'published'], 'Save');
    $this->assertSession()->pageTextContains('Created Publish transition.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'), 'Can transition from draft to published');

    $this->clickLink('Add a new transition');
    $this->assertCount(2, $this->cssSelect('input[name="to"][type="radio"]'));
    $this->assertCount(0, $this->cssSelect('input[name="to"][checked="checked"][type="radio"]'));
    $this->submitForm(['id' => 'create_new_draft', 'label' => 'Create new draft', 'from[draft]' => 'draft', 'to' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('Created Create new draft transition.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('draft'), 'Can transition from draft to draft');

    // The fist state to edit on the page should be published.
    $this->clickLink('Edit');
    $this->assertSession()->fieldValueEquals('label', 'Published');
    // Change the label.
    $this->submitForm(['label' => 'Live'], 'Save');
    $this->assertSession()->pageTextContains('Saved Live state.');

    // Allow published to draft.
    $this->clickLink('Edit', 3);
    $this->submitForm(['from[published]' => 'published'], 'Save');
    $this->assertSession()->pageTextContains('Saved Create new draft transition.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertTrue($workflow->getTypePlugin()->getState('published')->canTransitionTo('draft'), 'Can transition from published to draft');

    // Try creating a duplicate transition.
    $this->clickLink('Add a new transition');
    $this->submitForm(['id' => 'create_new_draft', 'label' => 'Create new draft', 'from[published]' => 'published', 'to' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('The machine-readable name is already in use. It must be unique.');
    // Try creating a transition which duplicates the states of another.
    $this->submitForm(['id' => 'create_new_draft2', 'label' => 'Create new draft again', 'from[published]' => 'published', 'to' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('The transition from Live to Draft already exists.');

    // Create a new transition.
    $this->submitForm(['id' => 'save_and_publish', 'label' => 'Save and publish', 'from[published]' => 'published', 'to' => 'published'], 'Save');
    $this->assertSession()->pageTextContains('Created Save and publish transition.');
    // Edit the new transition and try to add an existing transition.
    $this->clickLink('Edit', 4);
    $this->submitForm(['from[draft]' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('The transition from Draft to Live already exists.');

    // Delete the transition.
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'published'), 'Can transition from published to published');
    $this->clickLink('Delete');
    $this->assertSession()->pageTextContains('Are you sure you want to delete Save and publish from Test?');
    $this->submitForm([], 'Delete');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'published'), 'Cannot transition from published to published');

    // Try creating a duplicate state.
    $this->drupalGet('admin/config/workflow/workflows/manage/test');
    $this->clickLink('Add a new state');
    $this->submitForm(['label' => 'Draft', 'id' => 'draft'], 'Save');
    $this->assertSession()->pageTextContains('The machine-readable name is already in use. It must be unique.');

    // Ensure that weight changes the state ordering.
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertEquals('published', $workflow->getTypePlugin()->getInitialState()->id());
    $this->drupalGet('admin/config/workflow/workflows/manage/test');
    $this->submitForm(['states[draft][weight]' => '-1'], 'Save');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertEquals('draft', $workflow->getTypePlugin()->getInitialState()->id());

    // Verify that we are still on the workflow edit page.
    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test');

    // Ensure that weight changes the transition ordering.
    $this->assertEquals(['publish', 'create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitions()));
    $this->drupalGet('admin/config/workflow/workflows/manage/test');
    $this->submitForm(['transitions[create_new_draft][weight]' => '-1'], 'Save');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTypePlugin()->getTransitions()));

    // Verify that we are still on the workflow edit page.
    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test');

    // Ensure that a delete link for the published state exists before deleting
    // the draft state.
    $published_delete_link = Url::fromRoute('entity.workflow.delete_state_form', [
      'workflow' => $workflow->id(),
      'workflow_state' => 'published',
    ])->toString();
    $draft_delete_link = Url::fromRoute('entity.workflow.delete_state_form', [
      'workflow' => $workflow->id(),
      'workflow_state' => 'draft',
    ])->toString();
    $this->assertSession()->elementContains('css', 'tr[data-drupal-selector="edit-states-published"]', 'Delete');
    $this->assertSession()->linkByHrefExists($published_delete_link);
    $this->assertSession()->linkByHrefExists($draft_delete_link);

    // Make the published state a default state and ensure it is no longer
    // linked.
    \Drupal::state()->set('workflow_type_test.required_states', ['published']);
    $this->getSession()->reload();
    $this->assertSession()->linkByHrefNotExists($published_delete_link);
    $this->assertSession()->linkByHrefExists($draft_delete_link);
    $this->assertSession()->elementNotContains('css', 'tr[data-drupal-selector="edit-states-published"]', 'Delete');
    \Drupal::state()->set('workflow_type_test.required_states', []);
    $this->getSession()->reload();
    $this->assertSession()->elementContains('css', 'tr[data-drupal-selector="edit-states-published"]', 'Delete');
    $this->assertSession()->linkByHrefExists($published_delete_link);
    $this->assertSession()->linkByHrefExists($draft_delete_link);

    // Delete the Draft state.
    $this->clickLink('Delete');
    $this->assertSession()->pageTextContains('Are you sure you want to delete Draft from Test?');
    $this->submitForm([], 'Delete');
    $this->assertSession()->pageTextContains('State Draft deleted.');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertFalse($workflow->getTypePlugin()->hasState('draft'), 'Draft state deleted');
    $this->assertTrue($workflow->getTypePlugin()->hasState('published'), 'Workflow still has published state');

    // The last state cannot be deleted so the only delete link on the page will
    // be for the workflow.
    $this->assertSession()->linkByHrefNotExists($published_delete_link);
    $this->clickLink('Delete');
    $this->assertSession()->pageTextContains('Are you sure you want to delete Test?');
    $this->submitForm([], 'Delete');
    $this->assertSession()->pageTextContains('Workflow Test deleted.');
    $this->assertSession()->pageTextContains('There are no workflows yet.');
    $this->assertNull($workflow_storage->loadUnchanged('test'), 'The test workflow has been deleted');

    // Ensure that workflow types with default configuration are initialized
    // correctly.
    $this->drupalGet('admin/config/workflow/workflows');
    $this->clickLink('Add workflow');
    $this->submitForm(['label' => 'Test 2', 'id' => 'test2', 'workflow_type' => 'workflow_type_required_state_test'], 'Save');
    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test2');
    $workflow = $workflow_storage->loadUnchanged('test2');
    $this->assertTrue($workflow->getTypePlugin()->hasState('fresh'), 'The workflow has the "fresh" state');
    $this->assertTrue($workflow->getTypePlugin()->hasState('rotten'), 'The workflow has the "rotten" state');
    $this->assertTrue($workflow->getTypePlugin()->hasTransition('rot'), 'The workflow has the "rot" transition');
    $this->assertSession()->pageTextContains('Fresh');
    $this->assertSession()->pageTextContains('Rotten');
  }

  /**
   * Tests the workflow configuration form.
   */
  public function testWorkflowConfigurationForm() {
    $workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test', 'label' => 'Test']);
    $workflow
      ->getTypePlugin()
      ->addState('published', 'Published')
      ->addTransition('publish', 'Publish', ['published'], 'published');
    $workflow->save();

    $this->drupalLogin($this->createUser(['administer workflows']));

    // Add additional information to the workflow via the configuration form.
    $this->drupalGet('admin/config/workflow/workflows/manage/test');
    $this->assertSession()->pageTextContains('Example global workflow setting');
    $this->submitForm(['type_settings[example_setting]' => 'Extra global settings'], 'Save');

    $workflow_storage = $this->container->get('entity_type.manager')->getStorage('workflow');
    $workflow = $workflow_storage->loadUnchanged('test');
    $this->assertEquals('Extra global settings', $workflow->getTypePlugin()->getConfiguration()['example_setting']);
  }

  /**
   * Tests a workflow, state, and transition can have a numeric ID and label.
   */
  public function testNumericIds() {
    $this->drupalLogin($this->createUser(['administer workflows']));
    $this->drupalGet('admin/config/workflow/workflows');
    $this->clickLink('Add workflow');
    $this->submitForm(['label' => 123, 'id' => 123, 'workflow_type' => 'workflow_type_complex_test'], 'Save');

    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/123/add_state');

    $this->submitForm(['label' => 456, 'id' => 456], 'Save');
    $this->assertSession()->pageTextContains('Created 456 state.');

    $this->clickLink('Add a new state');
    $this->submitForm(['label' => 789, 'id' => 789], 'Save');
    $this->assertSession()->pageTextContains('Created 789 state.');

    $this->clickLink('Add a new transition');
    $this->submitForm(['id' => 101112, 'label' => 101112, 'from[456]' => 456, 'to' => 789], 'Save');
    $this->assertSession()->pageTextContains('Created 101112 transition.');

    $workflow = $this->container->get('entity_type.manager')->getStorage('workflow')->loadUnchanged(123);
    $this->assertEquals(123, $workflow->id());
    $this->assertEquals(456, $workflow->getTypePlugin()->getState(456)->id());
    $this->assertEquals(101112, $workflow->getTypePlugin()->getTransition(101112)->id());
    $this->assertEquals(789, $workflow->getTypePlugin()->getTransition(101112)->to()->id());
  }

  /**
   * Tests the sorting of states and transitions by weight and label.
   */
  public function testSorting() {
    $workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test', 'label' => 'Test']);
    $workflow
      ->getTypePlugin()
      ->setConfiguration([
        'states' => [
          'two_a' => [
            'label' => 'two a',
            'weight' => 2,
          ],
          'three' => [
            'label' => 'three',
            'weight' => 3,
          ],
          'two_b' => [
            'label' => 'two b',
            'weight' => 2,
          ],
          'one' => [
            'label' => 'one',
            'weight' => 1,
          ],
        ],
        'transitions' => [
          'three' => [
            'label' => 'three',
            'from' => ['three'],
            'to' => 'three',
            'weight' => 3,
          ],
          'two_a' => [
            'label' => 'two a',
            'from' => ['two_a'],
            'to' => 'two_a',
            'weight' => 2,
          ],
          'one' => [
            'label' => 'one',
            'from' => ['one'],
            'to' => 'one',
            'weight' => 1,
          ],
          'two_b' => [
            'label' => 'two b',
            'from' => ['two_b'],
            'to' => 'two_b',
            'weight' => 2,
          ],
        ],
      ]);
    $workflow->save();

    $this->drupalLogin($this->createUser(['administer workflows']));
    $this->drupalGet('admin/config/workflow/workflows/manage/test');
    $expected_states = ['one', 'two a', 'two b', 'three'];
    $elements = $this->xpath('//details[@id="edit-states-container"]//table/tbody/tr');
    foreach ($elements as $key => $element) {
      $this->assertEquals($expected_states[$key], $element->find('xpath', 'td')->getText());
    }
    $expected_transitions = ['one', 'two a', 'two b', 'three'];
    $elements = $this->xpath('//details[@id="edit-transitions-container"]//table/tbody/tr');
    foreach ($elements as $key => $element) {
      $this->assertEquals($expected_transitions[$key], $element->find('xpath', 'td')->getText());
    }

    // Ensure that there are enough weights to satisfy the potential number of
    // states and transitions.
    $this->assertSession()
      ->selectExists('states[three][weight]')
      ->selectOption('2');
    $this->assertSession()
      ->selectExists('states[three][weight]')
      ->selectOption('-2');
    $this->assertSession()
      ->selectExists('transitions[three][weight]')
      ->selectOption('2');
    $this->assertSession()
      ->selectExists('transitions[three][weight]')
      ->selectOption('-2');
  }

}


text:
<component name="libraryTable">
  <library name="Maven: org.jboss.profileservice:jboss-profileservice-plugins:0.2.2">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/org/jboss/profileservice/jboss-profileservice-plugins/0.2.2/jboss-profileservice-plugins-0.2.2.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/org/jboss/profileservice/jboss-profileservice-plugins/0.2.2/jboss-profileservice-plugins-0.2.2-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/org/jboss/profileservice/jboss-profileservice-plugins/0.2.2/jboss-profileservice-plugins-0.2.2-sources.jar!/" />
    </SOURCES>
  </library>
</component>

redpajama_set_name: RedPajamaGithub


text:
package sgw

//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.
//
// Code generated by Alibaba Cloud SDK Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
)

// ModifyGatewayFileShare invokes the sgw.ModifyGatewayFileShare API synchronously
func (client *Client) ModifyGatewayFileShare(request *ModifyGatewayFileShareRequest) (response *ModifyGatewayFileShareResponse, err error) {
	response = CreateModifyGatewayFileShareResponse()
	err = client.DoAction(request, response)
	return
}

// ModifyGatewayFileShareWithChan invokes the sgw.ModifyGatewayFileShare API asynchronously
func (client *Client) ModifyGatewayFileShareWithChan(request *ModifyGatewayFileShareRequest) (<-chan *ModifyGatewayFileShareResponse, <-chan error) {
	responseChan := make(chan *ModifyGatewayFileShareResponse, 1)
	errChan := make(chan error, 1)
	err := client.AddAsyncTask(func() {
		defer close(responseChan)
		defer close(errChan)
		response, err := client.ModifyGatewayFileShare(request)
		if err != nil {
			errChan <- err
		} else {
			responseChan <- response
		}
	})
	if err != nil {
		errChan <- err
		close(responseChan)
		close(errChan)
	}
	return responseChan, errChan
}

// ModifyGatewayFileShareWithCallback invokes the sgw.ModifyGatewayFileShare API asynchronously
func (client *Client) ModifyGatewayFileShareWithCallback(request *ModifyGatewayFileShareRequest, callback func(response *ModifyGatewayFileShareResponse, err error)) <-chan int {
	result := make(chan int, 1)
	err := client.AddAsyncTask(func() {
		var response *ModifyGatewayFileShareResponse
		var err error
		defer close(result)
		response, err = client.ModifyGatewayFileShare(request)
		callback(response, err)
		result <- 1
	})
	if err != nil {
		defer close(result)
		callback(nil, err)
		result <- 0
	}
	return result
}

// ModifyGatewayFileShareRequest is the request struct for api ModifyGatewayFileShare
type ModifyGatewayFileShareRequest struct {
	*requests.RpcRequest
	CacheConfig   string `position:"Query" name:"CacheConfig"`
	SecurityToken string `position:"Query" name:"SecurityToken"`
	IndexId       string `position:"Query" name:"IndexId"`
	GatewayId     string `position:"Query" name:"GatewayId"`
}

// ModifyGatewayFileShareResponse is the response struct for api ModifyGatewayFileShare
type ModifyGatewayFileShareResponse struct {
	*responses.BaseResponse
	RequestId string `json:"RequestId" xml:"RequestId"`
	Success   bool   `json:"Success" xml:"Success"`
	Code      string `json:"Code" xml:"Code"`
	Message   string `json:"Message" xml:"Message"`
	TaskId    string `json:"TaskId" xml:"TaskId"`
}

// CreateModifyGatewayFileShareRequest creates a request to invoke ModifyGatewayFileShare API
func CreateModifyGatewayFileShareRequest() (request *ModifyGatewayFileShareRequest) {
	request = &ModifyGatewayFileShareRequest{
		RpcRequest: &requests.RpcRequest{},
	}
	request.InitWithApiInfo("sgw", "2018-05-11", "ModifyGatewayFileShare", "hcs_sgw", "openAPI")
	request.Method = requests.POST
	return
}

// CreateModifyGatewayFileShareResponse creates a response to parse from ModifyGatewayFileShare response
func CreateModifyGatewayFileShareResponse() (response *ModifyGatewayFileShareResponse) {
	response = &ModifyGatewayFileShareResponse{
		BaseResponse: &responses.BaseResponse{},
	}
	return
}


text:
add_library(Qt5::genericSensorPlugin MODULE IMPORTED)

_populate_Sensors_plugin_properties(genericSensorPlugin RELEASE "sensors/qtsensors_generic.dll")

list(APPEND Qt5Sensors_PLUGINS Qt5::genericSensorPlugin)


text:
<?php

/**
 * Created by PhpStorm.
 * User: Sven de Ronde
 * Date: 18-2-2017
 * Time: 18:07
 */

namespace AppBundle\Form;

use Doctrine\Common\Util\Debug;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Translation\TranslatorInterface;

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

class SubjectType extends AbstractType
{
    /**
     *
     * @var TranslatorInterface
     */
    private $translator;

    public function __construct(TranslatorInterface $translator) {
        $this->translator = $translator;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', TextType::class, array(
                'label' => 'Vak',
                'attr' => array('minlength' => 2),
                'required' => true,
            ))
            ->add('description', TextareaType::class, array(
                'label' => 'Omschrijving'
            ));
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Subject',
            'translation_domain' => 'form',
        ));
    }
}


text:
package glinks

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"runtime"
	"strings"
	"time"
)

// CpuInfo encapsulates CPU statistics.
// For individual data points each field is in the unit of Jiffies. Total is the sum of all fields
// When returned by CpuDelta, each field is a percentage of total Jiffies over the duration
type CpuInfo struct {
	User      int
	Nice      int
	System    int
	Idle      int
	IoWait    int
	Irq       int
	SoftIrq   int
	Steal     int
	Guest     int
	GuestNice int
	Total     int
}

// IntrInfo presents interrupts serviced since boot.  The total is for all interrupts, then Intrs are the values for
// each
type IntrInfo struct {
	Total int
	Intrs []int
}

// Data holds all values held by /proc/stats
type CpuData struct {
	Cpu          CpuInfo
	Processors   []CpuInfo
	Intr         IntrInfo
	Ctxt         int
	Btime        int
	Processes    int
	ProcsRunning int
	ProcsBlocked int
	SoftIrq      IntrInfo
	Time         time.Time
}

func (d CpuData) SampleTime() int64 {
	return d.Time.Unix()
}

// Data holds all values held by /proc/stats
type CpuDelta struct {
	Cpu          CpuInfo
	Processors   []CpuInfo
	Intr         IntrInfo
	Ctxt         int
	Btime        int
	Processes    int
	ProcsRunning int
	ProcsBlocked int
	SoftIrq      IntrInfo
	Duration     time.Duration
	Time         time.Time
}

func (d CpuDelta) SampleTime() int64 {
	return d.Time.Unix()
}

// loadIntr creates an IntrInfo from the line of text
func loadIntr(fields []string) IntrInfo {
	info := IntrInfo{
		Total: atoi(fields[1]),
		Intrs: make([]int, len(fields)-1, len(fields)),
	}
	for index, val := range fields[2:] {
		info.Intrs[index] = atoi(val)
	}
	return info

}

// loadCpu creates an CpuInfo from the line of text for either the total or individual CPU
func loadCpu(fields []string) CpuInfo {
	info := CpuInfo{Steal: 0, Guest: 0, GuestNice: 0}

	// compute total jiffies from sum of available fields
	total := 0
	for _, val := range fields[1:] {
		total += atoi(val)
	}

	// I'm assuming at least a 2.6.0 kernel
	info.Total = total
	info.User = atoi(fields[1])
	info.Nice = atoi(fields[2])
	info.System = atoi(fields[3])
	info.Idle = atoi(fields[4])
	info.IoWait = atoi(fields[5])
	info.Irq = atoi(fields[6])
	info.SoftIrq = atoi(fields[7])

	// supported by 2.6.11+
	if len(fields) > 8 {
		info.Steal = atoi(fields[8])
	}

	// supported by 2.6.24+
	if len(fields) > 9 {
		info.Guest = atoi(fields[9])
	}
	// supported by 2.6.33+
	if len(fields) > 10 {
		info.GuestNice = atoi(fields[10])
	}
	return info
}

// CpuLoad takes the data from /proc/stat and presents a usable data structure
func CpuLoad() CpuData {
	cpu_stat_file := "/proc/stat"

	file, err := os.Open(cpu_stat_file)

	// for testing on non-Linux OSes I have an example copied off a linux host
	if TESTING {
		if os.IsNotExist(err) {
			log.Print("Falling back to dummy data")
			file, err = os.Open(fmt.Sprintf("dummy_data/proc_stat.%d", TESTITR))
			TESTITR += 1
		}
	}
	defer file.Close()
	check(err)

	data := CpuData{Time: time.Now()}
	cpuCount := runtime.NumCPU()
	data.Processors = make([]CpuInfo, cpuCount, cpuCount*2)
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fields := strings.Fields(scanner.Text())
		switch {
		case fields[0] == "cpu":
			data.Cpu = loadCpu(fields)
		case strings.HasPrefix(fields[0], "cpu"):
			cpu_num := atoi(fields[0][3:])
			data.Processors[cpu_num] = loadCpu(fields)
		case fields[0] == "intr":
			data.Intr = loadIntr(fields)
		case fields[0] == "softirq":
			data.SoftIrq = loadIntr(fields)
		case fields[0] == "ctxt":
			data.Ctxt = atoi(fields[1])
		case fields[0] == "btime":
			data.Btime = atoi(fields[1])
		case fields[0] == "processes":
			data.Processes = atoi(fields[1])
		case fields[0] == "procs_running":
			data.ProcsRunning = atoi(fields[1])
		case fields[0] == "procs_blocked":
			data.ProcsBlocked = atoi(fields[1])
		}
	}

	check(scanner.Err())

	return data
}

// CpuDelta computes the difference between a first and second Data element
// second is assumed to be later in time than first
// CPU statistics are reported back as percentages of use rather than Jiffies
func CpuDiff(first CpuData, second CpuData) CpuDelta {
	diff := CpuDelta{Duration: second.Time.Sub(first.Time), Time: second.Time}
	diff.Cpu = deltaCpu(first.Cpu, second.Cpu)
	diff.Processors = make([]CpuInfo, len(second.Processors))
	for i := range second.Processors {
		_ = "breakpoint"
		diff.Processors[i] = deltaCpu(first.Processors[i], second.Processors[i])
	}
	diff.Intr = deltaIntr(first.Intr, second.Intr)
	diff.SoftIrq = deltaIntr(first.SoftIrq, second.SoftIrq)

	diff.Ctxt = second.Ctxt - first.Ctxt
	diff.Btime = second.Btime - first.Btime
	diff.Processes = second.Processes - first.Processes
	diff.ProcsRunning = second.ProcsRunning - first.ProcsRunning
	diff.ProcsBlocked = second.ProcsBlocked - first.ProcsBlocked
	if TESTING {
		TESTITR = 1
	}

	return diff
}

// deltaCpu computes percentage of use over time for each field
func deltaCpu(first CpuInfo, second CpuInfo) CpuInfo {
	diff := CpuInfo{}
	diff.Total = second.Total - first.Total
	diff.User = percent(first.User, second.User, diff.Total)
	diff.Nice = percent(first.Nice, second.Nice, diff.Total)
	diff.System = percent(first.System, second.System, diff.Total)
	diff.Idle = percent(first.Idle, second.Idle, diff.Total)
	diff.IoWait = percent(first.IoWait, second.IoWait, diff.Total)
	diff.Irq = percent(first.Irq, second.Irq, diff.Total)
	diff.SoftIrq = percent(first.SoftIrq, second.SoftIrq, diff.Total)
	diff.Steal = percent(first.Steal, second.Steal, diff.Total)
	diff.Guest = percent(first.Guest, second.Guest, diff.Total)
	diff.GuestNice = percent(first.GuestNice, second.GuestNice, diff.Total)

	return diff
}

func percent(first int, second int, total int) int {
	return int(float32(second-first) / float32(total) * 100.0)
}

// deltaIntr just calculates the difference in each field between two points in time
func deltaIntr(first IntrInfo, second IntrInfo) IntrInfo {
	diff := IntrInfo{}
	diff.Total = second.Total - first.Total
	diff.Intrs = make([]int, len(second.Intrs))
	for i := range second.Intrs {
		diff.Intrs[i] = second.Intrs[i] - first.Intrs[i]
	}
	return diff
}


text:
<?php

namespace Zimbra\Admin\Request;

/**
 * CreateCos request class
 * Create a class of service.
 *
 * @package    Zimbra
 * @subpackage Admin
 * @category   Request
 * @author     Nguyen Van Nguyen - nguyennv1981@gmail.com
 * @copyright  Copyright © 2013 by Nguyen Van Nguyen.
 */
class CreateCos extends BaseAttr
{
    /**
     * Constructor method for CreateCos
     * @param string $name The name
     * @param array  $attrs
     * @return self
     */
    public function __construct($name, array $attrs = [])
    {
        parent::__construct($attrs);
        $this->setChild('name', trim($name));
    }

    /**
     * Gets name
     *
     * @return string
     */
    public function getName()
    {
        return $this->getChild('name');
    }

    /**
     * Sets name
     *
     * @param  string $name
     * @return self
     */
    public function setName($name)
    {
        return $this->setChild('name', trim($name));
    }
}


text:
<!DOCTYPE html>

{% include head.html %}

    {% include header.html %}

        {{ content }}

  {% include footer.html %}


text:
{% extends "base.html" %}
{% block title %}{{ article.title|striptags }}{% endblock %}
{% block content %}

        {% include "article_header.html" %}

        {{ article.content }}

    {% if article.tags %}

{% for tag in article.tags %}

                {{ tag }}

{% endfor %}

    {% endif %}

    {% if DISQUS_SITENAME %}

    {% elif TWITTER_USERNAME %}

        Tweet

    {% endif %}

{% endblock %}


text:
SELECT
	contacts.ID,
	CONCAT_WS(
		' ',
		contacts.lastname,
		contacts.`name`,
		contacts.patronymic
	) AS fio,
	companies.title AS company,
	posts.title AS post
FROM
	contacts,
	companies,
	companycontactpost,
	posts
WHERE
	contacts.ID = companycontactpost.contact_id
AND companies.ID = companycontactpost.company_id
AND posts.ID = companycontactpost.post_id


text:
package org.spongepowered.common.mixin.api.minecraft.world;

import net.minecraft.world.level.LevelSimulatedRW;
import org.spongepowered.api.world.volume.game.GenerationVolume;
import org.spongepowered.asm.mixin.Mixin;

@Mixin(LevelSimulatedRW.class)
public interface IWorldGenerationReaderMixin_API extends GenerationVolume.Mutable {

}


text:
function HomeController(){
    console.log('Home component');
}

HomeController.$inject = [];

angular.module('demoApp.homeComponent', []).component('homeComponent', {
    templateUrl: 'home/home.component.html',
    controller: HomeController,
    controllerAs: "homeCtrl",
    require: {
        parent: '^rootComponent'
    },
    bindings: {}
});


text:
package api.web.gw2.mapping.v2.skills;

import api.web.gw2.mapping.core.ImplementationSpecific;
import api.web.gw2.mapping.v2.APIv2;

/**
 * Defines an attribute.
 * @author Fabrice Bouyé
 */
@APIv2(endpoint = "v2/skills")
public enum SkillAttribute {

    /**
     * Defines the condition damage attribute.
     */
    CONDITION_DAMAGE("ConditionDamage"), // NOI18N.
    /**
     * Defines the condition duration attribute.
     */
    CONDITION_DURATION("ConditionDuration"), // NOI18N.
    /**
     * Defines the ferocity attribute.
     */
    FEROCITY("CritDamage"), // NOI18N.
    /**
     * Defines the healing attribute.
     */
    HEALING("Healing"), // NOI18N.
    /**
     * Defines the power attribute.
     */
    POWER("Power"), // NOI18N.
    /**
     * Defines the precision attribute.
     */
    PRECISION("Precision"), // NOI18N.
    /**
     * Defines the thoughness attribute.
     */
    TOUGHNESS("Toughness"), // NOI18N.
    /**
     * Defines the vitality attribute.
     */
    VITALITY("Vitality"), // NOI18N.
    /**
     * Fail safe value.
     */
    @ImplementationSpecific
    UNKNOWN(null);

    final String value;

    private SkillAttribute(String value) {
        this.value = value;
    }
}


text:
import React, { Component } from 'react';
import { func, shape } from 'prop-types';
import { Alert, Platform, ScrollView, StyleSheet, View } from 'react-native';

import * as RNIap from 'react-native-iap';
import RNRestart from 'react-native-restart';
import store from 'react-native-simple-store';

import Header from '../../components/header';

import Row from './components/row';

import I18n from '../../utils/i18n';
import tracker from '../../utils/tracker';

import { config } from '../../config';

const productSkus = config.inAppProducts;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
  titleBlock: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingTop: Platform.OS === 'ios' ? 60 : 20,
    paddingHorizontal: 10,
    marginBottom: 20,
  },
  block: {
    paddingHorizontal: 10,
    paddingVertical: 30,
  },
  title: {
    fontSize: 24,
    color: 'black',
  },
});

const checkPurchaseHistory = async () => {
  try {
    tracker.logEvent('user-premium-restore-purchase-start');
    const purchaseHistory = await RNIap.getAvailablePurchases();
    console.log('getPurchaseHistory', purchaseHistory);

    if (purchaseHistory.length > 0) {
      for (const purchase of purchaseHistory) {
        if (config.inAppProducts.includes(purchase.productId)) {
          tracker.logEvent('user-premium-restore-purchase-done');
          return true;
        }
      }
    } else {
      tracker.logEvent('user-premium-restore-purchase-empty');
      return false;
    }
  } catch (err) {
    tracker.logEvent('user-premium-restore-purchase-error', err);
    console.warn(err);
    return false;
  }
};

export default class AdFree extends Component {
  state = {
    productList: [],
  };

  componentDidMount = async () => {
    await RNIap.initConnection();

    this.getProducts();
  };

  componentWillUnmount() {
    RNIap.endConnection();
  }

  getProducts = async () => {
    try {
      const products = await RNIap.getProducts(productSkus);
      console.log('getProducts', products);
      this.setState({
        productList: products.filter((i) => productSkus.includes(i.productId)),
      });
    } catch (err) {
      console.warn(err);
    }
  };

  buyProductItem = async (product) => {
    // {
    //   description: '',
    //   introductoryPrice: '',
    //   subscriptionPeriodNumberIOS: '0',
    //   introductoryPriceNumberOfPeriodsIOS: '',
    //   introductoryPriceSubscriptionPeriodIOS: '',
    //   productId: 'com.example.adfree',
    //   price: '1000',
    //   introductoryPricePaymentModeIOS: '',
    //   type: 'Do not use this. It returned sub only before',
    //   title: '',
    //   subscriptionPeriodUnitIOS: 'DAY',
    //   localizedPrice: 'HK$1000.00',
    //   currency: 'HKD'
    // }
    tracker.logEvent('user-premium-buy-product-start', product);
    try {
      console.log('buyProductItem:', product);
      const purchase = await RNIap.buyProduct(product.productId);

      console.info('Purchase result', purchase);
      // {
      //   transactionReceipt: 'xxx',
      //   transactionDate: 1545732911000,
      //   productId: '',
      //   transactionId: '1000000489738811'
      // }
      if (productSkus.includes(purchase.productId)) {
        tracker.logEvent('user-premium-buy-product-done', purchase);
        this.applyLifetimePurchase();
        this.restartForApplyingPurchase();
      }

      tracker.logPurchase(
        product.price.replace(',', '.'),
        product.currency,
        true,
        product.title,
        product.type,
        product.productId,
      );
    } catch (err) {
      if (err.code === 'E_ALREADY_OWNED') {
        this.applyLifetimePurchase();
        this.restartForApplyingPurchase();
      } else if (err.code === 'E_USER_CANCELLED') {
        // You are currently subscribed || cancelled
      } else if (err.code === 'E_UNKNOWN') {
        Alert.alert(err.code, err.message);
      }

      tracker.logEvent('user-premium-buy-product-error', err);
      tracker.logPurchase(
        product.price.replace(',', '.'),
        product.currency,
        false,
        product.title,
        product.type,
        product.productId,
      );
    }
  };

  applyLifetimePurchase = () => {
    store.save('adFreeUntil', Number.MAX_SAFE_INTEGER);
    store.save('currentSubscription', 'adfree');
  };

  restartForApplyingPurchase = () => {
    Alert.alert(
      I18n.t('adfree.purchase_success.title'),
      I18n.t('adfree.purchase_success.description'),
      [
        {
          text: 'OK',
          onPress: () => {
            tracker.logEvent('user-premium-restart');
            RNRestart.Restart();
          },
        },
      ],
      { cancelable: false },
    );
  };

  restorePurchase = async () => {
    const history = await checkPurchaseHistory(false);
    if (history) {
      this.applyLifetimePurchase();
      Alert.alert(
        I18n.t('adfree.restore_success.title'),
        I18n.t('adfree.restore_success.description'),
        [
          {
            text: 'OK',
            onPress: () => {
              tracker.logEvent('user-premium-restore-purchase-restart');
              RNRestart.Restart();
            },
          },
        ],
        { cancelable: false },
      );
    } else {
      Alert.alert(
        I18n.t('adfree.restore_failed.title'),
        null,
        [{ text: 'OK' }],
        { cancelable: false },
      );
    }
  };

  render() {
    const {
      navigation: { goBack },
    } = this.props;
    const { productList } = this.state;

    return (
      <View style={styles.container}>
        <Header title={I18n.t('adfree.title')} backOnPress={() => goBack()} />

        <ScrollView>
          {productList.length > 0 &&
            productList.map((product) => (
              <Row
                key={product.productId}
                title={`${I18n.t('adfree.product.title')} ${
                  product.localizedPrice
                }`}
                description={I18n.t('adfree.product.description')}
                onPress={() => this.buyProductItem(product)}
              />
            ))}

          <Row
            title={I18n.t('adfree.restore_purchase')}
            onPress={() => this.restorePurchase()}
          />
        </ScrollView>
      </View>
    );
  }
}

AdFree.propTypes = {
  navigation: shape({
    goBack: func.isRequired,
  }).isRequired,
};


text:
<?php
/**
 * Contains \jamesiarmes\PhpEws\Type\TaskRecurrenceType.
 */

namespace jamesiarmes\PhpEws\Type;

/**
 * Defines the recurrence pattern for recurring tasks.
 *
 * @package php-ews\Type
 *
 * @todo Implement TaskRecurrencePatternTypes trait.
 * @todo Implement RecurrenceRangeTypes trait.
 */
class TaskRecurrenceType extends RecurrenceType
{
    /**
     * Describes how many days after the completion of the current task the next
     * occurrence will be due.
     *
     * @since Exchange 2007
     *
     * @var \jamesiarmes\PhpEws\Type\DailyRegeneratingPatternType
     */
    public $DailyRegeneration;

    /**
     * Describes how many months after the completion of the current task the
     * next occurrence will be due.
     *
     * @since Exchange 2007
     *
     * @var \jamesiarmes\PhpEws\Type\MonthlyRegeneratingPatternType
     */
    public $MonthlyRegeneration;

    /**
     * Describes how many weeks after the completion of the current task the
     * next occurrence will be due.
     *
     * @since Exchange 2007
     *
     * @var \jamesiarmes\PhpEws\Type\WeeklyRegeneratingPatternType
     */
    public $WeeklyRegeneration;

    /**
     * Describes how many years after the completion of the current task the
     * next occurrence will be due.
     *
     * @since Exchange 2007
     *
     * @var \jamesiarmes\PhpEws\Type\YearlyRegeneratingPatternType
     */
    public $YearlyRegeneration;
}


text:
layout: default
description: ArangoDB will always start up with a default database, named _system
---
Database Names
==============

ArangoDB will always start up with a default database, named *_system*.
Users can create additional databases in ArangoDB, provided the database
names conform to the following constraints:

* Database names must only consist of the letters *a* to *z* (both lower and
  upper case allowed), the numbers *0* to *9*, and the underscore (*_*) or
  dash (*-*) symbols
  This also means that any non-ASCII database names are not allowed
* Database names must always start with a letter. Database names starting
  with an underscore are considered to be system databases, and users should
  not create or delete those
* The maximum allowed length of a database name is 64 bytes
* Database names are case-sensitive


text: Place sticky footer content here.


text:
package com.jhlabs.composite;

import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.RenderingHints;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

/**
 * A special Composite used for drawing "marching ants". It draws the ants at the 127 contour of the alpha channel of the source.
 * This can only be used on TYPE_INT_RGBA images.
 */
public final class ContourComposite implements Composite {

	private int offset;

	public ContourComposite( int offset ) {
		this.offset = offset;
	}

	public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
		return new ContourCompositeContext( offset, srcColorModel, dstColorModel );
	}

	public int hashCode() {
		return 0;
	}

	public boolean equals(Object o) {
		if (!(o instanceof ContourComposite))
			return false;
		return true;
	}

}

class ContourCompositeContext implements CompositeContext {

	private int offset;

	public ContourCompositeContext( int offset, ColorModel srcColorModel, ColorModel dstColorModel ) {
		this.offset = offset;
	}

	public void dispose() {
	}

	public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
		int x = src.getMinX();
		int y = src.getMinY();
		int w = src.getWidth();
		int h = src.getHeight();

		int[] srcPix = null;
		int[] srcPix2 = null;
		int[] dstInPix = null;
		int[] dstOutPix = new int[w*4];

		for ( int i = 0; i < h; i++ ) {
			srcPix = src.getPixels(x, y, w, 1, srcPix);
			dstInPix = dstIn.getPixels(x, y, w, 1, dstInPix);

			int lastAlpha = 0;
			int k = 0;
			for ( int j = 0; j < w; j++ ) {
				int alpha = srcPix[k+3];
				int alphaAbove = i != 0 ? srcPix2[k+3] : alpha;

				if ( i != 0 && j != 0 && ((alpha ^ lastAlpha) & 0x80) != 0 || ((alpha ^ alphaAbove) & 0x80) != 0 ) {
					if ((offset+i+j)%10 > 4) {
						dstOutPix[k] = 0x00;
						dstOutPix[k+1] = 0x00;
						dstOutPix[k+2] = 0x00;
					} else {
						dstOutPix[k] = 0xff;
						dstOutPix[k+1] = 0xff;
						dstOutPix[k+2] = 0x7f;
					}
					dstOutPix[k+3] = 0xff;
				} else {
					dstOutPix[k] = dstInPix[k];
					dstOutPix[k+1] = dstInPix[k+1];
					dstOutPix[k+2] = dstInPix[k+2];
//					if ( dstOut == dstIn )
						dstOutPix[k] = 0xff;
						dstOutPix[k+1] = 0;
						dstOutPix[k+2] = 0;
						dstOutPix[k+3] = 0;
//					else
//						dstOutPix[k+3] = dstInPix[k+3];
				}

				lastAlpha = alpha;
				k += 4;
			}

			dstOut.setPixels(x, y, w, 1, dstOutPix);

			int[] t = srcPix;
			srcPix = srcPix2;
			srcPix2 = t;
			y++;
		}
	}

}


text:
namespace engine {

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
const std::size_t HistoryManager::DEFAULT_HISTORY_SIZE = 10;

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
HistoryManager::HistoryManager() {
	_maxSize = 0;
	_currentPos = 0;
}

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
HistoryManager::HistoryManager(StackEngine &stackEngine) {
	init(stackEngine);
}

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
void HistoryManager::init(StackEngine &stackEngine) {
	_maxSize = DEFAULT_HISTORY_SIZE;
	_currentPos = 0;
	_history.clear();
	_history.push_front(
		Item(stackEngine.refStack(), stackEngine.refRegister())
	);
}

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
bool HistoryManager::undo(StackEngine &stackEngine) {
	if (_currentPos + 1 == _history.size()) {
		return true;
	}
	else {
		auto itr = _history.begin();
		++_currentPos;
		for (std::size_t ucnt = 0; ucnt < _currentPos; ++ucnt) {
			++itr;
		}
		stackEngine.refStack() = itr->stackVector;
		stackEngine.refRegister() = itr->registerVector;
	}
	return false;
}

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
bool HistoryManager::redo(StackEngine &stackEngine) {
	if (0 == _currentPos) {
		return true;
	}
	else {
		auto itr = _history.begin();
		--_currentPos;
		for (std::size_t ucnt = 0; ucnt < _currentPos; ++ucnt) {
			++itr;
		}
		stackEngine.refStack() = itr->stackVector;
		stackEngine.refRegister() = itr->registerVector;
	}
	return false;
}

////==--------------------------------------------------------------------====//
// STACK ENGINE HISTORY MANAGER
// [ Update ]
// Nov 19, 2016
//====--------------------------------------------------------------------==////
void HistoryManager::manage(StackEngine &stackEngine) {
	if (0 != _currentPos) {
		auto itr = _history.begin();
		for (std::size_t ucnt = 0; ucnt < _currentPos; ++ucnt) {
			++itr;
		}
		_history.erase(_history.begin(), itr);
	}
	_history.push_front(
		Item(stackEngine.refStack(), stackEngine.refRegister())
	);
	while (_history.size() > _maxSize + 1) {
		_history.pop_back();
	}
	_currentPos = 0;
}

} // namespace engine


text:
/*
 * Description:  This module simulates a basic DDR-style memory controller
 * (and can easily be extended to do FB-DIMM as well).
 *
 * This module models a single channel, connected to any number of
 * DIMMs with any number of ranks of DRAMs each.  If you want multiple
 * address/data channels, you need to instantiate multiple copies of
 * this module.
 *
 * Each memory request is placed in a queue associated with a specific
 * memory bank.  This queue is of finite size; if the queue is full
 * the request will back up in an (infinite) common queue and will
 * effectively throttle the whole system.  This sort of behavior is
 * intended to be closer to real system behavior than if we had an
 * infinite queue on each bank.  If you want the latter, just make
 * the bank queues unreasonably large.
 *
 * The head item on a bank queue is issued when all of the
 * following are true:
 *   the bank is available
 *   the address path to the DIMM is available
 *   the data path to or from the DIMM is available
 *
 * Note that we are not concerned about fixed offsets in time.  The bank
 * will not be used at the same moment as the address path, but since
 * there is no queue in the DIMM or the DRAM it will be used at a constant
 * number of cycles later, so it is treated as if it is used at the same
 * time.
 *
 * We are assuming closed bank policy; that is, we automatically close
 * each bank after a single read or write.  Adding an option for open
 * bank policy is for future work.
 *
 * We are assuming "posted CAS"; that is, we send the READ or WRITE
 * immediately after the ACTIVATE.  This makes scheduling the address
 * bus trivial; we always schedule a fixed set of cycles.  For DDR-400,
 * this is a set of two cycles; for some configurations such as
 * DDR-800 the parameter tRRD forces this to be set to three cycles.
 *
 * We assume a four-bit-time transfer on the data wires.  This is
 * the minimum burst length for DDR-2.  This would correspond
 * to (for example) a memory where each DIMM is 72 bits wide
 * and DIMMs are ganged in pairs to deliver 64 bytes at a shot.
 * This gives us the same occupancy on the data wires as on the
 * address wires (for the two-address-cycle case).
 *
 * The only non-trivial scheduling problem is the data wires.
 * A write will use the wires earlier in the operation than a read
 * will; typically one cycle earlier as seen at the DRAM, but earlier
 * by a worst-case round-trip wire delay when seen at the memory controller.
 * So, while reads from one rank can be scheduled back-to-back
 * every two cycles, and writes (to any rank) scheduled every two cycles,
 * when a read is followed by a write we need to insert a bubble.
 * Furthermore, consecutive reads from two different ranks may need
 * to insert a bubble due to skew between when one DRAM stops driving the
 * wires and when the other one starts.  (These bubbles are parameters.)
 *
 * This means that when some number of reads and writes are at the
 * heads of their queues, reads could starve writes, and/or reads
 * to the same rank could starve out other requests, since the others
 * would never see the data bus ready.
 * For this reason, we have implemented an anti-starvation feature.
 * A group of requests is marked "old", and a counter is incremented
 * each cycle as long as any request from that batch has not issued.
 * if the counter reaches twice the bank busy time, we hold off any
 * newer requests until all of the "old" requests have issued.
 *
 * We also model tFAW.  This is an obscure DRAM parameter that says
 * that no more than four activate requests can happen within a window
 * of a certain size.  For most configurations this does not come into play,
 * or has very little effect, but it could be used to throttle the power
 * consumption of the DRAM.  In this implementation (unlike in a DRAM
 * data sheet) TFAW is measured in memory bus cycles; i.e. if TFAW = 16
 * then no more than four activates may happen within any 16 cycle window.
 * Refreshes are included in the activates.
 *
 */

#include "base/cast.hh"
#include "base/cprintf.hh"
#include "base/random.hh"
#include "debug/RubyMemory.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/slicc_interface/NetworkMessage.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/structures/RubyMemoryControl.hh"
#include "mem/ruby/system/System.hh"

using namespace std;

// Value to reset watchdog timer to.
// If we're idle for this many memory control cycles,
// shut down our clock (our rescheduling of ourselves).
// Refresh shuts down as well.
// When we restart, we'll be in a different phase
// with respect to ruby cycles, so this introduces
// a slight inaccuracy.  But it is necessary or the
// ruby tester never terminates because the event
// queue is never empty.
#define IDLECOUNT_MAX_VALUE 1000

// Output operator definition

ostream&
operator<<(ostream& out, const RubyMemoryControl& obj)
{
    obj.print(out);
    out << flush;
    return out;
}

// ****************************************************************

// CONSTRUCTOR
RubyMemoryControl::RubyMemoryControl(const Params *p)
    : MemoryControl(p)
{
    m_banks_per_rank = p->banks_per_rank;
    m_ranks_per_dimm = p->ranks_per_dimm;
    m_dimms_per_channel = p->dimms_per_channel;
    m_bank_bit_0 = p->bank_bit_0;
    m_rank_bit_0 = p->rank_bit_0;
    m_dimm_bit_0 = p->dimm_bit_0;
    m_bank_queue_size = p->bank_queue_size;
    m_bank_busy_time = p->bank_busy_time;
    m_rank_rank_delay = p->rank_rank_delay;
    m_read_write_delay = p->read_write_delay;
    m_basic_bus_busy_time = p->basic_bus_busy_time;
    m_mem_ctl_latency = p->mem_ctl_latency;
    m_refresh_period = p->refresh_period;
    m_tFaw = p->tFaw;
    m_mem_random_arbitrate = p->mem_random_arbitrate;
    m_mem_fixed_delay = p->mem_fixed_delay;

    m_profiler_ptr = new MemCntrlProfiler(name(),
                                          m_banks_per_rank,
                                          m_ranks_per_dimm,
                                          m_dimms_per_channel);
}

void
RubyMemoryControl::init()
{
    m_msg_counter = 0;

    assert(m_tFaw <= 62); // must fit in a uint64 shift register

    m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
    m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel;
    m_refresh_period_system = m_refresh_period / m_total_banks;

    m_bankQueues = new list<MemoryNode *> [m_total_banks];
    assert(m_bankQueues);

    m_bankBusyCounter = new int [m_total_banks];
    assert(m_bankBusyCounter);

    m_oldRequest = new int [m_total_banks];
    assert(m_oldRequest);

    for (int i = 0; i < m_total_banks; i++) {
        m_bankBusyCounter[i] = 0;
        m_oldRequest[i] = 0;
    }

    m_busBusyCounter_Basic = 0;
    m_busBusyCounter_Write = 0;
    m_busBusyCounter_ReadNewRank = 0;
    m_busBusy_WhichRank = 0;

    m_roundRobin = 0;
    m_refresh_count = 1;
    m_need_refresh = 0;
    m_refresh_bank = 0;
    m_idleCount = 0;
    m_ageCounter = 0;

    // Each tfaw shift register keeps a moving bit pattern
    // which shows when recent activates have occurred.
    // m_tfaw_count keeps track of how many 1 bits are set
    // in each shift register.  When m_tfaw_count is >= 4,
    // new activates are not allowed.
    m_tfaw_shift = new uint64[m_total_ranks];
    m_tfaw_count = new int[m_total_ranks];
    for (int i = 0; i < m_total_ranks; i++) {
        m_tfaw_shift[i] = 0;
        m_tfaw_count[i] = 0;
    }
}

void
RubyMemoryControl::reset()
{
    m_msg_counter = 0;

    assert(m_tFaw <= 62); // must fit in a uint64 shift register

    m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel;
    m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel;
    m_refresh_period_system = m_refresh_period / m_total_banks;

    assert(m_bankQueues);

    assert(m_bankBusyCounter);

    assert(m_oldRequest);

    for (int i = 0; i < m_total_banks; i++) {
        m_bankBusyCounter[i] = 0;
        m_oldRequest[i] = 0;
    }

    m_busBusyCounter_Basic = 0;
    m_busBusyCounter_Write = 0;
    m_busBusyCounter_ReadNewRank = 0;
    m_busBusy_WhichRank = 0;

    m_roundRobin = 0;
    m_refresh_count = 1;
    m_need_refresh = 0;
    m_refresh_bank = 0;
    m_idleCount = 0;
    m_ageCounter = 0;

    // Each tfaw shift register keeps a moving bit pattern
    // which shows when recent activates have occurred.
    // m_tfaw_count keeps track of how many 1 bits are set
    // in each shift register.  When m_tfaw_count is >= 4,
    // new activates are not allowed.
    for (int i = 0; i < m_total_ranks; i++) {
        m_tfaw_shift[i] = 0;
        m_tfaw_count[i] = 0;
    }
}

RubyMemoryControl::~RubyMemoryControl()
{
    delete [] m_bankQueues;
    delete [] m_bankBusyCounter;
    delete [] m_oldRequest;
    delete m_profiler_ptr;
}

// enqueue new request from directory
void
RubyMemoryControl::enqueue(const MsgPtr& message, Cycles latency)
{
    Cycles arrival_time = curCycle() + latency;
    const MemoryMsg* memMess = safe_cast<const MemoryMsg*>(message.get());
    physical_address_t addr = memMess->getAddr().getAddress();
    MemoryRequestType type = memMess->getType();
    bool is_mem_read = (type == MemoryRequestType_MEMORY_READ);
    MemoryNode *thisReq = new MemoryNode(arrival_time, message, addr,
                                         is_mem_read, !is_mem_read);
    enqueueMemRef(thisReq);
}

// Alternate entry point used when we already have a MemoryNode
// structure built.
void
RubyMemoryControl::enqueueMemRef(MemoryNode *memRef)
{
    m_msg_counter++;
    memRef->m_msg_counter = m_msg_counter;
    physical_address_t addr = memRef->m_addr;
    int bank = getBank(addr);

    DPRINTF(RubyMemory,
            "New memory request%7d: %#08x %c arrived at %10d bank = %3x sched %c\n",
            m_msg_counter, addr, memRef->m_is_mem_read ? 'R':'W',
            memRef->m_time * g_system_ptr->clockPeriod(),
            bank, m_event.scheduled() ? 'Y':'N');

    m_profiler_ptr->profileMemReq(bank);
    m_input_queue.push_back(memRef);

    if (!m_event.scheduled()) {
        schedule(m_event, clockEdge());
    }
}

// dequeue, peek, and isReady are used to transfer completed requests
// back to the directory
void
RubyMemoryControl::dequeue()
{
    assert(isReady());
    MemoryNode *req = m_response_queue.front();
    m_response_queue.pop_front();
    delete req;
}

const Message*
RubyMemoryControl::peek()
{
    MemoryNode *node = peekNode();
    Message* msg_ptr = node->m_msgptr.get();
    assert(msg_ptr != NULL);
    return msg_ptr;
}

MemoryNode *
RubyMemoryControl::peekNode()
{
    assert(isReady());
    MemoryNode *req = m_response_queue.front();
    DPRINTF(RubyMemory, "Peek: memory request%7d: %#08x %c sched %c\n",
            req->m_msg_counter, req->m_addr, req->m_is_mem_read ? 'R':'W',
            m_event.scheduled() ? 'Y':'N');

    return req;
}

bool
RubyMemoryControl::isReady()
{
    return ((!m_response_queue.empty()) &&
            (m_response_queue.front()->m_time <= g_system_ptr->curCycle()));
}

void
RubyMemoryControl::setConsumer(Consumer* consumer_ptr)
{
    m_consumer_ptr = consumer_ptr;
}

void
RubyMemoryControl::print(ostream& out) const
{
}

// Queue up a completed request to send back to directory
void
RubyMemoryControl::enqueueToDirectory(MemoryNode *req, Cycles latency)
{
    Tick arrival_time = clockEdge(latency);
    Cycles ruby_arrival_time = g_system_ptr->ticksToCycles(arrival_time);
    req->m_time = ruby_arrival_time;
    m_response_queue.push_back(req);

    DPRINTF(RubyMemory, "Enqueueing msg %#08x %c back to directory at %15d\n",
            req->m_addr, req->m_is_mem_read ? 'R':'W', arrival_time);

    // schedule the wake up
    m_consumer_ptr->scheduleEventAbsolute(arrival_time);
}

// getBank returns an integer that is unique for each
// bank across this memory controller.
const int
RubyMemoryControl::getBank(const physical_address_t addr) const
{
    int dimm = (addr >> m_dimm_bit_0) & (m_dimms_per_channel - 1);
    int rank = (addr >> m_rank_bit_0) & (m_ranks_per_dimm - 1);
    int bank = (addr >> m_bank_bit_0) & (m_banks_per_rank - 1);
    return (dimm * m_ranks_per_dimm * m_banks_per_rank)
        + (rank * m_banks_per_rank)
        + bank;
}

const int
RubyMemoryControl::getRank(const physical_address_t addr) const
{
    int bank = getBank(addr);
    int rank = (bank / m_banks_per_rank);
    assert (rank < (m_ranks_per_dimm * m_dimms_per_channel));
    return rank;
}

// getRank returns an integer that is unique for each rank
// and independent of individual bank.
const int
RubyMemoryControl::getRank(int bank) const
{
    int rank = (bank / m_banks_per_rank);
    assert (rank < (m_ranks_per_dimm * m_dimms_per_channel));
    return rank;
}

// Not used!
const int
RubyMemoryControl::getChannel(const physical_address_t addr) const
{
    assert(false);
    return -1;
}

// Not used!
const int
RubyMemoryControl::getRow(const physical_address_t addr) const
{
    assert(false);
    return -1;
}

// queueReady determines if the head item in a bank queue
// can be issued this cycle
bool
RubyMemoryControl::queueReady(int bank)
{
    if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
        m_profiler_ptr->profileMemBankBusy();

        DPRINTF(RubyMemory, "bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
        return false;
    }

    if (m_mem_random_arbitrate >= 2) {
        if (random_mt.random(0, 100) < m_mem_random_arbitrate) {
            m_profiler_ptr->profileMemRandBusy();
            return false;
        }
    }

    if (m_mem_fixed_delay)
        return true;

    if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
        m_profiler_ptr->profileMemNotOld();
        return false;
    }

    if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
        // Another bank must have issued this same cycle.  For
        // profiling, we count this as an arb wait rather than a bus
        // wait.  This is a little inaccurate since it MIGHT have also
        // been blocked waiting for a read-write or a read-read
        // instead, but it's pretty close.
        m_profiler_ptr->profileMemArbWait(1);
        return false;
    }

    if (m_busBusyCounter_Basic > 0) {
        m_profiler_ptr->profileMemBusBusy();
        return false;
    }

    int rank = getRank(bank);
    if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
        m_profiler_ptr->profileMemTfawBusy();
        return false;
    }

    bool write = !m_bankQueues[bank].front()->m_is_mem_read;
    if (write && (m_busBusyCounter_Write > 0)) {
        m_profiler_ptr->profileMemReadWriteBusy();
        return false;
    }

    if (!write && (rank != m_busBusy_WhichRank)
        && (m_busBusyCounter_ReadNewRank > 0)) {
        m_profiler_ptr->profileMemDataBusBusy();
        return false;
    }

    return true;
}

// issueRefresh checks to see if this bank has a refresh scheduled
// and, if so, does the refresh and returns true
bool
RubyMemoryControl::issueRefresh(int bank)
{
    if (!m_need_refresh || (m_refresh_bank != bank))
        return false;
    if (m_bankBusyCounter[bank] > 0)
        return false;
    // Note that m_busBusyCounter will prevent multiple issues during
    // the same cycle, as well as on different but close cycles:
    if (m_busBusyCounter_Basic > 0)
        return false;
    int rank = getRank(bank);
    if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW)
        return false;

    // Issue it:
    DPRINTF(RubyMemory, "Refresh bank %3x\n", bank);

    m_profiler_ptr->profileMemRefresh();
    m_need_refresh--;
    m_refresh_bank++;
    if (m_refresh_bank >= m_total_banks)
        m_refresh_bank = 0;
    m_bankBusyCounter[bank] = m_bank_busy_time;
    m_busBusyCounter_Basic = m_basic_bus_busy_time;
    m_busBusyCounter_Write = m_basic_bus_busy_time;
    m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
    markTfaw(rank);
    return true;
}

// Mark the activate in the tFaw shift register
void
RubyMemoryControl::markTfaw(int rank)
{
    if (m_tFaw) {
        m_tfaw_shift[rank] |= (1 << (m_tFaw-1));
        m_tfaw_count[rank]++;
    }
}

// Issue a memory request: Activate the bank, reserve the address and
// data buses, and queue the request for return to the requesting
// processor after a fixed latency.
void
RubyMemoryControl::issueRequest(int bank)
{
    int rank = getRank(bank);
    MemoryNode *req = m_bankQueues[bank].front();
    m_bankQueues[bank].pop_front();

    DPRINTF(RubyMemory, "Mem issue request%7d: %#08x %c "
            "bank=%3x sched %c\n", req->m_msg_counter, req->m_addr,
            req->m_is_mem_read? 'R':'W',
            bank, m_event.scheduled() ? 'Y':'N');

    if (req->m_msgptr) {  // don't enqueue L3 writebacks
        enqueueToDirectory(req, Cycles(m_mem_ctl_latency + m_mem_fixed_delay));
    }
    m_oldRequest[bank] = 0;
    markTfaw(rank);
    m_bankBusyCounter[bank] = m_bank_busy_time;
    m_busBusy_WhichRank = rank;
    if (req->m_is_mem_read) {
        m_profiler_ptr->profileMemRead();
        m_busBusyCounter_Basic = m_basic_bus_busy_time;
        m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay;
        m_busBusyCounter_ReadNewRank =
            m_basic_bus_busy_time + m_rank_rank_delay;
    } else {
        m_profiler_ptr->profileMemWrite();
        m_busBusyCounter_Basic = m_basic_bus_busy_time;
        m_busBusyCounter_Write = m_basic_bus_busy_time;
        m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
    }
}

// executeCycle:  This function is called once per memory clock cycle
// to simulate all the periodic hardware.
void
RubyMemoryControl::executeCycle()
{
    // Keep track of time by counting down the busy counters:
    for (int bank=0; bank < m_total_banks; bank++) {
        if (m_bankBusyCounter[bank] > 0) m_bankBusyCounter[bank]--;
    }
    if (m_busBusyCounter_Write > 0)
        m_busBusyCounter_Write--;
    if (m_busBusyCounter_ReadNewRank > 0)
        m_busBusyCounter_ReadNewRank--;
    if (m_busBusyCounter_Basic > 0)
        m_busBusyCounter_Basic--;

    // Count down the tFAW shift registers:
    for (int rank=0; rank < m_total_ranks; rank++) {
        if (m_tfaw_shift[rank] & 1) m_tfaw_count[rank]--;
        m_tfaw_shift[rank] >>= 1;
    }

    // After time period expires, latch an indication that we need a refresh.
    // Disable refresh if in mem_fixed_delay mode.
    if (!m_mem_fixed_delay) m_refresh_count--;
    if (m_refresh_count == 0) {
        m_refresh_count = m_refresh_period_system;

        // Are we overrunning our ability to refresh?
        assert(m_need_refresh < 10);
        m_need_refresh++;
    }

    // If this batch of requests is all done, make a new batch:
    m_ageCounter++;
    int anyOld = 0;
    for (int bank=0; bank < m_total_banks; bank++) {
        anyOld |= m_oldRequest[bank];
    }
    if (!anyOld) {
        for (int bank=0; bank < m_total_banks; bank++) {
            if (!m_bankQueues[bank].empty()) m_oldRequest[bank] = 1;
        }
        m_ageCounter = 0;
    }

    // If randomness desired, re-randomize round-robin position each cycle
    if (m_mem_random_arbitrate) {
        m_roundRobin = random_mt.random(0, m_total_banks - 1);
    }

    // For each channel, scan round-robin, and pick an old, ready
    // request and issue it.  Treat a refresh request as if it were at
    // the head of its bank queue.  After we issue something, keep
    // scanning the queues just to gather statistics about how many
    // are waiting.  If in mem_fixed_delay mode, we can issue more
    // than one request per cycle.
    int queueHeads = 0;
    int banksIssued = 0;
    for (int i = 0; i < m_total_banks; i++) {
        m_roundRobin++;
        if (m_roundRobin >= m_total_banks) m_roundRobin = 0;
        issueRefresh(m_roundRobin);
        int qs = m_bankQueues[m_roundRobin].size();
        if (qs > 1) {
            m_profiler_ptr->profileMemBankQ(qs-1);
        }
        if (qs > 0) {
            // we're not idle if anything is queued
            m_idleCount = IDLECOUNT_MAX_VALUE;
            queueHeads++;
            if (queueReady(m_roundRobin)) {
                issueRequest(m_roundRobin);
                banksIssued++;
                if (m_mem_fixed_delay) {
                    m_profiler_ptr->profileMemWaitCycles(m_mem_fixed_delay);
                }
            }
        }
    }

    // memWaitCycles is a redundant catch-all for the specific
    // counters in queueReady
    m_profiler_ptr->profileMemWaitCycles(queueHeads - banksIssued);

    // Check input queue and move anything to bank queues if not full.
    // Since this is done here at the end of the cycle, there will
    // always be at least one cycle of latency in the bank queue.  We
    // deliberately move at most one request per cycle (to simulate
    // typical hardware).  Note that if one bank queue fills up, other
    // requests can get stuck behind it here.
    if (!m_input_queue.empty()) {
        // we're not idle if anything is pending
        m_idleCount = IDLECOUNT_MAX_VALUE;
        MemoryNode *req = m_input_queue.front();
        int bank = getBank(req->m_addr);
        if (m_bankQueues[bank].size() < m_bank_queue_size) {
            m_input_queue.pop_front();
            m_bankQueues[bank].push_back(req);
        }
        m_profiler_ptr->profileMemInputQ(m_input_queue.size());
    }
}

unsigned int
RubyMemoryControl::drain(DrainManager *dm)
{
    DPRINTF(RubyMemory, "MemoryController drain\n");
    if(m_event.scheduled()) {
        deschedule(m_event);
    }
    return 0;
}

// wakeup:  This function is called once per memory controller clock cycle.
void
RubyMemoryControl::wakeup()
{
    DPRINTF(RubyMemory, "MemoryController wakeup\n");
    // execute everything
    executeCycle();

    m_idleCount--;
    if (m_idleCount > 0) {
        assert(!m_event.scheduled());
        schedule(m_event, clockEdge(Cycles(1)));
    }
}

/**
 * This function reads the different buffers that exist in the Ruby Memory
 * Controller, and figures out if any of the buffers hold a message that
 * contains the data for the address provided in the packet. True is returned
 * if any of the messages was read, otherwise false is returned.
 *
 * I think we should move these buffers to being message buffers, instead of
 * being lists.
 */
bool
RubyMemoryControl::functionalReadBuffers(Packet *pkt)
{
    for (std::list<MemoryNode *>::iterator it = m_input_queue.begin();
         it != m_input_queue.end(); ++it) {
        Message* msg_ptr = (*it)->m_msgptr.get();
        if (msg_ptr->functionalRead(pkt)) {
            return true;
        }
    }

    for (std::list<MemoryNode *>::iterator it = m_response_queue.begin();
         it != m_response_queue.end(); ++it) {
        Message* msg_ptr = (*it)->m_msgptr.get();
        if (msg_ptr->functionalRead(pkt)) {
            return true;
        }
    }

    for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
        for (std::list<MemoryNode *>::iterator it = m_bankQueues[bank].begin();
             it != m_bankQueues[bank].end(); ++it) {
            Message* msg_ptr = (*it)->m_msgptr.get();
            if (msg_ptr->functionalRead(pkt)) {
                return true;
            }
        }
    }

    return false;
}

/**
 * This function reads the different buffers that exist in the Ruby Memory
 * Controller, and figures out if any of the buffers hold a message that
 * needs to functionally written with the data in the packet.
 *
 * The number of messages written is returned at the end. This is required
 * for debugging purposes.
 */
uint32_t
RubyMemoryControl::functionalWriteBuffers(Packet *pkt)
{
    uint32_t num_functional_writes = 0;

    for (std::list<MemoryNode *>::iterator it = m_input_queue.begin();
         it != m_input_queue.end(); ++it) {
        Message* msg_ptr = (*it)->m_msgptr.get();
        if (msg_ptr->functionalWrite(pkt)) {
            num_functional_writes++;
        }
    }

    for (std::list<MemoryNode *>::iterator it = m_response_queue.begin();
         it != m_response_queue.end(); ++it) {
        Message* msg_ptr = (*it)->m_msgptr.get();
        if (msg_ptr->functionalWrite(pkt)) {
            num_functional_writes++;
        }
    }

    for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
        for (std::list<MemoryNode *>::iterator it = m_bankQueues[bank].begin();
             it != m_bankQueues[bank].end(); ++it) {
            Message* msg_ptr = (*it)->m_msgptr.get();
            if (msg_ptr->functionalWrite(pkt)) {
                num_functional_writes++;
            }
        }
    }

    return num_functional_writes;
}

void
RubyMemoryControl::regStats()
{
    m_profiler_ptr->regStats();
}

RubyMemoryControl *
RubyMemoryControlParams::create()
{
    return new RubyMemoryControl(this);
}


text:
title: Kong Vitals
---

### Introduction

Vitals is a feature within Kong's Admin API and Kong Manager that provides
metrics about the health and performance of Kong nodes and Kong-proxied APIs.

## Requirements

- PostgresSQL 9.5+ or Cassandra 2.1+

## How to Enable and Disable Vitals

Kong Enterprise ships with Vitals enabled by default.

Vitals can be disabled (or re-enabled) in the configuration file (e.g kong.conf):

```bash
# via your Kong configuration file; e.g., kong.conf
vitals = on  # vitals is enabled
vitals = off # vitals is disabled
```

or by environment variables:

```bash
# or via environment variables
$ export KONG_VITALS=on
$ export KONG_VITALS=off
```

Kong must be restarted for these changes to take effect.

## Vitals Metrics

Vitals metrics fall into two categories:

- Health Metrics - for monitoring the health of a Kong cluster
- Traffic Metrics — for monitoring the usage of upstream services

Within these categories, Vitals collects the following metrics:

- [Health Metrics](#health-metrics)
  - [Latency](#latency)
    - [Proxy Latency (Request)](#proxy-latency-request)
    - [Upstream Latency](#upstream-latency)
  - [Datastore Cache](#datastore-cache)
    - [Datastore Cache Hit/Miss](#datastore-cache-hit-miss)
    - [Datastore Cache Hit Ratio](#datastore-cache-hit-ratio)
- [Traffic Metrics](#traffic-metrics)
  - [Request Counts](#request-counts)
    - [Total Requests](#total-requests)
    - [Requests per Consumer](#request-per-consumer)
  - [Status Codes](#status-code)
    - [Total Status Code Classes](#total-status-code-classes)
    - [Total Status Codes per Service](#total-status-codes-per-service)
    - [Total Status Codes per Route](#total-status-codes-per-route)
    - [Total Status Codes per Consumer](#total-status-codes-per-consumer)
    - [Total Status Codes per Consumer per Route](#total-status-codes-per-consumer-per-route)

All metrics are collected at 1-second intervals and aggregated into 1-minute
intervals. The 1-second intervals are retained for one hour. The 1-minute
intervals are retained for 25 hours.

If longer retention times are needed, the Vitals API can be used to pull metrics
out of Kong and into a data retention tool.

### Health Metrics

Health metrics give insight into the performance of a Kong cluster; for example,
how many requests it is processing and the latency on those requests.

Health metrics are tracked for each node in a cluster as well as for the cluster
as a whole. In Kong, a node is a running process with a unique identifier,
configuration, cache layout, and connections to both Kong's datastores and the
upstream APIs it proxies. Note that node identifiers are unique to the process,
and not to the host on which the process runs. In other words, each Kong restart
results in a new node, and therefore a new node ID.

#### Latency

The Vitals API may return null for Latency metrics—this occurs when no API
requests were proxied during the timeframe. Null latencies are not graphed in
Kong Manager—periods with null latencies appear as gaps in Vitals charts.

##### Proxy Latency (Request)

The Proxy Latency metrics are the min, max, and average values for the time, in milliseconds, that the Kong proxy spends processing API proxy requests. This includes time to execute plugins that run in the access phase as well as DNS lookup time. This does not include time spent in Kong's load balancer, time spent sending the request to the upstream, or time spent on the response.

These metrics are referenced in the Vitals API with the following labels: `latency_proxy_request_min_ms`, `latency_proxy_request_max_ms`, `latency_proxy_request_avg_ms`

Latency is not reported when a request is prematurely ended by Kong (e.g., bad auth, rate limited, etc.)—note that this differs from the "Total Requests" metric that does count such requests.

##### Upstream Latency

The Upstream Latency metrics are the min, max, and average values for the time elapsed, in milliseconds, between Kong sending requests upstream and Kong receiving the first bytes of responses from upstream.

These metrics are referenced in the Vitals API with the following labels: `latency_upstream_min_ms`, `latency_upstream_max_ms`, `latency_upstream_avg_ms`

#### Datastore Cache

##### Datastore Cache Hit/Miss

The Datastore Cache Hit/Miss metrics are the count of requests to Kong's node-level datastore cache. When Kong workers need configuration information to respond to a given API proxy request, they first check their worker-specific cache (also known as L1 cache), then if the information isn't available they check the node-wide datastore cache (also known as L2 cache). If neither cache contains the necessary information, Kong requests it from the datastore.

A "Hit" indicates that an entity was retrieved from the data store cache. A "Miss" indicates that the record had to be fetched from the datastore. Not every API request will result in datastore cache access—some entities will be retrieved from Kong's worker-specific cache memory.

These metrics are referenced in the Vitals API with the following labels: `cache_datastore_hits_total`, `cache_datastore_misses_total`

##### Datastore Cache Hit Ratio

This metric contains the ratio of datastore cache hits to the total count of datastore cache requests.

> Note: Datastore Cache Hit Ratio cannot be calculated for time indices with no hits and no misses.

### Traffic Metrics

Traffic metrics provide insight into which of your services are being used, and by whom, and how they are responding.

#### Request Counts

##### Total Requests

This metric is the count of all API proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, etc.

This metric is referenced in the Vitals API with the following label: `requests_proxy_total`

##### Requests Per Consumer

This metric is the count of all API proxy requests received from each specific consumer. Consumers are identified by credentials in their requests (e.g., API key, OAuth token, etc) as required by the Kong Auth plugin(s) in use.

This metric is referenced in the Vitals API with the following label: `requests_consumer_total`

#### Status Codes

##### Total Status Code Classes

This metric is the count of all status codes grouped by status code class (e.g. 4xx, 5xx).

This metric is referenced in the Vitals API with the following label: `status_code_classes_total`

##### Total Status Codes per Service

This metric is the total count of each specific status code for a given service.

This metric is referenced in the Vitals API with the following label: `status_codes_per_service_total`

##### Total Status Codes per Route

This metric is the total count of each specific status code for a given route.

This metric is referenced in the Vitals API with the following label: `status_codes_per_route_total`

##### Total Status Codes per Consumer

This metric is the total count of each specific status code for a given consumer.

This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_total`

##### Total Status Codes per Consumer Per Route

This metric is the total count of each specific status code for a given consumer and route.

This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_route_total`

## Vitals API

Vitals data is available via endpoints on Kong's Admin API. Access to these endpoints may be controlled via Admin API RBAC. The Vitals API is described in the attached OAS (Open API Spec, formerly Swagger) file [vitalsSpec.yaml][vitals_spec]

## Vitals Data Visualization in Kong Manager

Kong Manager includes visualization of Vitals data. Additional visualizations, dashboarding of Vitals data alongside data from other systems, etc., can be achieved using the Vitals API to integrate with common monitoring systems.

### Time Frame Control

A timeframe selector adjacent to Vitals charts in Kong Manager controls the timeframe of data visualized, which indirectly controls the granularity of the data. For example, the "Last 5 Minutes" choice will display 1-second resolution data, while longer time frames will show 1-minute resolution data.

Timestamps on the x-axis of Vitals charts are displayed either in the browser's local time zone, or in UTC, depending on the UTC option that appears adjacent to Vitals charts.

### Cluster and Node Data

Metrics can be displayed on Vitals charts at both node and cluster level. Controls are available to show cluster-wide metrics and/or node-specific metrics. Clicking on individual nodes will toggle the display of data from those nodes. Nodes can be identified by a unique Kong node identifier, by hostname, or by a combination of the two.

### Status Code Data

Visualizations of cluster-wide status code classes (1xx, 2xx, 3xx, 4xx, 5xx) can be found in the Status Codes page of Kong Manager. This page contains the counts of status code classes graphed over time, as well as the ratio of code classes to total requests. Note: this page does not include non-standard code classes (6xx, 7xx, etc.) Individual status code data can be viewed in the Consumer, Route, and Service details pages under the Activity tab. Both standard and non-standard status codes are visible in these views.

## Known Issues

Vitals data does not appear in Kong Manager or the Admin API.
First, make sure Vitals is enabled. (`vitals = on` in your Kong configuration).

Then, check your log files. If you see `[vitals] kong_vitals_requests_consumers cache is full` or `[vitals] error attempting to push to list: no memory`, then Vitals is no longer able to track requests because its cache is full. This condition may resolve itself if traffic to the node subsides long enough for it to work down the cache. Regardless, the node will continue to proxy requests as usual.

### Limitations in Cassandra 2.x

Vitals data is purged regularly: 1-second data is purged after one hour, and 1-minute data is purged after 25 hours. Due to limitations in Cassandra 2.x query options, the counter table vitals_consumers is not purged. If it becomes necessary to prune this table, you will need to do so manually.

[vitals_spec]: /enterprise/{{page.kong_version}}/admin-api/vitals/vitalsSpec.yaml