<commit_before>//===--- RequirementEnvironment.cpp - Requirement Environments ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the RequirementEnvironment class, which is used to
// capture how a witness to a protocol requirement maps type parameters.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/RequirementEnvironment.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/Statistic.h"

#define DEBUG_TYPE "Protocol conformance checking"

using namespace swift;

STATISTIC(NumRequirementEnvironments, "# of requirement environments");

RequirementEnvironment::RequirementEnvironment(
                                           DeclContext *conformanceDC,
                                           GenericSignature *reqSig,
                                           ProtocolDecl *proto,
                                           ClassDecl *covariantSelf,
                                           ProtocolConformance *conformance)
    : reqSig(reqSig) {
  ASTContext &ctx = conformanceDC->getASTContext();

  auto concreteType = conformanceDC->getSelfInterfaceType();
  auto *conformanceSig = conformanceDC->getGenericSignatureOfContext();

  // This is a substitution function from the generic parameters of the
  // conforming type to the synthetic environment.
  //
  // For structs, enums and protocols, this is a 1:1 mapping; for classes,
  // we increase the depth of each generic parameter by 1 so that we can
  // introduce a class-bound 'Self' parameter.
  //
  // This is a raw function rather than a substitution map because we need to
  // keep generic parameters as generic, even if the conformanceSig (the best
  // way to create the substitution map) equates them to concrete types.
  auto conformanceToSyntheticTypeFn = [&](SubstitutableType *type) {
    auto *genericParam = cast<GenericTypeParamType>(type);
    if (covariantSelf) {
      return GenericTypeParamType::get(genericParam->getDepth() + 1,
                                       genericParam->getIndex(), ctx);
    }

    return GenericTypeParamType::get(genericParam->getDepth(),
                                     genericParam->getIndex(), ctx);
  };
  auto conformanceToSyntheticConformanceFn =
      MakeAbstractConformanceForGenericType();

  auto substConcreteType = concreteType.subst(
      conformanceToSyntheticTypeFn, conformanceToSyntheticConformanceFn);

  // Calculate the depth at which the requirement's generic parameters
  // appear in the synthetic signature.
  unsigned depth = 0;
  if (covariantSelf) {
    depth++;
  }
  if (conformanceSig) {
    depth += conformanceSig->getGenericParams().back()->getDepth() + 1;
  }

  // Build a substitution map to replace the protocol's \c Self and the type
  // parameters of the requirement into a combined context that provides the
  // type parameters of the conformance context and the parameters of the
  // requirement.
  auto selfType = cast<GenericTypeParamType>(
      proto->getSelfInterfaceType()->getCanonicalType());

  reqToSyntheticEnvMap = SubstitutionMap::get(reqSig,
    [selfType, substConcreteType, depth, covariantSelf, &ctx]
    (SubstitutableType *type) -> Type {
      // If the conforming type is a class, the protocol 'Self' maps to
      // the class-constrained 'Self'. Otherwise, it maps to the concrete
      // type.
      if (type->isEqual(selfType)) {
        if (covariantSelf)
          return GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
        return substConcreteType;
      }
      // Other requirement generic parameters map 1:1 with their depth
      // increased appropriately.
      auto *genericParam = cast<GenericTypeParamType>(type);
      // In a protocol requirement, the only generic parameter at depth 0
      // should be 'Self', and all others at depth 1. Anything else is
      // invalid code.
      if (genericParam->getDepth() != 1)
        return Type();
      auto substGenericParam =
        GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
      return substGenericParam;
    },
    [selfType, substConcreteType, conformance, conformanceDC, &ctx](
        CanType type, Type replacement, ProtocolDecl *proto)
          -> Optional<ProtocolConformanceRef> {
      // The protocol 'Self' conforms concretely to the conforming type.
      if (type->isEqual(selfType)) {
        ProtocolConformance *specialized = conformance;
        if (conformance && conformance->getGenericSignature()) {
          auto concreteSubs =
            substConcreteType->getContextSubstitutionMap(
              conformanceDC->getParentModule(), conformanceDC);
          specialized =
            ctx.getSpecializedConformance(substConcreteType, conformance,
                                          concreteSubs);
        }

        if (specialized)
          return ProtocolConformanceRef(specialized);
      }

      // All other generic parameters come from the requirement itself
      // and conform abstractly.
      return ProtocolConformanceRef(proto);
    });

  // If the requirement itself is non-generic, the synthetic signature
  // is that of the conformance context.
  if (!covariantSelf &&
      reqSig->getGenericParams().size() == 1 &&
      reqSig->getRequirements().size() == 1) {
    syntheticSignature = conformanceDC->getGenericSignatureOfContext();
    if (syntheticSignature) {
      syntheticSignature = syntheticSignature->getCanonicalSignature();
      syntheticEnvironment =
        syntheticSignature->createGenericEnvironment();
    }

    return;
  }

  // Construct a generic signature builder by collecting the constraints
  // from the requirement and the context of the conformance together,
  // because both define the capabilities of the requirement.
  GenericSignatureBuilder builder(ctx);

  auto source =
    GenericSignatureBuilder::FloatingRequirementSource::forAbstract();

  // If the conforming type is a class, add a class-constrained 'Self'
  // parameter.
  if (covariantSelf) {
    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
    builder.addGenericParameter(paramTy);
  }

  // Now, add all generic parameters from the conforming type.
  if (conformanceSig) {
    for (auto param : conformanceSig->getGenericParams()) {
      auto substParam = Type(param).subst(conformanceToSyntheticTypeFn,
                                          conformanceToSyntheticConformanceFn);
      builder.addGenericParameter(substParam->castTo<GenericTypeParamType>());
    }
  }

  // Next, add requirements.
  if (covariantSelf) {
    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
    Requirement reqt(RequirementKind::Superclass, paramTy, substConcreteType);
    builder.addRequirement(reqt, source, nullptr);
  }

  if (conformanceSig) {
    for (auto &rawReq : conformanceSig->getRequirements()) {
      if (auto req = rawReq.subst(conformanceToSyntheticTypeFn,
                                  conformanceToSyntheticConformanceFn))
        builder.addRequirement(*req, source, nullptr);
    }
  }

  // Finally, add the generic parameters from the requirement.
  for (auto genericParam : reqSig->getGenericParams().slice(1)) {
    // The only depth that makes sense is depth == 1, the generic parameters
    // of the requirement itself. Anything else is from invalid code.
    if (genericParam->getDepth() != 1) {
      return;
    }

    // Create an equivalent generic parameter at the next depth.
    auto substGenericParam =
      GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);

    builder.addGenericParameter(substGenericParam);
  }

  ++NumRequirementEnvironments;

  // Next, add each of the requirements (mapped from the requirement's
  // interface types into the abstract type parameters).
  for (auto &rawReq : reqSig->getRequirements()) {
    if (auto req = rawReq.subst(reqToSyntheticEnvMap))
      builder.addRequirement(*req, source, conformanceDC->getParentModule());
  }

  // Produce the generic signature and environment.
  // FIXME: Pass in a source location for the conformance, perhaps? It seems
  // like this could fail.
  syntheticSignature =
    std::move(builder).computeGenericSignature(SourceLoc());
  syntheticEnvironment = syntheticSignature->createGenericEnvironment();
}
<commit_msg>Switch requirement environment over to the abstract generic signature request<commit_after>//===--- RequirementEnvironment.cpp - Requirement Environments ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the RequirementEnvironment class, which is used to
// capture how a witness to a protocol requirement maps type parameters.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/RequirementEnvironment.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/Statistic.h"

#define DEBUG_TYPE "Protocol conformance checking"

using namespace swift;

STATISTIC(NumRequirementEnvironments, "# of requirement environments");

RequirementEnvironment::RequirementEnvironment(
                                           DeclContext *conformanceDC,
                                           GenericSignature *reqSig,
                                           ProtocolDecl *proto,
                                           ClassDecl *covariantSelf,
                                           ProtocolConformance *conformance)
    : reqSig(reqSig) {
  ASTContext &ctx = conformanceDC->getASTContext();

  auto concreteType = conformanceDC->getSelfInterfaceType();
  auto *conformanceSig = conformanceDC->getGenericSignatureOfContext();

  // This is a substitution function from the generic parameters of the
  // conforming type to the synthetic environment.
  //
  // For structs, enums and protocols, this is a 1:1 mapping; for classes,
  // we increase the depth of each generic parameter by 1 so that we can
  // introduce a class-bound 'Self' parameter.
  //
  // This is a raw function rather than a substitution map because we need to
  // keep generic parameters as generic, even if the conformanceSig (the best
  // way to create the substitution map) equates them to concrete types.
  auto conformanceToSyntheticTypeFn = [&](SubstitutableType *type) {
    auto *genericParam = cast<GenericTypeParamType>(type);
    if (covariantSelf) {
      return GenericTypeParamType::get(genericParam->getDepth() + 1,
                                       genericParam->getIndex(), ctx);
    }

    return GenericTypeParamType::get(genericParam->getDepth(),
                                     genericParam->getIndex(), ctx);
  };
  auto conformanceToSyntheticConformanceFn =
      MakeAbstractConformanceForGenericType();

  auto substConcreteType = concreteType.subst(
      conformanceToSyntheticTypeFn, conformanceToSyntheticConformanceFn);

  // Calculate the depth at which the requirement's generic parameters
  // appear in the synthetic signature.
  unsigned depth = 0;
  if (covariantSelf) {
    depth++;
  }
  if (conformanceSig) {
    depth += conformanceSig->getGenericParams().back()->getDepth() + 1;
  }

  // Build a substitution map to replace the protocol's \c Self and the type
  // parameters of the requirement into a combined context that provides the
  // type parameters of the conformance context and the parameters of the
  // requirement.
  auto selfType = cast<GenericTypeParamType>(
      proto->getSelfInterfaceType()->getCanonicalType());

  reqToSyntheticEnvMap = SubstitutionMap::get(reqSig,
    [selfType, substConcreteType, depth, covariantSelf, &ctx]
    (SubstitutableType *type) -> Type {
      // If the conforming type is a class, the protocol 'Self' maps to
      // the class-constrained 'Self'. Otherwise, it maps to the concrete
      // type.
      if (type->isEqual(selfType)) {
        if (covariantSelf)
          return GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
        return substConcreteType;
      }
      // Other requirement generic parameters map 1:1 with their depth
      // increased appropriately.
      auto *genericParam = cast<GenericTypeParamType>(type);
      // In a protocol requirement, the only generic parameter at depth 0
      // should be 'Self', and all others at depth 1. Anything else is
      // invalid code.
      if (genericParam->getDepth() != 1)
        return Type();
      auto substGenericParam =
        GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
      return substGenericParam;
    },
    [selfType, substConcreteType, conformance, conformanceDC, &ctx](
        CanType type, Type replacement, ProtocolDecl *proto)
          -> Optional<ProtocolConformanceRef> {
      // The protocol 'Self' conforms concretely to the conforming type.
      if (type->isEqual(selfType)) {
        ProtocolConformance *specialized = conformance;
        if (conformance && conformance->getGenericSignature()) {
          auto concreteSubs =
            substConcreteType->getContextSubstitutionMap(
              conformanceDC->getParentModule(), conformanceDC);
          specialized =
            ctx.getSpecializedConformance(substConcreteType, conformance,
                                          concreteSubs);
        }

        if (specialized)
          return ProtocolConformanceRef(specialized);
      }

      // All other generic parameters come from the requirement itself
      // and conform abstractly.
      return ProtocolConformanceRef(proto);
    });

  // If the requirement itself is non-generic, the synthetic signature
  // is that of the conformance context.
  if (!covariantSelf &&
      reqSig->getGenericParams().size() == 1 &&
      reqSig->getRequirements().size() == 1) {
    syntheticSignature = conformanceDC->getGenericSignatureOfContext();
    if (syntheticSignature) {
      syntheticSignature = syntheticSignature->getCanonicalSignature();
      syntheticEnvironment =
        syntheticSignature->createGenericEnvironment();
    }

    return;
  }

  // Construct a generic signature by collecting the constraints
  // from the requirement and the context of the conformance together,
  // because both define the capabilities of the requirement.
  SmallVector<GenericTypeParamType *, 2> genericParamTypes;

  // If the conforming type is a class, add a class-constrained 'Self'
  // parameter.
  if (covariantSelf) {
    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
    genericParamTypes.push_back(paramTy);
  }

  // Now, add all generic parameters from the conforming type.
  if (conformanceSig) {
    for (auto param : conformanceSig->getGenericParams()) {
      auto substParam = Type(param).subst(conformanceToSyntheticTypeFn,
                                          conformanceToSyntheticConformanceFn);
      genericParamTypes.push_back(substParam->castTo<GenericTypeParamType>());
    }
  }

  // Next, add requirements.
  SmallVector<Requirement, 2> requirements;
  if (covariantSelf) {
    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
    Requirement reqt(RequirementKind::Superclass, paramTy, substConcreteType);
    requirements.push_back(reqt);
  }

  if (conformanceSig) {
    for (auto &rawReq : conformanceSig->getRequirements()) {
      if (auto req = rawReq.subst(conformanceToSyntheticTypeFn,
                                  conformanceToSyntheticConformanceFn))
        requirements.push_back(*req);
    }
  }

  // Finally, add the generic parameters from the requirement.
  for (auto genericParam : reqSig->getGenericParams().slice(1)) {
    // The only depth that makes sense is depth == 1, the generic parameters
    // of the requirement itself. Anything else is from invalid code.
    if (genericParam->getDepth() != 1) {
      return;
    }

    // Create an equivalent generic parameter at the next depth.
    auto substGenericParam =
      GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);

    genericParamTypes.push_back(substGenericParam);
  }

  ++NumRequirementEnvironments;

  // Next, add each of the requirements (mapped from the requirement's
  // interface types into the abstract type parameters).
  for (auto &rawReq : reqSig->getRequirements()) {
    if (auto req = rawReq.subst(reqToSyntheticEnvMap))
      requirements.push_back(*req);
  }

  // Produce the generic signature and environment.
  // FIXME: Pass in a source location for the conformance, perhaps? It seems
  // like this could fail.
  syntheticSignature = evaluateOrDefault(
      ctx.evaluator,
      AbstractGenericSignatureRequest{
        nullptr, std::move(genericParamTypes), std::move(requirements)},
      nullptr);
  syntheticEnvironment = syntheticSignature->createGenericEnvironment();
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>

using namespace boost;
using namespace std;

class rshell{
	protected:
		//Data Members
		string commands;
		string nextConnector;
		vector<string> commandlist;
		bool prevCommandPass;
		bool allCount;
		bool forceExit;
	public:
		//Constructor
		rshell(){
			commands = "";
			nextConnector = ";";
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
		}
		// Parses the string (strings ending in ';' will keep the ';')
		void parseAllCommands(){
			char_separator<char> delims(" ");
			tokenizer<char_separator<char> > tokenlist(commands, delims);
			for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
				string com(*i);
				commandlist.push_back(com);
			}
		}

		// Executes one command and sets prevCommandPass to true or false.
		void executeCommand(vector<string> com){
			char* argv[1024];
			pid_t p = getpid();
			pid_t pid = fork();
			int status;

			for(unsigned int i = 0; i < com.size(); i++){
				argv[i] = (char*)com.at(i).c_str();
			}
			argv[com.size()] = NULL;

			if (pid == 0){
				if (execvp(argv[0], argv)){
					prevCommandPass = true;
				}
				perror("execvp failed: ");
				prevCommandPass = false;
				_exit(1);
			}
			else if (pid > 0){
				if ((p = wait(&status)) < 0){
					perror("child failed: ");
					prevCommandPass = false;
					_exit(1);
				}
			}
			else{
				perror("fork failed: ");
				_exit(1);
			}
		}

		//Splits commandlist into commands with their arguments then calls executeCommand to run them.
		void executeAllCommands(){
			vector<string> commandsublist;
			unsigned int i = 0;
			unsigned int j = 0;
			while (i < commandlist.size()){
				j = 0;
				if (checkCommandRun()){
					while (!checkBreaker(i)){
						//Exit check
						if (commandlist.at(i) == "exit"){
							cout << "Forced Exit." << endl;
							forceExit = true;
							_Exit(0);
						}
						// Comment check
						if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
							executeCommand(commandsublist);
							return;
						}
						//Adds command to the list
						commandsublist.push_back(commandlist.at(i));
						i++;
						j++;
						if (i == commandlist.size()){
							executeCommand(commandsublist);
							return;
						}
					}
					if (checkBreaker(i)){
						if (nextConnector == "||"){
							if (allCount == true){
								prevCommandPass = true;
							}
							else{
								if (prevCommandPass == false){
									allCount = false;
								}
								else{
									allCount = true;
								}
							}
						}
						else if (nextConnector == "&&"){
							if (allCount == true){
								if (prevCommandPass == false){
									allCount = false;
								}
							}
							else{
								allCount = false;
								prevCommandPass = false;
							}
						}
						else if (nextConnector == ";"){
							allCount = true;
							prevCommandPass = true;
						}
						nextConnector = commandlist.at(i);
					}
					i++;
				}
				executeCommand(commandsublist);
				commandsublist.clear();
			}
		}

		//	Checks if there is a '#' at the front of the string
		bool checkComment(string str){
			if (str.at(0) == '#'){
				return true;
			}
			return false
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if (i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				else{
					return false;
				}
			}
			else
				return false;
			}
		}

		// Checks if the next command should be run
		bool checkCommandRun(){
			if (nextConnector == "||"){
				if(allCount == true){
					return false;
				}
				else{
					return true;
				}
			}
			else if (nextConnector == "&&"){
				if(allCount == true){
					return true;
				}
				else{
					return false;
				}
			}
			else if (nextConnector == ";"){
				return true;
			}
			else{
				return false;
			}
		}

		//Starts the program.
		void run(){
			while (!forceExit && commands != "exit"){
				cout << "$";
				getline(cin, commands);
				parseAllCommands();
				executeAllCommands();
				commandlist.clear();
				nextConnector = ";";
				prevCommandPass = true;
			}
		}
};
<commit_msg>tiny tiny change<commit_after>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>

using namespace boost;
using namespace std;

class rshell{
	protected:
		//Data Members
		string commands;
		string nextConnector;
		vector<string> commandlist;
		bool prevCommandPass;
		bool allCount;
		bool forceExit;
	public:
		//Constructor
		rshell(){
			commands = "";
			nextConnector = ";";
			prevCommandPass = true;
			forceExit = false;
			allCount = true;
		}

		// Parses the string (strings ending in ';' will keep the ';')
		void parseAllCommands(){
			char_separator<char> delims(" ");
			tokenizer<char_separator<char> > tokenlist(commands, delims);
			for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
				string com(*i);
				commandlist.push_back(com);
			}
		}

		// Executes one command and sets prevCommandPass to true or false.
		void executeCommand(vector<string> com){
			char* argv[1024];
			pid_t p = getpid();
			pid_t pid = fork();
			int status;

			for(unsigned int i = 0; i < com.size(); i++){
				argv[i] = (char*)com.at(i).c_str();
			}
			argv[com.size()] = NULL;

			if (pid == 0){
				if (execvp(argv[0], argv)){
					prevCommandPass = true;
				}
				perror("execvp failed: ");
				prevCommandPass = false;
				_exit(1);
			}
			else if (pid > 0){
				if ((p = wait(&status)) < 0){
					perror("child failed: ");
					prevCommandPass = false;
					_exit(1);
				}
			}
			else{
				perror("fork failed: ");
				_exit(1);
			}
		}

		//Splits commandlist into commands with their arguments then calls executeCommand to run them.
		void executeAllCommands(){
			vector<string> commandsublist;
			unsigned int i = 0;
			unsigned int j = 0;
			while (i < commandlist.size()){
				j = 0;
				if (checkCommandRun()){
					while (!checkBreaker(i)){
						//Exit check
						if (commandlist.at(i) == "exit"){
							cout << "Forced Exit." << endl;
							forceExit = true;
							_Exit(0);
						}
						// Comment check
						if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
							executeCommand(commandsublist);
							return;
						}
						//Adds command to the list
						commandsublist.push_back(commandlist.at(i));
						i++;
						j++;
						if (i == commandlist.size()){
							executeCommand(commandsublist);
							return;
						}
					}
					if (checkBreaker(i)){
						if (nextConnector == "||"){
							if (allCount == true){
								prevCommandPass = true;
							}
							else{
								if (prevCommandPass == false){
									allCount = false;
								}
								else{
									allCount = true;
								}
							}
						}
						else if (nextConnector == "&&"){
							if (allCount == true){
								if (prevCommandPass == false){
									allCount = false;
								}
							}
							else{
								allCount = false;
								prevCommandPass = false;
							}
						}
						else if (nextConnector == ";"){
							allCount = true;
							prevCommandPass = true;
						}
						nextConnector = commandlist.at(i);
					}
					i++;
				}
				executeCommand(commandsublist);
				commandsublist.clear();
			}
		}

		//	Checks if there is a '#' at the front of the string
		bool checkComment(string str){
			if (str.at(0) == '#'){
				return true;
			}
			return false
		}

		//	Checks if the string is a breaker
		bool checkBreaker(int i){
			if (i < commandlist.size() + 1){
				if (commandlist.at(i) == "|" && commandlist.at(i + 1) == "|"){
					return true;
				}
				else if (commandlist.at(i) == "&" && commandlist.at(i + 1) == "&"){
					return true;
				}
				else if (commandlist.at(i) == ";"){
					return true;
				else{
					return false;
				}
			}
			else
				return false;
			}
		}

		// Checks if the next command should be run
		bool checkCommandRun(){
			if (nextConnector == "||"){
				if(allCount == true){
					return false;
				}
				else{
					return true;
				}
			}
			else if (nextConnector == "&&"){
				if(allCount == true){
					return true;
				}
				else{
					return false;
				}
			}
			else if (nextConnector == ";"){
				return true;
			}
			else{
				return false;
			}
		}

		//Starts the program.
		void run(){
			while (!forceExit && commands != "exit"){
				cout << "$";
				getline(cin, commands);
				parseAllCommands();
				executeAllCommands();
				commandlist.clear();
				nextConnector = ";";
				prevCommandPass = true;
			}
		}
};
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestMultiTexturing.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

// .NAME Test of vtkGLSLShaderDeviceAdapter
// .SECTION Description
// this program tests the shader support in vtkRendering.

#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkImageData.h>
#include <vtkPlaneSource.h>
#include <vtkProperty.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPointSet.h>
#include <vtkPolyData.h>
#include <vtkPainterPolyDataMapper.h>
#include <vtkPNGReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkStripper.h>
#include <vtkTriangleFilter.h>
#include <vtkTexture.h>

#include <vtkTestUtilities.h>
#include <vtkRegressionTestImage.h>

int TestMultiTexturing(int argc, char *argv[])
{
  char* fname1 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/RedCircle.png");
  char* fname2 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/BlueCircle.png");
  char* fname3 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/GreenCircle.png");

  vtkPNGReader * imageReaderRed = vtkPNGReader::New();
  vtkPNGReader * imageReaderBlue = vtkPNGReader::New();
  vtkPNGReader * imageReaderGreen = vtkPNGReader::New();

  imageReaderRed->SetFileName(fname1);
  imageReaderBlue->SetFileName(fname2);
  imageReaderGreen->SetFileName(fname3);
  imageReaderRed->Update();
  imageReaderBlue->Update();
  imageReaderGreen->Update();

  /*vtkPolyData * polyData = vtkPolyData::New();
  vtkPoints * points = vtkPoints::New();
  points->Allocate(16);

  points->InsertNextPoint(-1.0, -1.0, 0.0);
  points->InsertNextPoint(1.0, -1.0, 0.0);
  points->InsertNextPoint(1.0, 1.0, 0.0);
  points->InsertNextPoint(-1.0, 1.0, 0.0);

  polyData->SetPoints(points);

  vtkCellArray * cells = vtkCellArray::New();
  cells->Allocate(cells->EstimateSize(1, 4));
  cells->InsertNextCell(4);
  cells->InsertCellPoint(0);
  cells->InsertCellPoint(1);
  cells->InsertCellPoint(2);
  cells->InsertCellPoint(3);

  polyData->SetPolys(cells);*/

  vtkPlaneSource *planeSource = vtkPlaneSource::New();
  planeSource->Update();

  vtkTriangleFilter *triangleFilter = vtkTriangleFilter::New();
  triangleFilter->SetInputConnection(planeSource->GetOutputPort());
  planeSource->Delete();

  vtkStripper *stripper = vtkStripper::New();
  stripper->SetInputConnection(triangleFilter->GetOutputPort());
  triangleFilter->Delete();
  stripper->Update();

  vtkPolyData *polyData = stripper->GetOutput();
  polyData->Register(NULL);
  stripper->Delete();
  polyData->GetPointData()->SetNormals(NULL);

  vtkFloatArray *TCoords = vtkFloatArray::New();
  TCoords->SetNumberOfComponents(2);
  TCoords->Allocate(8);

  TCoords->InsertNextTuple2(0.0, 0.0);
  TCoords->InsertNextTuple2(0.0, 1.0);
  TCoords->InsertNextTuple2(1.0, 0.0);
  TCoords->InsertNextTuple2(1.0, 1.0);
  TCoords->SetName("MultTCoords");

  polyData->GetPointData()->AddArray(TCoords);

  TCoords->Delete();

  vtkTexture * textureRed =  vtkTexture::New();
  vtkTexture * textureBlue =  vtkTexture::New();
  vtkTexture * textureGreen =  vtkTexture::New();
  textureRed->SetInputConnection(imageReaderRed->GetOutputPort());
  textureBlue->SetInputConnection(imageReaderBlue->GetOutputPort());
  textureGreen->SetInputConnection(imageReaderGreen->GetOutputPort());

  textureRed->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_0);
  textureBlue->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_1);
  textureGreen->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_2);

  // replace the fargments color and then accumulate the textures
  // RGBA values.
  textureRed->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
  textureBlue->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
  textureGreen->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);

  vtkPolyDataMapper * mapper = vtkPolyDataMapper::New();
  mapper->SetInput(polyData);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_0, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_1, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_2, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);

  vtkActor * actor = vtkActor::New();
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_0,textureRed);
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_1,textureBlue);
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_2,textureGreen);
  actor->SetMapper(mapper);

  vtkRenderer * renderer = vtkRenderer::New();
  vtkRenderWindow * renWin = vtkRenderWindow::New();
  renWin->SetSize(300, 300);
  renWin->AddRenderer(renderer);
  renderer->SetBackground(1.0, 0.5, 1.0);

  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);

  renderer->AddActor(actor);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  //points->Delete();
  //cells->Delete();
  polyData->Delete();
  mapper->Delete();
  actor->Delete();
  renWin->Delete();
  renderer->Delete();
  iren->Delete();
  imageReaderRed->Delete();
  imageReaderBlue->Delete();
  imageReaderGreen->Delete();
  textureRed->Delete();
  textureBlue->Delete();
  textureGreen->Delete();

  return !retVal;
}
<commit_msg>BUG:Fixed memory leak.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestMultiTexturing.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

// .NAME Test of vtkGLSLShaderDeviceAdapter
// .SECTION Description
// this program tests the shader support in vtkRendering.

#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkImageData.h>
#include <vtkPlaneSource.h>
#include <vtkProperty.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPointSet.h>
#include <vtkPolyData.h>
#include <vtkPainterPolyDataMapper.h>
#include <vtkPNGReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkStripper.h>
#include <vtkTriangleFilter.h>
#include <vtkTexture.h>

#include <vtkTestUtilities.h>
#include <vtkRegressionTestImage.h>

int TestMultiTexturing(int argc, char *argv[])
{
  char* fname1 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/RedCircle.png");
  char* fname2 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/BlueCircle.png");
  char* fname3 =
    vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/GreenCircle.png");

  vtkPNGReader * imageReaderRed = vtkPNGReader::New();
  vtkPNGReader * imageReaderBlue = vtkPNGReader::New();
  vtkPNGReader * imageReaderGreen = vtkPNGReader::New();

  imageReaderRed->SetFileName(fname1);
  imageReaderBlue->SetFileName(fname2);
  imageReaderGreen->SetFileName(fname3);
  delete[] fname1;
  delete[] fname2;
  delete[] fname3;
  imageReaderRed->Update();
  imageReaderBlue->Update();
  imageReaderGreen->Update();

  /*vtkPolyData * polyData = vtkPolyData::New();
  vtkPoints * points = vtkPoints::New();
  points->Allocate(16);

  points->InsertNextPoint(-1.0, -1.0, 0.0);
  points->InsertNextPoint(1.0, -1.0, 0.0);
  points->InsertNextPoint(1.0, 1.0, 0.0);
  points->InsertNextPoint(-1.0, 1.0, 0.0);

  polyData->SetPoints(points);

  vtkCellArray * cells = vtkCellArray::New();
  cells->Allocate(cells->EstimateSize(1, 4));
  cells->InsertNextCell(4);
  cells->InsertCellPoint(0);
  cells->InsertCellPoint(1);
  cells->InsertCellPoint(2);
  cells->InsertCellPoint(3);

  polyData->SetPolys(cells);*/

  vtkPlaneSource *planeSource = vtkPlaneSource::New();
  planeSource->Update();

  vtkTriangleFilter *triangleFilter = vtkTriangleFilter::New();
  triangleFilter->SetInputConnection(planeSource->GetOutputPort());
  planeSource->Delete();

  vtkStripper *stripper = vtkStripper::New();
  stripper->SetInputConnection(triangleFilter->GetOutputPort());
  triangleFilter->Delete();
  stripper->Update();

  vtkPolyData *polyData = stripper->GetOutput();
  polyData->Register(NULL);
  stripper->Delete();
  polyData->GetPointData()->SetNormals(NULL);

  vtkFloatArray *TCoords = vtkFloatArray::New();
  TCoords->SetNumberOfComponents(2);
  TCoords->Allocate(8);

  TCoords->InsertNextTuple2(0.0, 0.0);
  TCoords->InsertNextTuple2(0.0, 1.0);
  TCoords->InsertNextTuple2(1.0, 0.0);
  TCoords->InsertNextTuple2(1.0, 1.0);
  TCoords->SetName("MultTCoords");

  polyData->GetPointData()->AddArray(TCoords);

  TCoords->Delete();

  vtkTexture * textureRed =  vtkTexture::New();
  vtkTexture * textureBlue =  vtkTexture::New();
  vtkTexture * textureGreen =  vtkTexture::New();
  textureRed->SetInputConnection(imageReaderRed->GetOutputPort());
  textureBlue->SetInputConnection(imageReaderBlue->GetOutputPort());
  textureGreen->SetInputConnection(imageReaderGreen->GetOutputPort());

  textureRed->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_0);
  textureBlue->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_1);
  textureGreen->SetTextureUnit(vtkTexture::VTK_TEXTURE_UNIT_2);

  // replace the fargments color and then accumulate the textures
  // RGBA values.
  textureRed->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
  textureBlue->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
  textureGreen->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);

  vtkPolyDataMapper * mapper = vtkPolyDataMapper::New();
  mapper->SetInput(polyData);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_0, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_1, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);
  mapper->MapDataArrayToMultiTextureAttribute(
    vtkTexture::VTK_TEXTURE_UNIT_2, "MultTCoords", vtkDataObject::FIELD_ASSOCIATION_POINTS);

  vtkActor * actor = vtkActor::New();
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_0,textureRed);
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_1,textureBlue);
  actor->GetProperty()->SetTexture(vtkTexture::VTK_TEXTURE_UNIT_2,textureGreen);
  actor->SetMapper(mapper);

  vtkRenderer * renderer = vtkRenderer::New();
  vtkRenderWindow * renWin = vtkRenderWindow::New();
  renWin->SetSize(300, 300);
  renWin->AddRenderer(renderer);
  renderer->SetBackground(1.0, 0.5, 1.0);

  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);

  renderer->AddActor(actor);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  //points->Delete();
  //cells->Delete();
  polyData->Delete();
  mapper->Delete();
  actor->Delete();
  renWin->Delete();
  renderer->Delete();
  iren->Delete();
  imageReaderRed->Delete();
  imageReaderBlue->Delete();
  imageReaderGreen->Delete();
  textureRed->Delete();
  textureBlue->Delete();
  textureGreen->Delete();

  return !retVal;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <seastar/core/print.hh>
#include "db/query_context.hh"
#include "db/system_keyspace.hh"
#include "db/large_data_handler.hh"
#include "sstables/sstables.hh"

static logging::logger large_data_logger("large_data");

namespace db {

nop_large_data_handler::nop_large_data_handler()
    : large_data_handler(std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(),
          std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max()) {
    // Don't require start() to be called on nop large_data_handler.
    start();
}

large_data_handler::large_data_handler(uint64_t partition_threshold_bytes, uint64_t row_threshold_bytes, uint64_t cell_threshold_bytes, uint64_t rows_count_threshold)
        : _partition_threshold_bytes(partition_threshold_bytes)
        , _row_threshold_bytes(row_threshold_bytes)
        , _cell_threshold_bytes(cell_threshold_bytes)
        , _rows_count_threshold(rows_count_threshold)
{
    large_data_logger.debug("partition_threshold_bytes={} row_threshold_bytes={} cell_threshold_bytes={} rows_count_threshold={}",
        partition_threshold_bytes, row_threshold_bytes, cell_threshold_bytes, rows_count_threshold);
}

future<bool> large_data_handler::maybe_record_large_partitions(const sstables::sstable& sst, const sstables::key& key, uint64_t partition_size) {
    assert(running());
    if (partition_size > _partition_threshold_bytes) {
        ++_stats.partitions_bigger_than_threshold;
        return with_sem([&sst, &key, partition_size, this] {
            return record_large_partitions(sst, key, partition_size);
        }).then([] {
            return true;
        });
    }
    return make_ready_future<bool>(false);
}

void large_data_handler::start() {
    _running = true;
}

future<> large_data_handler::stop() {
    if (!running()) {
        return make_ready_future<>();
    }
    _running = false;
    return _sem.wait(max_concurrency);
}

template <typename T> static std::string key_to_str(const T& key, const schema& s) {
    std::ostringstream oss;
    oss << key.with_schema(s);
    return oss.str();
}

future<> large_data_handler::maybe_delete_large_data_entries(sstables::shared_sstable sst) {
    assert(running());
    auto schema = sst->get_schema();
    auto filename = sst->get_filename();
    auto data_size = sst->data_size();

    future<> large_partitions = make_ready_future<>();
    auto entry = sst->get_large_data_stat(sstables::large_data_type::partition_size);
    if (entry && entry->above_threshold) {
        large_partitions = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_PARTITIONS);
        });
    }
    future<> large_rows = make_ready_future<>();
    entry = sst->get_large_data_stat(sstables::large_data_type::row_size);
    if (entry && entry->above_threshold) {
        large_rows = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_ROWS);
        });
    }
    future<> large_cells = make_ready_future<>();
    entry = sst->get_large_data_stat(sstables::large_data_type::cell_size);
    if (entry && entry->above_threshold) {
        large_cells = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_CELLS);
        });
    }
    return when_all(std::move(large_partitions), std::move(large_rows), std::move(large_cells)).discard_result();
}

template <typename... Args>
static future<> try_record(std::string_view large_table, const sstables::sstable& sst,  const sstables::key& partition_key, int64_t size,
        std::string_view desc, std::string_view extra_path, const std::vector<sstring> &extra_fields, Args&&... args) {
    sstring extra_fields_str;
    sstring extra_values;
    for (std::string_view field : extra_fields) {
        extra_fields_str += format(", {}", field);
        extra_values += ", ?";
    }
    const sstring req = format("INSERT INTO system.large_{}s (keyspace_name, table_name, sstable_name, {}_size, partition_key, compaction_time{}) VALUES (?, ?, ?, ?, ?, ?{}) USING TTL 2592000",
            large_table, large_table, extra_fields_str, extra_values);
    const schema &s = *sst.get_schema();
    auto ks_name = s.ks_name();
    auto cf_name = s.cf_name();
    const auto sstable_name = sst.get_filename();
    std::string pk_str = key_to_str(partition_key.to_partition_key(s), s);
    auto timestamp = db_clock::now();
    large_data_logger.warn("Writing large {} {}/{}: {}{} ({} bytes)", desc, ks_name, cf_name, pk_str, extra_path, size);
    return db::qctx->execute_cql(req, ks_name, cf_name, sstable_name, size, pk_str, timestamp, args...)
            .discard_result()
            .handle_exception([ks_name, cf_name, large_table, sstable_name] (std::exception_ptr ep) {
                large_data_logger.warn("Failed to add a record to system.large_{}s: ks = {}, table = {}, sst = {} exception = {}",
                        large_table, ks_name, cf_name, sstable_name, ep);
            });
}

future<> cql_table_large_data_handler::record_large_partitions(const sstables::sstable& sst, const sstables::key& key, uint64_t partition_size) const {
    return try_record("partition", sst, key, int64_t(partition_size), "partition", "", {});
}

void cql_table_large_data_handler::log_too_many_rows(const sstables::sstable& sst, const sstables::key& partition_key,
        uint64_t rows_count) const {
    const schema& s = *sst.get_schema();
    large_data_logger.warn("Writing a partition with too many rows [{}/{}:{}] ({} rows)",
                           s.ks_name(), s.cf_name(), partition_key.to_partition_key(s).with_schema(s),
                           rows_count);
}

future<> cql_table_large_data_handler::record_large_cells(const sstables::sstable& sst, const sstables::key& partition_key,
        const clustering_key_prefix* clustering_key, const column_definition& cdef, uint64_t cell_size) const {
    auto column_name = cdef.name_as_text();
    std::string_view cell_type = cdef.is_atomic() ? "cell" : "collection";
    static const std::vector<sstring> extra_fields{"clustering_key", "column_name"};
    if (clustering_key) {
        const schema &s = *sst.get_schema();
        auto ck_str = key_to_str(*clustering_key, s);
        return try_record("cell", sst, partition_key, int64_t(cell_size), cell_type, format("{} {}", ck_str, column_name), extra_fields, ck_str, column_name);
    } else {
        return try_record("cell", sst, partition_key, int64_t(cell_size), cell_type, column_name, extra_fields, data_value::make_null(utf8_type), column_name);
    }
}

future<> cql_table_large_data_handler::record_large_rows(const sstables::sstable& sst, const sstables::key& partition_key,
        const clustering_key_prefix* clustering_key, uint64_t row_size) const {
    static const std::vector<sstring> extra_fields{"clustering_key"};
    if (clustering_key) {
        const schema &s = *sst.get_schema();
        std::string ck_str = key_to_str(*clustering_key, s);
        return try_record("row", sst, partition_key, int64_t(row_size), "row", ck_str, extra_fields,  ck_str);
    } else {
        return try_record("row", sst, partition_key, int64_t(row_size), "static row", "", extra_fields, data_value::make_null(utf8_type));
    }
}

future<> cql_table_large_data_handler::delete_large_data_entries(const schema& s, sstring sstable_name, std::string_view large_table_name) const {
    const sstring req =
            format("DELETE FROM system.{} WHERE keyspace_name = ? AND table_name = ? AND sstable_name = ?",
                    large_table_name);
    return db::qctx->execute_cql(req, s.ks_name(), s.cf_name(), sstable_name)
            .discard_result()
            .handle_exception([&s, sstable_name, large_table_name] (std::exception_ptr ep) {
                large_data_logger.warn("Failed to drop entries from {}: ks = {}, table = {}, sst = {} exception = {}",
                        large_table_name, s.ks_name(), s.cf_name(), sstable_name, ep);
            });
}
}
<commit_msg>large_data_handler: Prepare for stopped qctx<commit_after>/*
 * Copyright (C) 2018-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <seastar/core/print.hh>
#include "db/query_context.hh"
#include "db/system_keyspace.hh"
#include "db/large_data_handler.hh"
#include "sstables/sstables.hh"

static logging::logger large_data_logger("large_data");

namespace db {

nop_large_data_handler::nop_large_data_handler()
    : large_data_handler(std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(),
          std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max()) {
    // Don't require start() to be called on nop large_data_handler.
    start();
}

large_data_handler::large_data_handler(uint64_t partition_threshold_bytes, uint64_t row_threshold_bytes, uint64_t cell_threshold_bytes, uint64_t rows_count_threshold)
        : _partition_threshold_bytes(partition_threshold_bytes)
        , _row_threshold_bytes(row_threshold_bytes)
        , _cell_threshold_bytes(cell_threshold_bytes)
        , _rows_count_threshold(rows_count_threshold)
{
    large_data_logger.debug("partition_threshold_bytes={} row_threshold_bytes={} cell_threshold_bytes={} rows_count_threshold={}",
        partition_threshold_bytes, row_threshold_bytes, cell_threshold_bytes, rows_count_threshold);
}

future<bool> large_data_handler::maybe_record_large_partitions(const sstables::sstable& sst, const sstables::key& key, uint64_t partition_size) {
    assert(running());
    if (partition_size > _partition_threshold_bytes) {
        ++_stats.partitions_bigger_than_threshold;
        return with_sem([&sst, &key, partition_size, this] {
            return record_large_partitions(sst, key, partition_size);
        }).then([] {
            return true;
        });
    }
    return make_ready_future<bool>(false);
}

void large_data_handler::start() {
    _running = true;
}

future<> large_data_handler::stop() {
    if (!running()) {
        return make_ready_future<>();
    }
    _running = false;
    return _sem.wait(max_concurrency);
}

template <typename T> static std::string key_to_str(const T& key, const schema& s) {
    std::ostringstream oss;
    oss << key.with_schema(s);
    return oss.str();
}

future<> large_data_handler::maybe_delete_large_data_entries(sstables::shared_sstable sst) {
    assert(running());
    auto schema = sst->get_schema();
    auto filename = sst->get_filename();
    auto data_size = sst->data_size();

    future<> large_partitions = make_ready_future<>();
    auto entry = sst->get_large_data_stat(sstables::large_data_type::partition_size);
    if (entry && entry->above_threshold) {
        large_partitions = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_PARTITIONS);
        });
    }
    future<> large_rows = make_ready_future<>();
    entry = sst->get_large_data_stat(sstables::large_data_type::row_size);
    if (entry && entry->above_threshold) {
        large_rows = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_ROWS);
        });
    }
    future<> large_cells = make_ready_future<>();
    entry = sst->get_large_data_stat(sstables::large_data_type::cell_size);
    if (entry && entry->above_threshold) {
        large_cells = with_sem([schema, filename, this] () mutable {
            return delete_large_data_entries(*schema, std::move(filename), db::system_keyspace::LARGE_CELLS);
        });
    }
    return when_all(std::move(large_partitions), std::move(large_rows), std::move(large_cells)).discard_result();
}

template <typename... Args>
static future<> try_record(std::string_view large_table, const sstables::sstable& sst,  const sstables::key& partition_key, int64_t size,
        std::string_view desc, std::string_view extra_path, const std::vector<sstring> &extra_fields, Args&&... args) {
    // FIXME  This check is for test/cql-test-env that stop qctx (it does so because
    // it stops query processor and doesn't want us to access its freed instantes)
    if (!db::qctx) {
        return make_ready_future<>();
    }

    sstring extra_fields_str;
    sstring extra_values;
    for (std::string_view field : extra_fields) {
        extra_fields_str += format(", {}", field);
        extra_values += ", ?";
    }
    const sstring req = format("INSERT INTO system.large_{}s (keyspace_name, table_name, sstable_name, {}_size, partition_key, compaction_time{}) VALUES (?, ?, ?, ?, ?, ?{}) USING TTL 2592000",
            large_table, large_table, extra_fields_str, extra_values);
    const schema &s = *sst.get_schema();
    auto ks_name = s.ks_name();
    auto cf_name = s.cf_name();
    const auto sstable_name = sst.get_filename();
    std::string pk_str = key_to_str(partition_key.to_partition_key(s), s);
    auto timestamp = db_clock::now();
    large_data_logger.warn("Writing large {} {}/{}: {}{} ({} bytes)", desc, ks_name, cf_name, pk_str, extra_path, size);
    return db::qctx->execute_cql(req, ks_name, cf_name, sstable_name, size, pk_str, timestamp, args...)
            .discard_result()
            .handle_exception([ks_name, cf_name, large_table, sstable_name] (std::exception_ptr ep) {
                large_data_logger.warn("Failed to add a record to system.large_{}s: ks = {}, table = {}, sst = {} exception = {}",
                        large_table, ks_name, cf_name, sstable_name, ep);
            });
}

future<> cql_table_large_data_handler::record_large_partitions(const sstables::sstable& sst, const sstables::key& key, uint64_t partition_size) const {
    return try_record("partition", sst, key, int64_t(partition_size), "partition", "", {});
}

void cql_table_large_data_handler::log_too_many_rows(const sstables::sstable& sst, const sstables::key& partition_key,
        uint64_t rows_count) const {
    const schema& s = *sst.get_schema();
    large_data_logger.warn("Writing a partition with too many rows [{}/{}:{}] ({} rows)",
                           s.ks_name(), s.cf_name(), partition_key.to_partition_key(s).with_schema(s),
                           rows_count);
}

future<> cql_table_large_data_handler::record_large_cells(const sstables::sstable& sst, const sstables::key& partition_key,
        const clustering_key_prefix* clustering_key, const column_definition& cdef, uint64_t cell_size) const {
    auto column_name = cdef.name_as_text();
    std::string_view cell_type = cdef.is_atomic() ? "cell" : "collection";
    static const std::vector<sstring> extra_fields{"clustering_key", "column_name"};
    if (clustering_key) {
        const schema &s = *sst.get_schema();
        auto ck_str = key_to_str(*clustering_key, s);
        return try_record("cell", sst, partition_key, int64_t(cell_size), cell_type, format("{} {}", ck_str, column_name), extra_fields, ck_str, column_name);
    } else {
        return try_record("cell", sst, partition_key, int64_t(cell_size), cell_type, column_name, extra_fields, data_value::make_null(utf8_type), column_name);
    }
}

future<> cql_table_large_data_handler::record_large_rows(const sstables::sstable& sst, const sstables::key& partition_key,
        const clustering_key_prefix* clustering_key, uint64_t row_size) const {
    static const std::vector<sstring> extra_fields{"clustering_key"};
    if (clustering_key) {
        const schema &s = *sst.get_schema();
        std::string ck_str = key_to_str(*clustering_key, s);
        return try_record("row", sst, partition_key, int64_t(row_size), "row", ck_str, extra_fields,  ck_str);
    } else {
        return try_record("row", sst, partition_key, int64_t(row_size), "static row", "", extra_fields, data_value::make_null(utf8_type));
    }
}

future<> cql_table_large_data_handler::delete_large_data_entries(const schema& s, sstring sstable_name, std::string_view large_table_name) const {
    const sstring req =
            format("DELETE FROM system.{} WHERE keyspace_name = ? AND table_name = ? AND sstable_name = ?",
                    large_table_name);
    return db::qctx->execute_cql(req, s.ks_name(), s.cf_name(), sstable_name)
            .discard_result()
            .handle_exception([&s, sstable_name, large_table_name] (std::exception_ptr ep) {
                large_data_logger.warn("Failed to drop entries from {}: ks = {}, table = {}, sst = {} exception = {}",
                        large_table_name, s.ks_name(), s.cf_name(), sstable_name, ep);
            });
}
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_Sound.h"
#include "IModule.h"
#include "Framework.h"
#include "Entity.h"
#include "Audio.h"
#include "AssetAPI.h"
#include "EC_Placeable.h"
#include "EC_SoundListener.h"
#include "SceneManager.h"

#include "LoggingFunctions.h"
DEFINE_POCO_LOGGING_FUNCTIONS("EC_Sound")

#include "MemoryLeakCheck.h"

EC_Sound::EC_Sound(IModule *module):
    IComponent(module->GetFramework()),
    soundRef(this, "Sound ref"),
    soundInnerRadius(this, "Sound radius inner", 0.0f),
    soundOuterRadius(this, "Sound radius outer", 20.0f),
    loopSound(this, "Loop sound", false),
    soundGain(this, "Sound gain", 1.0f),
    spatial(this, "Spatial", true)
{
    static AttributeMetadata metaData("", "0", "1", "0.1");
    soundGain.SetMetadata(&metaData);

    connect(this, SIGNAL(ParentEntitySet()), SLOT(UpdateSignals()));
    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), SLOT(AttributeUpdated(IAttribute*)));
}

EC_Sound::~EC_Sound()
{
    StopSound();
}

void EC_Sound::AttributeUpdated(IAttribute *attribute)
{
    if (attribute == &soundRef)
        framework_->Asset()->RequestAsset(soundRef.Get().ref);

    UpdateSoundSettings();
}

void EC_Sound::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        entity->ConnectAction("PlaySound", this, SLOT(PlaySound()));
        entity->ConnectAction("StopSound", this, SLOT(StopSound()));
    }
}

void EC_Sound::PositionChange(const QVector3D &pos)
{
    if (soundChannel)
        soundChannel->SetPosition(Vector3df(pos.x(), pos.y(), pos.z()));
}

void EC_Sound::PlaySound()
{
    ComponentChanged(AttributeChange::LocalOnly);

    // If previous sound is still playing stop it before we apply a new sound.
    if (soundChannel)
    {
        soundChannel->Stop();
        soundChannel.reset();
    }

    AssetPtr audioAsset = GetFramework()->Asset()->GetAsset(soundRef.Get().ref);
    if (!audioAsset)
    {
        ///\todo Make a request.
        return;
    }

    bool soundListenerExists = true;
    EC_Placeable *placeable = dynamic_cast<EC_Placeable *>(FindPlaceable().get());

    // If we are going to play back positional audio, check that there is a sound listener enabled that can listen to it.
    // Otherwise, if no SoundListener exists, play back the audio as nonpositional.
    if (placeable && spatial.Get())
        soundListenerExists = (GetActiveSoundListener() != Scene::EntityPtr());

    if (placeable && spatial.Get() && soundListenerExists)
    {
        soundChannel = GetFramework()->Audio()->PlaySound3D(placeable->GetPosition(), audioAsset, SoundChannel::Triggered);
        if (soundChannel)
            soundChannel->SetRange(soundInnerRadius.Get(), soundOuterRadius.Get(), 2.0f);
    }
    else // Play back sound as a nonpositional sound, if no EC_Placeable was found or if spatial was not set.
    {
        soundChannel = GetFramework()->Audio()->PlaySound(audioAsset, SoundChannel::Ambient);
    }

    if (soundChannel)
    {
        soundChannel->SetGain(soundGain.Get());
        soundChannel->SetLooped(loopSound.Get());
    }
}

void EC_Sound::StopSound()
{
    if (soundChannel)
        soundChannel->Stop();
    soundChannel.reset();
}

void EC_Sound::UpdateSoundSettings()
{
    if (soundChannel)
    {
        soundChannel->SetGain(soundGain.Get());
        soundChannel->SetLooped(loopSound.Get());
        soundChannel->SetRange(soundInnerRadius.Get(), soundOuterRadius.Get(), 2.0f);
    }
}

Scene::EntityPtr EC_Sound::GetActiveSoundListener()
{
#ifdef _DEBUG
    int numActiveListeners = 0; // For debugging, count how many listeners are active.
#endif

    Scene::EntityList listeners = parent_entity_->GetScene()->GetEntitiesWithComponent("EC_SoundListener");
    foreach(Scene::EntityPtr listener, listeners)
    {
        EC_SoundListener *ec = listener->GetComponent<EC_SoundListener>().get();
        if (ec->active.Get())
        {
#ifndef _DEBUG
            assert(ec->GetParentEntity());
            return ec->GetParentEntity()->shared_from_this;
#else
            ++numActiveListeners;
#endif
        }
    }

    if (numActiveListeners != 1)
        LogWarning("Warning: When playing back positional 3D audio, " + QString::number(numActiveListeners).toStdString() + " active sound listeners were found!");
    return Scene::EntityPtr();
}

void EC_Sound::UpdateSignals()
{
    if (!GetParentEntity())
    {
        LogError("Couldn't update singals cause component dont have parent entity set.");
        return;
    }
    Scene::SceneManager *scene = GetParentEntity()->GetScene();
    if(!scene)
    {
        LogError("Fail to update signals cause parent entity's scene is null.");
        return;
    }

    RegisterActions();
}

ComponentPtr EC_Sound::FindPlaceable() const
{
    assert(framework_);
    ComponentPtr comp;
    if(!GetParentEntity())
    {
        LogError("Fail to find a placeable component cause parent entity is null.");
        return comp;
    }
    comp = GetParentEntity()->GetComponent<EC_Placeable>();
    //We need to update sound source position when placeable component has changed it's transformation.
    connect(comp.get(), SIGNAL(PositionChanged(const QVector3D &)),
            SLOT(PositionChange(const QVector3D &)), Qt::UniqueConnection);
    return comp;
}
<commit_msg>Fix EC_Sound to build in release mode.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "EC_Sound.h"
#include "IModule.h"
#include "Framework.h"
#include "Entity.h"
#include "Audio.h"
#include "AssetAPI.h"
#include "EC_Placeable.h"
#include "EC_SoundListener.h"
#include "SceneManager.h"

#include "LoggingFunctions.h"
DEFINE_POCO_LOGGING_FUNCTIONS("EC_Sound")

#include "MemoryLeakCheck.h"

EC_Sound::EC_Sound(IModule *module):
    IComponent(module->GetFramework()),
    soundRef(this, "Sound ref"),
    soundInnerRadius(this, "Sound radius inner", 0.0f),
    soundOuterRadius(this, "Sound radius outer", 20.0f),
    loopSound(this, "Loop sound", false),
    soundGain(this, "Sound gain", 1.0f),
    spatial(this, "Spatial", true)
{
    static AttributeMetadata metaData("", "0", "1", "0.1");
    soundGain.SetMetadata(&metaData);

    connect(this, SIGNAL(ParentEntitySet()), SLOT(UpdateSignals()));
    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), SLOT(AttributeUpdated(IAttribute*)));
}

EC_Sound::~EC_Sound()
{
    StopSound();
}

void EC_Sound::AttributeUpdated(IAttribute *attribute)
{
    if (attribute == &soundRef)
        framework_->Asset()->RequestAsset(soundRef.Get().ref);

    UpdateSoundSettings();
}

void EC_Sound::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        entity->ConnectAction("PlaySound", this, SLOT(PlaySound()));
        entity->ConnectAction("StopSound", this, SLOT(StopSound()));
    }
}

void EC_Sound::PositionChange(const QVector3D &pos)
{
    if (soundChannel)
        soundChannel->SetPosition(Vector3df(pos.x(), pos.y(), pos.z()));
}

void EC_Sound::PlaySound()
{
    ComponentChanged(AttributeChange::LocalOnly);

    // If previous sound is still playing stop it before we apply a new sound.
    if (soundChannel)
    {
        soundChannel->Stop();
        soundChannel.reset();
    }

    AssetPtr audioAsset = GetFramework()->Asset()->GetAsset(soundRef.Get().ref);
    if (!audioAsset)
    {
        ///\todo Make a request.
        return;
    }

    bool soundListenerExists = true;
    EC_Placeable *placeable = dynamic_cast<EC_Placeable *>(FindPlaceable().get());

    // If we are going to play back positional audio, check that there is a sound listener enabled that can listen to it.
    // Otherwise, if no SoundListener exists, play back the audio as nonpositional.
    if (placeable && spatial.Get())
        soundListenerExists = (GetActiveSoundListener() != Scene::EntityPtr());

    if (placeable && spatial.Get() && soundListenerExists)
    {
        soundChannel = GetFramework()->Audio()->PlaySound3D(placeable->GetPosition(), audioAsset, SoundChannel::Triggered);
        if (soundChannel)
            soundChannel->SetRange(soundInnerRadius.Get(), soundOuterRadius.Get(), 2.0f);
    }
    else // Play back sound as a nonpositional sound, if no EC_Placeable was found or if spatial was not set.
    {
        soundChannel = GetFramework()->Audio()->PlaySound(audioAsset, SoundChannel::Ambient);
    }

    if (soundChannel)
    {
        soundChannel->SetGain(soundGain.Get());
        soundChannel->SetLooped(loopSound.Get());
    }
}

void EC_Sound::StopSound()
{
    if (soundChannel)
        soundChannel->Stop();
    soundChannel.reset();
}

void EC_Sound::UpdateSoundSettings()
{
    if (soundChannel)
    {
        soundChannel->SetGain(soundGain.Get());
        soundChannel->SetLooped(loopSound.Get());
        soundChannel->SetRange(soundInnerRadius.Get(), soundOuterRadius.Get(), 2.0f);
    }
}

Scene::EntityPtr EC_Sound::GetActiveSoundListener()
{
#ifdef _DEBUG
    int numActiveListeners = 0; // For debugging, count how many listeners are active.
#endif

    Scene::EntityList listeners = parent_entity_->GetScene()->GetEntitiesWithComponent("EC_SoundListener");
    foreach(Scene::EntityPtr listener, listeners)
    {
        EC_SoundListener *ec = listener->GetComponent<EC_SoundListener>().get();
        if (ec->active.Get())
        {
#ifndef _DEBUG
            assert(ec->GetParentEntity());
            return ec->GetParentEntity()->shared_from_this();
#else
            ++numActiveListeners;
#endif
        }
    }

#ifdef _DEBUG
    if (numActiveListeners != 1)
        LogWarning("Warning: When playing back positional 3D audio, " + QString::number(numActiveListeners).toStdString() + " active sound listeners were found!");
#endif
    return Scene::EntityPtr();
}

void EC_Sound::UpdateSignals()
{
    if (!GetParentEntity())
    {
        LogError("Couldn't update singals cause component dont have parent entity set.");
        return;
    }
    Scene::SceneManager *scene = GetParentEntity()->GetScene();
    if(!scene)
    {
        LogError("Fail to update signals cause parent entity's scene is null.");
        return;
    }

    RegisterActions();
}

ComponentPtr EC_Sound::FindPlaceable() const
{
    assert(framework_);
    ComponentPtr comp;
    if(!GetParentEntity())
    {
        LogError("Fail to find a placeable component cause parent entity is null.");
        return comp;
    }
    comp = GetParentEntity()->GetComponent<EC_Placeable>();
    //We need to update sound source position when placeable component has changed it's transformation.
    connect(comp.get(), SIGNAL(PositionChanged(const QVector3D &)),
            SLOT(PositionChange(const QVector3D &)), Qt::UniqueConnection);
    return comp;
}
<|endoftext|>


<commit_before>#include <iostream>

#if !defined(NOMINMAX)
#define NOMINMAX // fckng Windows
#endif

#include "vtrc-client/vtrc-client.h"
#include "vtrc-common/vtrc-thread-pool.h"
#include "vtrc-common/vtrc-stub-wrapper.h"
#include "vtrc-common/vtrc-random-device.h"

#include "protocol/hello.pb.h"

#include "boost/lexical_cast.hpp"

#include "openssl/err.h"
#include "openssl/rand.h"

#if defined(X509_NAME)
#undef X509_NAME
#endif

#include "openssl/ssl.h"

#include "../protocol/ssl-wrapper.h"

using namespace vtrc;

const std::string CERTF = "../server.crt";

namespace {

    typedef howto::hello_ssl_service_Stub   stub_type;
    typedef common::stub_wrapper<stub_type> stub_wrap;

    void on_connect( )
    {
        std::cout << "connect...";
    }
    void on_ready( )
    {
        std::cout << "ready...";
    }
    void on_disconnect( )
    {
        std::cout << "disconnect...";
    }

    void ssl_throw( const char *add )
    {
        std::string err(add);
        err += ": ";
        size_t final = err.size( );
        err.resize( final + 1024 );
        ERR_error_string_n(ERR_get_error( ), &err[final], err.size( ) - final );
        throw std::runtime_error( err );
    }
}

int verify_callback( X509_STORE_CTX *x509, void */*p*/ )
{
    char subject[512];
    int ver = X509_verify_cert(x509);
    if( ver <= 0 ) {
        int err = X509_STORE_CTX_get_error(x509);
        char errorbuf[1024];
        ERR_error_string_n(err, errorbuf, 1024);
        std::cout << "Cert is not valid. " << errorbuf << "\n";
    }
    X509 *cc = X509_STORE_CTX_get_current_cert( x509 );
    if( !cc ) {
        ssl_throw("ds");
    }
    X509_NAME *sn = X509_get_subject_name( cc );
    X509_NAME_oneline(sn, subject, 256);
    std::cout << "Verify call: " << subject << "\n";

    /// we don't care, cuz "Hello, world!"
    return 1;
}

class my_ssl_wrapper: public ssl_wrapper_client {
public:
    my_ssl_wrapper( )
        :ssl_wrapper_client(TLSv1_2_client_method( ))
    { }
private:
    void init_context( )
    {
        SSL_CTX_set_mode( get_context( ), SSL_MODE_AUTO_RETRY           );
        SSL_CTX_set_mode( get_context( ), SSL_MODE_ENABLE_PARTIAL_WRITE );
        SSL_CTX_set_mode( get_context( ), SSL_MODE_RELEASE_BUFFERS      );

        SSL_CTX_set_cert_verify_callback( get_context( ), verify_callback, 0 );

        int err = SSL_CTX_load_verify_locations( get_context( ),
                                                 CERTF.c_str( ), 0 );
        if( err == 0 ) {
            ssl_throw("SSL_CTX_load_verify_locations");
        }
    }
};

std::string send_data( stub_wrap &stub, my_ssl_wrapper &ssl,
                       const std::string &data, bool decode = true )
{
    howto::request_message  req;
    howto::response_message res;

    req.set_block( ssl.encrypt( data ) );
    //std::cout << "packed: " << req.block( ).size( ) << "\n";

    stub.call( &stub_type::send_block, &req, &res );
    std::string result;
    if( decode ) {
        result = ssl.decrypt( res.block( ) );
    } else {
        ssl.get_in( ).write( res.block( ) );
    }
//    std::cout << "result: " << result.size( ) << " "
//              << res.block( ).size( ) << "\n";
    return result;
}

void connect_handshake( stub_wrap &stub )
{
    my_ssl_wrapper ssl;
    ssl.init( );
    howto::request_message  req;
    howto::response_message res;
    std::string data;
    while (!ssl.init_finished( )) {

        std::string res_data = ssl.do_handshake( );

        if( !res_data.empty( ) ) {
            req.set_block( res_data );
            stub.call( &stub_type::send_block, &req, &res );
            data = res.block( );
            if( !data.empty( ) ) { //
                ssl.get_in( ).write( data.c_str( ), data.size( ) );
            }
        }
    }

    std::cout << "Init success!\n";

    int i = 0;

    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World1" )
              << "\n";
    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World2", false )
              << "\n";
    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World3" )
              << "\n";

    std::string test(41, '!');
    std::cout << i++ << ": " << send_data( stub, ssl, test ) << "\n";
}

int main( int argc, const char **argv )
{
    common::thread_pool tp( 1 );

    const char *address = "127.0.0.1";
    unsigned short port = 56560;

    if( argc > 2 ) {
        address = argv[1];
        port = boost::lexical_cast<unsigned short>( argv[2] );
    } else if( argc > 1 ) {
        port = boost::lexical_cast<unsigned short>( argv[1] );
    }

    vtrc::common::random_device rd(true);
    std::string seed = rd.generate_block( 1024 );

    RAND_seed( seed.c_str( ), seed.size( ) );

    SSL_load_error_strings( );
    SSLeay_add_ssl_algorithms( );

    try {

        client::vtrc_client_sptr cl =
                         client::vtrc_client::create( tp.get_io_service( ) );

        cl->on_connect_connect( on_connect );
        cl->on_ready_connect( on_ready );
        cl->on_disconnect_connect( on_disconnect );

        std::cout <<  "Connecting..." << std::endl;

        cl->connect( address, port );
        std::cout << "Ok" << std::endl;

        vtrc::unique_ptr<common::rpc_channel> channel(cl->create_channel( ));

        stub_wrap hello(channel.get( ));

        connect_handshake( hello );

    } catch( const std::exception &ex ) {
        std::cerr << "Hello, world failed: " << ex.what( ) << "\n";
    }

    tp.stop( );
    tp.join_all( );

    /// make valgrind happy.
    google::protobuf::ShutdownProtobufLibrary( );

    return 0;
}
<commit_msg>exmpl<commit_after>#include <iostream>

#if !defined(NOMINMAX)
#define NOMINMAX // fckng Windows
#endif

#include "vtrc-client/vtrc-client.h"
#include "vtrc-common/vtrc-thread-pool.h"
#include "vtrc-common/vtrc-stub-wrapper.h"
#include "vtrc-common/vtrc-random-device.h"

#include "protocol/hello.pb.h"

#include "boost/lexical_cast.hpp"

#include "openssl/err.h"
#include "openssl/rand.h"

#if defined(X509_NAME)
#undef X509_NAME // fckng MS
#endif

#include "openssl/ssl.h"

#include "../protocol/ssl-wrapper.h"

using namespace vtrc;

const std::string CERTF = "../server.crt";

namespace {

    typedef howto::hello_ssl_service_Stub   stub_type;
    typedef common::stub_wrapper<stub_type> stub_wrap;

    void on_connect( )
    {
        std::cout << "connect...";
    }
    void on_ready( )
    {
        std::cout << "ready...";
    }
    void on_disconnect( )
    {
        std::cout << "disconnect...";
    }

    void ssl_throw( const char *add )
    {
        std::string err(add);
        err += ": ";
        size_t final = err.size( );
        err.resize( final + 1024 );
        ERR_error_string_n(ERR_get_error( ), &err[final], err.size( ) - final );
        throw std::runtime_error( err );
    }
}

int verify_callback( X509_STORE_CTX *x509, void */*p*/ )
{
    char subject[512];
    int ver = X509_verify_cert(x509);
    if( ver <= 0 ) {
        int err = X509_STORE_CTX_get_error(x509);
        char errorbuf[1024];
        ERR_error_string_n(err, errorbuf, 1024);
        std::cout << "Cert is not valid. " << errorbuf << "\n";
    }
    X509 *cc = X509_STORE_CTX_get_current_cert( x509 );
    if( !cc ) {
        ssl_throw("ds");
    }
    X509_NAME *sn = X509_get_subject_name( cc );
    X509_NAME_oneline(sn, subject, 256);
    std::cout << "Verify call: " << subject << "\n";

    /// we don't care, cuz "Hello, world!"
    return 1;
}

class my_ssl_wrapper: public ssl_wrapper_client {
public:
    my_ssl_wrapper( )
        :ssl_wrapper_client(TLSv1_2_client_method( ))
    { }
private:
    void init_context( )
    {
        SSL_CTX_set_mode( get_context( ), SSL_MODE_AUTO_RETRY           );
        SSL_CTX_set_mode( get_context( ), SSL_MODE_ENABLE_PARTIAL_WRITE );
        SSL_CTX_set_mode( get_context( ), SSL_MODE_RELEASE_BUFFERS      );

        SSL_CTX_set_cert_verify_callback( get_context( ), verify_callback, 0 );

        int err = SSL_CTX_load_verify_locations( get_context( ),
                                                 CERTF.c_str( ), 0 );
        if( err == 0 ) {
            ssl_throw("SSL_CTX_load_verify_locations");
        }
    }
};

std::string send_data( stub_wrap &stub, my_ssl_wrapper &ssl,
                       const std::string &data, bool decode = true )
{
    howto::request_message  req;
    howto::response_message res;

    req.set_block( ssl.encrypt( data ) );
    //std::cout << "packed: " << req.block( ).size( ) << "\n";

    stub.call( &stub_type::send_block, &req, &res );
    std::string result;
    if( decode ) {
        result = ssl.decrypt( res.block( ) );
    } else {
        ssl.get_in( ).write( res.block( ) );
    }
//    std::cout << "result: " << result.size( ) << " "
//              << res.block( ).size( ) << "\n";
    return result;
}

void connect_handshake( stub_wrap &stub )
{
    my_ssl_wrapper ssl;
    ssl.init( );
    howto::request_message  req;
    howto::response_message res;
    std::string data;
    while (!ssl.init_finished( )) {

        std::string res_data = ssl.do_handshake( );

        if( !res_data.empty( ) ) {
            req.set_block( res_data );
            stub.call( &stub_type::send_block, &req, &res );
            data = res.block( );
            if( !data.empty( ) ) { //
                ssl.get_in( ).write( data.c_str( ), data.size( ) );
            }
        }
    }

    std::cout << "Init success!\n";

    int i = 0;

    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World1" )
              << "\n";
    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World2", false )
              << "\n";
    std::cout << i++ << ": " << send_data( stub, ssl, "Hello, World3" )
              << "\n";

    std::string test(41, '!');
    std::cout << i++ << ": " << send_data( stub, ssl, test ) << "\n";
}

int main( int argc, const char **argv )
{
    common::thread_pool tp( 1 );

    const char *address = "127.0.0.1";
    unsigned short port = 56560;

    if( argc > 2 ) {
        address = argv[1];
        port = boost::lexical_cast<unsigned short>( argv[2] );
    } else if( argc > 1 ) {
        port = boost::lexical_cast<unsigned short>( argv[1] );
    }

    vtrc::common::random_device rd(true);
    std::string seed = rd.generate_block( 1024 );

    RAND_seed( seed.c_str( ), seed.size( ) );

    SSL_load_error_strings( );
    SSLeay_add_ssl_algorithms( );

    try {

        client::vtrc_client_sptr cl =
                         client::vtrc_client::create( tp.get_io_service( ) );

        cl->on_connect_connect( on_connect );
        cl->on_ready_connect( on_ready );
        cl->on_disconnect_connect( on_disconnect );

        std::cout <<  "Connecting..." << std::endl;

        cl->connect( address, port );
        std::cout << "Ok" << std::endl;

        vtrc::unique_ptr<common::rpc_channel> channel(cl->create_channel( ));

        stub_wrap hello(channel.get( ));

        connect_handshake( hello );

    } catch( const std::exception &ex ) {
        std::cerr << "Hello, world failed: " << ex.what( ) << "\n";
    }

    tp.stop( );
    tp.join_all( );

    /// make valgrind happy.
    google::protobuf::ShutdownProtobufLibrary( );

    return 0;
}
<|endoftext|>