<commit_before>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

        private:
            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

        private:
            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

        private:
            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;

        private:
            void bind_to_texture();

            model::Texture *texture_pointer;       // pointer to the texture.

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // rotate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<commit_msg>Muokattu kommentteja.<commit_after>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            // this method sets a shader pointer.
            void set_shader_pointer(GLuint shaderID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint shaderID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

        private:
            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets a texture pointer.
            void set_texture_pointer(GLuint textureID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint textureID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `shaderID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

        private:
            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint shaderID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets a species pointer.
            void set_species_pointer(GLuint speciesID, void* species_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint speciesID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `textureID` from the new shader.
            void switch_to_new_shader(model::Shader *new_world_pointer);

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

        private:
            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint textureID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

        private:
            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

        private:
            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint objectID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint objectID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `speciesID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;
            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            glm::mat4 ProjectionMatrix;
            glm::mat4 ViewMatrix;

        private:
            void bind_to_texture();

            model::Texture *texture_pointer;       // pointer to the texture.

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint speciesID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `objectID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint objectID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // coordinate vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "browser/message_box.h"

namespace atom {

int ShowMessageBox(NativeWindow* parent_window,
                   MessageBoxType type,
                   const std::vector<std::string>& buttons,
                   const std::string& title,
                   const std::string& message,
                   const std::string& detail) {
  return 0;
}

}  // namespace atom
<commit_msg>[Win] Show an empty window for ShowMessageBox.<commit_after>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "browser/message_box.h"

#include "base/message_loop.h"
#include "base/run_loop.h"
#include "base/utf_string_conversions.h"
#include "browser/native_window.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/message_box_view.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"

namespace atom {

namespace {

class MessageDialog : public base::MessageLoop::Dispatcher,
                      public views::WidgetDelegate,
                      public views::ButtonListener {
 public:
  MessageDialog(NativeWindow* parent_window,
                MessageBoxType type,
                const std::vector<std::string>& buttons,
                const std::string& title,
                const std::string& message,
                const std::string& detail);
  virtual ~MessageDialog();

 private:
  // Overridden from MessageLoop::Dispatcher:
  virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;

  // Overridden from views::Widget:
  virtual void WindowClosing() OVERRIDE;
  virtual views::Widget* GetWidget() OVERRIDE;
  virtual const views::Widget* GetWidget() const OVERRIDE;
  virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;

  // Overridden from views::ButtonListener:
  virtual void ButtonPressed(views::Button* sender,
                             const ui::Event& event) OVERRIDE;

  bool should_close_;
  views::Widget* widget_;
  views::MessageBoxView* message_box_view_;

  DISALLOW_COPY_AND_ASSIGN(MessageDialog);
};

////////////////////////////////////////////////////////////////////////////////
// MessageDialog, public:

MessageDialog::MessageDialog(NativeWindow* parent_window,
                             MessageBoxType type,
                             const std::vector<std::string>& buttons,
                             const std::string& title,
                             const std::string& message,
                             const std::string& detail)
    : should_close_(false) {
  views::MessageBoxView::InitParams params(UTF8ToUTF16(title));
  params.message = UTF8ToUTF16(message);
  message_box_view_ = new views::MessageBoxView(params);

  views::Widget::InitParams widget_params;
  widget_params.delegate = this;
  if (parent_window)
    widget_params.parent = parent_window->GetNativeWindow();
  widget_ = new views::Widget;
  widget_->Init(widget_params);

  widget_->Show();
}

MessageDialog::~MessageDialog() {
}

////////////////////////////////////////////////////////////////////////////////
// MessageDialog, private:

bool MessageDialog::Dispatch(const base::NativeEvent& event) {
  TranslateMessage(&event);
  DispatchMessage(&event);
  return !should_close_;
}

void MessageDialog::WindowClosing() {
  should_close_ = true;
}

views::Widget* MessageDialog::GetWidget() {
  return widget_;
}

const views::Widget* MessageDialog::GetWidget() const {
  return widget_;
}

views::ClientView* MessageDialog::CreateClientView(views::Widget* widget) {
  return new views::ClientView(widget, message_box_view_);
}

void MessageDialog::ButtonPressed(views::Button* sender,
                                  const ui::Event& event) {
}

}  // namespace

int ShowMessageBox(NativeWindow* parent_window,
                   MessageBoxType type,
                   const std::vector<std::string>& buttons,
                   const std::string& title,
                   const std::string& message,
                   const std::string& detail) {
  MessageDialog dialog(parent_window, type, buttons, title, message, detail);
  {
    base::MessageLoop::ScopedNestableTaskAllower allow(
        base::MessageLoopForUI::current());
    base::RunLoop run_loop(&dialog);
    run_loop.Run();
  }
  return 0;
}

}  // namespace atom
<|endoftext|>


<commit_before>#ifndef SYNCHRONIZE_LOCKS_NUM
#   define SYNCHRONIZE_LOCKS_NUM 0x100
#endif
#ifndef READ_SIDE_PARALLELISM
#   define READ_SIDE_PARALLELISM 0x8
#endif

#include <iostream>
#include <array>
#include <mutex>
#include <memory>
#include <functional>
#include <algorithm>
#include <thread>

namespace syncope {

namespace detail {

    class LockLayerImpl {
        enum {
            N = SYNCHRONIZE_LOCKS_NUM
        };
        static_assert((N & (N - 1)) == 0, "N (SYNCHRONIZE_LOCKS_NUM) must be a power of two");
        static const int MASK = N - 1;
        typedef std::recursive_mutex MutexT;
        mutable std::array<MutexT, N> mutexes_;
        const char* name_;
    public:
        LockLayerImpl(const char* name) : name_(name) {}
        LockLayerImpl(LockLayerImpl const&) = delete;
        LockLayerImpl& operator = (LockLayerImpl const&) = delete;

        void lock(size_t hash) const {
            size_t ix = hash & MASK;
            mutexes_[ix].lock();
        }

        void unlock(size_t hash) const {
            size_t ix = hash & MASK;
            mutexes_[ix].unlock();
        }
    };
} // namespace detail

// namespace locks

    template<class Hash, class T>
    class LockGuard {
        T const* ptr_;
        detail::LockLayerImpl& lock_pool_;
        Hash hash_;

        void lock() const {
            lock_pool_.lock(hash_(reinterpret_cast<size_t>(ptr_)));
        }

        void unlock() const {
            lock_pool_.unlock(hash_(reinterpret_cast<size_t>(ptr_)));
        }
    public:
        LockGuard(T const* ptr, detail::LockLayerImpl& lockpool) : ptr_(ptr), lock_pool_(lockpool) {
            lock();
        }

        LockGuard(LockGuard const&) = delete;

        LockGuard& operator = (LockGuard const&) = delete;

        LockGuard(LockGuard&& other) : ptr_(other.ptr_), lock_pool_(other.lock_pool_) {
            other.ptr_ = nullptr;
        }

        LockGuard& operator = (LockGuard&& other) {
            ptr_ = other.ptr_;
            other.ptr_ = nullptr;
            assert(&lock_pool_ == &other.lock_pool_);
        }

        ~LockGuard() {
            if (ptr_ != nullptr) {
                unlock();
            }
        }
    };

    template<class Hash, int P, typename... T>
    class LockGuardMany {
        enum {
            H = sizeof...(T)*P  // hashes array size (can be greater than sizeof...(T))
        };
        detail::LockLayerImpl& impl_;
        std::array<size_t, H> hashes_;

        template<int I, int M, int H>
        struct fill_hashes
        {
            void operator () (std::array<size_t, H>& hashes, std::tuple<T const*...> const& items) {
                Hash hash;
                const auto p = std::get<I>(items);
                for (int i = 0; i < P; i++) {
                    size_t h = hash(reinterpret_cast<size_t>(p), i);
                    hashes[I*P + i] = h;
                }
                fill_hashes<I + 1, M, H> fh;
                fh(hashes, items);
            }
        };

        template<int M, int H>
        struct fill_hashes<M, M, H>{
            void operator() (std::array<size_t, H>& hashes, std::tuple<T const*...> const& items) {}
        };

        void lock() const {
            for (auto h: hashes_) {
                impl_.lock(h);
            }
        }

        void unlock() const {
            for (auto it = hashes_.crbegin(); it != hashes_.crend(); it++) {
                impl_.unlock(*it);
            }
        }

    public:

        LockGuardMany(detail::LockLayerImpl& impl, T const*... others)
            : impl_(impl)
        {
            auto all = std::tie(others...);
            fill_hashes<0, sizeof...(others), H> fill_all;
            fill_all(hashes_, all);
            std::sort(hashes_.begin(), hashes_.end());
            lock();
        }

        ~LockGuardMany() {
            unlock();
        }
    };

    namespace detail {

    class StaticString {
        const char* str_;
    public:
        StaticString(const char* s) : str_(s) {
            // TODO: assert(string is static)
        }

        const char* str() const { return str_; }
    };

    //! Simple hash - uses std::hash internally
    struct SimpleHash {
        size_t operator() (size_t value) const {
            std::hash<size_t> hash;
            return hash(value);
        }
    };

    //! Simple hash - uses std::hash and ignores bias
    struct SimpleHash2 {
        size_t operator() (size_t value, int bias) const {
            std::hash<size_t> hash;
            return hash(value);
        }
    };

    template<int P>
    struct BiasedHash {
        static_assert((P & (P - 1)) == 0, "P must be a power of two");
        size_t operator() (size_t value) const {
            std::hash<size_t> hash;
            std::hash<std::thread::id> thash;
            auto id = std::this_thread::get_id();
            size_t bias = thash(id);
            return hash(value) + (bias & (P - 1));
        }
    };

    template<int P>
    struct BiasedHash2 {
        static_assert((P & (P - 1)) == 0, "P must be a power of two");
        size_t operator() (size_t value, int bias) const {
            std::hash<size_t> hash;
            return hash(value) + (bias & (P - 1));
        }
    };

    }

    /** Lock hierarchy layer.
      */
    class SymmetricLockLayer {
        detail::LockLayerImpl impl_;
    public:

        /** C-tor
          * @param name statically initialized string
          */
        SymmetricLockLayer(detail::StaticString name) : impl_(name.str()) {}

        template<class T>
        LockGuard<detail::SimpleHash, T> synchronize(T const* ptr) {
            return std::move(LockGuard<detail::SimpleHash, T>(ptr, impl_));
        }

        template<typename... T>
        LockGuardMany<detail::SimpleHash2, 1, T...> synchronize(T const*... args) {
            return std::move(LockGuardMany<detail::SimpleHash2, 1, T...>(impl_, args...));
        }
    };

    /** Asymmetric lock hierarchy layer.
      */
    class AsymmetricLockLayer {
        detail::LockLayerImpl impl_;
        enum {
            P = READ_SIDE_PARALLELISM  // Parallelism factor for readers and writers
        };
    public:

        /** C-tor
          * @param name statically initialized string
          */
        AsymmetricLockLayer(detail::StaticString name) : impl_(name.str()) {}

        template<class T>
        LockGuard<detail::BiasedHash<P>, T> read_lock(T const* ptr) {
            return std::move(LockGuard<detail::BiasedHash<P>, T>(ptr, impl_));
        }

        template<typename... T>
        LockGuardMany<detail::BiasedHash2<P>, P, T...> write_lock(T const*... args) {
            return std::move(LockGuardMany<detail::BiasedHash2<P>, P, T...>(impl_, args...));
        }
    };
}  // namespace syncope

#define STATIC_STRING(x) locks::detail::StaticString(x"")
<commit_msg>Errors fixed<commit_after>#ifndef SYNCHRONIZE_LOCKS_NUM
#   define SYNCHRONIZE_LOCKS_NUM 0x100
#endif
#ifndef READ_SIDE_PARALLELISM
#   define READ_SIDE_PARALLELISM 0x8
#endif

#include <iostream>
#include <array>
#include <mutex>
#include <memory>
#include <functional>
#include <algorithm>
#include <thread>

namespace syncope {

namespace detail {

    class LockLayerImpl {
        enum {
            N = SYNCHRONIZE_LOCKS_NUM
        };
        static_assert((N & (N - 1)) == 0, "N (SYNCHRONIZE_LOCKS_NUM) must be a power of two");
        static const int MASK = N - 1;
        typedef std::recursive_mutex MutexT;
        mutable std::array<MutexT, N> mutexes_;
        const char* name_;
    public:
        LockLayerImpl(const char* name) : name_(name) {}
        LockLayerImpl(LockLayerImpl const&) = delete;
        LockLayerImpl& operator = (LockLayerImpl const&) = delete;

        void lock(size_t hash) const {
            size_t ix = hash & MASK;
            mutexes_[ix].lock();
        }

        void unlock(size_t hash) const {
            size_t ix = hash & MASK;
            mutexes_[ix].unlock();
        }
    };
} // namespace detail

// namespace locks

    template<class T>
    class LockGuard {
        size_t value_;
        bool owns_lock_;
        detail::LockLayerImpl& lock_pool_;

        void lock() {
            lock_pool_.lock(value_);
            owns_lock_ = true;
        }

        void unlock() {
            lock_pool_.unlock(value_);
            owns_lock_ = false;
        }
    public:
        template<typename Hash>
        LockGuard(T const* ptr, detail::LockLayerImpl& lockpool, Hash const& hash)
            : value_(hash(reinterpret_cast<size_t>(ptr)))
            , owns_lock_(false)
            , lock_pool_(lockpool)
        {
            lock();
        }

        LockGuard(LockGuard const&) = delete;

        LockGuard& operator = (LockGuard const&) = delete;

        LockGuard(LockGuard&& other)
            : value_(other.value_)
            , owns_lock_(other.owns_lock_)
            , lock_pool_(other.lock_pool_)
        {
            other.owns_lock_ = false;
        }

        LockGuard& operator = (LockGuard&& other) {
            value_ = other.value_;
            other.owns_lock_ = false;
            assert(&lock_pool_ == &other.lock_pool_);
        }

        ~LockGuard() {
            if (owns_lock_) {
                unlock();
            }
        }
    };

    template<int P, typename... T>
    class LockGuardMany {
        enum {
            H = sizeof...(T)*P  // hashes array size (can be greater than sizeof...(T))
        };
        detail::LockLayerImpl& impl_;
        std::array<size_t, H> hashes_;
        bool owns_lock_;

        template<int I, int M, int H>
        struct fill_hashes
        {
            template<typename Hash>
            void operator () (std::array<size_t, H>& hashes, std::tuple<T const*...> const& items, Hash const& hash) {
                const auto p = std::get<I>(items);
                for (int i = 0; i < P; i++) {
                    size_t h = hash(reinterpret_cast<size_t>(p), i);
                    hashes[I*P + i] = h;
                }
                fill_hashes<I + 1, M, H> fh;
                fh(hashes, items, hash);
            }
        };

        template<int M, int H>
        struct fill_hashes<M, M, H>{
            template<typename Hash>
            void operator() (std::array<size_t, H>& hashes, std::tuple<T const*...> const& items, Hash const& hash) {}
        };

        void lock() {
            for (auto h: hashes_) {
                impl_.lock(h);
            }
            owns_lock_ = true;
        }

        void unlock() {
            for (auto it = hashes_.crbegin(); it != hashes_.crend(); it++) {
                impl_.unlock(*it);
            }
            owns_lock_ = false;
        }

    public:

        template<typename Hash>
        LockGuardMany(detail::LockLayerImpl& impl, Hash const& hash, T const*... others)
            : impl_(impl)
            , owns_lock_(false)
        {
            auto all = std::tie(others...);
            fill_hashes<0, sizeof...(others), H> fill_all;
            fill_all(hashes_, all, hash);
            std::sort(hashes_.begin(), hashes_.end());
            lock();
        }

        ~LockGuardMany() {
            unlock();
        }

        LockGuardMany(LockGuardMany const&) = delete;
        LockGuardMany& operator = (LockGuardMany const&) = delete;

        LockGuardMany(LockGuardMany&& other)
            : impl_(other.impl_)
            , owns_lock_(other.owns_lock_)
        {
            std::swap(hashes_, other.hashes_);
            other.owns_lock_ = false;
        }

        LockGuardMany& operator = (LockGuardMany&& other) {
            assert(&other.impl_ == &impl_);
            std::swap(hashes_, other.hashes_);
            owns_lock_ = other.owns_lock_;
            other.owns_lock_ = false;
        }
    };

    namespace detail {

    class StaticString {
        const char* str_;
    public:
        StaticString(const char* s) : str_(s) {
            // TODO: assert(string is static)
        }

        const char* str() const { return str_; }
    };

    //! Simple hash - simply returns it's argument
    struct SimpleHash {
        size_t operator() (size_t value) const {
            return value;
        }
    };

    //! Simple hash
    struct SimpleHash2 {
        size_t operator() (size_t value, int bias) const {
            return value;
        }
    };

    template<int P>
    struct BiasedHash {
        static_assert((P & (P - 1)) == 0, "P must be a power of two");
        size_t operator() (size_t value) const {
            std::hash<std::thread::id> hash;
            auto id = std::this_thread::get_id();
            size_t bias = hash(id);
            return value + (bias & (P - 1));
        }
    };

    template<int P>
    struct BiasedHash2 {
        static_assert((P & (P - 1)) == 0, "P must be a power of two");
        size_t operator() (size_t value, int bias) const {
            return value + (bias & (P - 1));
        }
    };

    }

    /** Lock hierarchy layer.
      */
    class SymmetricLockLayer {
        detail::LockLayerImpl impl_;
    public:

        /** C-tor
          * @param name statically initialized string
          */
        SymmetricLockLayer(detail::StaticString name) : impl_(name.str()) {}

        template<class T>
        LockGuard<T> synchronize(T const* ptr) {
            return std::move(LockGuard<T>(ptr, impl_, detail::SimpleHash()));
        }

        template<typename... T>
        LockGuardMany<1, T...> synchronize(T const*... args) {
            return std::move(LockGuardMany<1, T...>(impl_, detail::SimpleHash2(), args...));
        }
    };

    /** Asymmetric lock hierarchy layer.
      */
    class AsymmetricLockLayer {
        detail::LockLayerImpl impl_;
        enum {
            P = READ_SIDE_PARALLELISM  // Parallelism factor for readers and writers
        };
    public:

        /** C-tor
          * @param name statically initialized string
          */
        AsymmetricLockLayer(detail::StaticString name) : impl_(name.str()) {}

        template<class T>
        LockGuard<T> read_lock(T const* ptr) {
            return std::move(LockGuard<T>(ptr, impl_, detail::BiasedHash<P>()));
        }

        template<typename... T>
        LockGuardMany<P, T...> write_lock(T const*... args) {
            return std::move(LockGuardMany<P, T...>(impl_, detail::BiasedHash2<P>(), args...));
        }
    };
}  // namespace syncope

#define STATIC_STRING(x) syncope::detail::StaticString(x"")
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013-2014 Daniel Nicoletti <dantti12@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "engineuwsgi.h"
#include "plugin.h"

#include <Cutelyst/Application>

#include <QCoreApplication>
#include <QSocketNotifier>
#include <QPluginLoader>

using namespace Cutelyst;

static QList<EngineUwsgi *> coreEngines;

void cuteOutput(QtMsgType, const QMessageLogContext &, const QString &);
void uwsgi_cutelyst_loop(void);

/**
 * This function is called as soon as
 * the plugin is loaded
 */
extern "C" void uwsgi_cutelyst_on_load()
{
    uwsgi_register_loop( (char *) "CutelystQtLoop", uwsgi_cutelyst_loop);

    (void) new QCoreApplication(uwsgi.argc, uwsgi.argv);

    if (qEnvironmentVariableIsEmpty("CUTELYST_NO_UWSGI_LOG")) {
        qInstallMessageHandler(cuteOutput);
    }
}

extern "C" int uwsgi_cutelyst_init()
{
    uwsgi_log("Initializing Cutelyst plugin\n");

    uwsgi.loop = (char *) "CutelystQtLoop";

    return 0;
}

extern "C" void uwsgi_cutelyst_post_fork()
{
    Q_FOREACH (EngineUwsgi *engine, coreEngines) {
        if (engine->thread() != qApp->thread()) {
            engine->thread()->start();
        } else {
            Q_EMIT engine->postFork();
        }
    }
}

extern "C" int uwsgi_cutelyst_request(struct wsgi_request *wsgi_req)
{
    // empty request ?
    if (!wsgi_req->uh->pktsize) {
        qCDebug(CUTELYST_UWSGI) << "Empty request. skip.";
        return -1;
    }

    // get uwsgi variables
    if (uwsgi_parse_vars(wsgi_req)) {
        qCDebug(CUTELYST_UWSGI) << "Invalid request. skip.";
        return -1;
    }

    coreEngines.at(wsgi_req->async_id)->processRequest(wsgi_req);

    return UWSGI_OK;
}

#ifdef UWSGI_GO_CHEAP_CODE // Actually we only need uwsgi 2.0.1
static void fsmon_reload(struct uwsgi_fsmon *fs)
{
    qCDebug(CUTELYST_UWSGI) << "Reloading application due to file change";
    uwsgi_reload(uwsgi.argv);
}
#endif // UWSGI_GO_CHEAP_CODE

/**
 * This function is called when the master process is exiting
 */
extern "C" void uwsgi_cutelyst_master_cleanup()
{
    qCDebug(CUTELYST_UWSGI) << "Master process finishing" << QCoreApplication::applicationPid();
    delete qApp;
    qCDebug(CUTELYST_UWSGI) << "Master process finished" << QCoreApplication::applicationPid();
}

/**
 * This function is called when the child process is exiting
 */
extern "C" void uwsgi_cutelyst_atexit()
{
    uwsgi_log("Child process finishing: %d\n", QCoreApplication::applicationPid());

    Q_FOREACH (EngineUwsgi *engine, coreEngines) {
        engine->stop();
    }
    qDeleteAll(coreEngines);

    uwsgi_log("Child process finished: %d\n", QCoreApplication::applicationPid());
}

extern "C" void uwsgi_cutelyst_init_apps()
{
    QString path(options.app);
    if (path.isEmpty()) {
        uwsgi_log("Cutelyst application name or path was not set\n");
        exit(1);
    }

    uwsgi_log("Cutelyst loading application: \"%s\"\n", options.app);

#ifdef UWSGI_GO_CHEAP_CODE
    if (options.reload) {
        // Register application auto reload
        char *file = qstrdup(path.toUtf8().constData());
        uwsgi_register_fsmon(file, fsmon_reload, NULL);
    }
#endif // UWSGI_GO_CHEAP_CODE

    QString config(options.config);
    if (!config.isNull()) {
        qputenv("CUTELYST_CONFIG", config.toUtf8());
    }

    QPluginLoader *loader = new QPluginLoader(path);
    if (!loader->load()) {
        uwsgi_log("Could not load application: %s\n", loader->errorString().data());
        exit(1);
    }

    QObject *instance = loader->instance();
    if (!instance) {
        uwsgi_log("Could not get a QObject instance: %s\n", loader->errorString().data());
        exit(1);
    }

    Application *app = qobject_cast<Application *>(instance);
    if (!app) {
        uwsgi_log("Could not cast Cutelyst::Application from instance: %s\n", loader->errorString().data());
        exit(1);
    }

    EngineUwsgi *mainEngine = new EngineUwsgi(app);
    if (!mainEngine->initApplication(app, false)) {
        uwsgi_log("Failed to init application.\n");
        exit(1);
    }
    coreEngines.append(mainEngine);

    EngineUwsgi *engine = mainEngine;
    for (int i = 0; i < uwsgi.cores; ++i) {
        // Create the desired threads
        // i > 0 the main thread counts as one thread
        if (uwsgi.threads > 1 && i > 0) {
            engine = new EngineUwsgi(app);
            engine->setThread(new QThread);

            // Post fork might fail when on threaded mode
            QObject::connect(engine, &EngineUwsgi::engineDisabled,
                             mainEngine, &EngineUwsgi::reuseEngineRequests);

            coreEngines.append(engine);
        }

        // Add core request
        struct wsgi_request *wsgi_req = new wsgi_request;
        memset(wsgi_req, 0, sizeof(struct wsgi_request));
        wsgi_req->async_id = i;
        engine->addUnusedRequest(wsgi_req);
    }

    // register a new app under a specific "mountpoint"
    uwsgi_add_app(1, CUTELYST_MODIFIER1, (char *) "", 0, NULL, NULL);

    delete loader;
}

void uwsgi_cutelyst_watch_signal(int signalFD)
{
    QSocketNotifier *socketNotifier = new QSocketNotifier(signalFD, QSocketNotifier::Read);
    QObject::connect(socketNotifier, &QSocketNotifier::activated,
                     [=](int fd) {
        socketNotifier->setEnabled(false);
        uwsgi_receive_signal(fd, (char *) "worker", uwsgi.mywid);
        socketNotifier->setEnabled(true);
    });
}

void uwsgi_cutelyst_loop()
{
    // ensure SIGPIPE is ignored
    signal(SIGPIPE, SIG_IGN);

    // FIX for some reason this is not being set by UWSGI
    uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;

    // monitor signals
    if (uwsgi.signal_socket > -1) {
        uwsgi_cutelyst_watch_signal(uwsgi.signal_socket);
        uwsgi_cutelyst_watch_signal(uwsgi.my_signal_socket);
    }

    // start the qt event loop
    qApp->exec();
}

void cuteOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    switch (type) {
    case QtDebugMsg:
        uwsgi_log("%s[debug] %s\n", context.category, localMsg.constData());
        break;
    case QtWarningMsg:
        uwsgi_log("%s[warn] %s\n", context.category, localMsg.constData());
        break;
    case QtCriticalMsg:
        uwsgi_log("%s[crit] %s\n", context.category, localMsg.constData());
        break;
    case QtFatalMsg:
        uwsgi_log("%s[fatal] %s\n", context.category, localMsg.constData());
        abort();
    }
}
<commit_msg>uWSGI Engine Wait 2 seconds to the application file to be filed when auto reload is enabled<commit_after>/*
 * Copyright (C) 2013-2014 Daniel Nicoletti <dantti12@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "engineuwsgi.h"
#include "plugin.h"

#include <Cutelyst/Application>

#include <QCoreApplication>
#include <QSocketNotifier>
#include <QPluginLoader>
#include <QFileInfo>

using namespace Cutelyst;

static QList<EngineUwsgi *> coreEngines;

void cuteOutput(QtMsgType, const QMessageLogContext &, const QString &);
void uwsgi_cutelyst_loop(void);

/**
 * This function is called as soon as
 * the plugin is loaded
 */
extern "C" void uwsgi_cutelyst_on_load()
{
    uwsgi_register_loop( (char *) "CutelystQtLoop", uwsgi_cutelyst_loop);

    (void) new QCoreApplication(uwsgi.argc, uwsgi.argv);

    if (qEnvironmentVariableIsEmpty("CUTELYST_NO_UWSGI_LOG")) {
        qInstallMessageHandler(cuteOutput);
    }
}

extern "C" int uwsgi_cutelyst_init()
{
    uwsgi_log("Initializing Cutelyst plugin\n");

    uwsgi.loop = (char *) "CutelystQtLoop";

    return 0;
}

extern "C" void uwsgi_cutelyst_post_fork()
{
    Q_FOREACH (EngineUwsgi *engine, coreEngines) {
        if (engine->thread() != qApp->thread()) {
            engine->thread()->start();
        } else {
            Q_EMIT engine->postFork();
        }
    }
}

extern "C" int uwsgi_cutelyst_request(struct wsgi_request *wsgi_req)
{
    // empty request ?
    if (!wsgi_req->uh->pktsize) {
        qCDebug(CUTELYST_UWSGI) << "Empty request. skip.";
        return -1;
    }

    // get uwsgi variables
    if (uwsgi_parse_vars(wsgi_req)) {
        qCDebug(CUTELYST_UWSGI) << "Invalid request. skip.";
        return -1;
    }

    coreEngines.at(wsgi_req->async_id)->processRequest(wsgi_req);

    return UWSGI_OK;
}

#ifdef UWSGI_GO_CHEAP_CODE // Actually we only need uwsgi 2.0.1
static void fsmon_reload(struct uwsgi_fsmon *fs)
{
    qCDebug(CUTELYST_UWSGI) << "Reloading application due to file change";
    QFileInfo fileInfo(fs->path);
    int count = 0;
    // Ugly hack to wait for 2 seconds for the file to be filled
    while (fileInfo.size() == 0 && count < 10) {
        ++count;
        qCDebug(CUTELYST_UWSGI) << "Sleeping as the application file is empty" << count;
        usleep(200 * 1000);
        fileInfo.refresh();
    }

    uwsgi_reload(uwsgi.argv);
}
#endif // UWSGI_GO_CHEAP_CODE

/**
 * This function is called when the master process is exiting
 */
extern "C" void uwsgi_cutelyst_master_cleanup()
{
    qCDebug(CUTELYST_UWSGI) << "Master process finishing" << QCoreApplication::applicationPid();
    delete qApp;
    qCDebug(CUTELYST_UWSGI) << "Master process finished" << QCoreApplication::applicationPid();
}

/**
 * This function is called when the child process is exiting
 */
extern "C" void uwsgi_cutelyst_atexit()
{
    uwsgi_log("Child process finishing: %d\n", QCoreApplication::applicationPid());

    Q_FOREACH (EngineUwsgi *engine, coreEngines) {
        engine->stop();
    }
    qDeleteAll(coreEngines);

    uwsgi_log("Child process finished: %d\n", QCoreApplication::applicationPid());
}

extern "C" void uwsgi_cutelyst_init_apps()
{
    QString path(options.app);
    if (path.isEmpty()) {
        uwsgi_log("Cutelyst application name or path was not set\n");
        exit(1);
    }

    uwsgi_log("Cutelyst loading application: \"%s\"\n", options.app);

#ifdef UWSGI_GO_CHEAP_CODE
    if (options.reload) {
        // Register application auto reload
        char *file = qstrdup(path.toUtf8().constData());
        uwsgi_register_fsmon(file, fsmon_reload, NULL);
    }
#endif // UWSGI_GO_CHEAP_CODE

    QString config(options.config);
    if (!config.isNull()) {
        qputenv("CUTELYST_CONFIG", config.toUtf8());
    }

    QPluginLoader *loader = new QPluginLoader(path);
    if (!loader->load()) {
        uwsgi_log("Could not load application: %s\n", loader->errorString().data());
        exit(1);
    }

    QObject *instance = loader->instance();
    if (!instance) {
        uwsgi_log("Could not get a QObject instance: %s\n", loader->errorString().data());
        exit(1);
    }

    Application *app = qobject_cast<Application *>(instance);
    if (!app) {
        uwsgi_log("Could not cast Cutelyst::Application from instance: %s\n", loader->errorString().data());
        exit(1);
    }

    EngineUwsgi *mainEngine = new EngineUwsgi(app);
    if (!mainEngine->initApplication(app, false)) {
        uwsgi_log("Failed to init application.\n");
        exit(1);
    }
    coreEngines.append(mainEngine);

    EngineUwsgi *engine = mainEngine;
    for (int i = 0; i < uwsgi.cores; ++i) {
        // Create the desired threads
        // i > 0 the main thread counts as one thread
        if (uwsgi.threads > 1 && i > 0) {
            engine = new EngineUwsgi(app);
            engine->setThread(new QThread);

            // Post fork might fail when on threaded mode
            QObject::connect(engine, &EngineUwsgi::engineDisabled,
                             mainEngine, &EngineUwsgi::reuseEngineRequests);

            coreEngines.append(engine);
        }

        // Add core request
        struct wsgi_request *wsgi_req = new wsgi_request;
        memset(wsgi_req, 0, sizeof(struct wsgi_request));
        wsgi_req->async_id = i;
        engine->addUnusedRequest(wsgi_req);
    }

    // register a new app under a specific "mountpoint"
    uwsgi_add_app(1, CUTELYST_MODIFIER1, (char *) "", 0, NULL, NULL);

    delete loader;
}

void uwsgi_cutelyst_watch_signal(int signalFD)
{
    QSocketNotifier *socketNotifier = new QSocketNotifier(signalFD, QSocketNotifier::Read);
    QObject::connect(socketNotifier, &QSocketNotifier::activated,
                     [=](int fd) {
        socketNotifier->setEnabled(false);
        uwsgi_receive_signal(fd, (char *) "worker", uwsgi.mywid);
        socketNotifier->setEnabled(true);
    });
}

void uwsgi_cutelyst_loop()
{
    // ensure SIGPIPE is ignored
    signal(SIGPIPE, SIG_IGN);

    // FIX for some reason this is not being set by UWSGI
    uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;

    // monitor signals
    if (uwsgi.signal_socket > -1) {
        uwsgi_cutelyst_watch_signal(uwsgi.signal_socket);
        uwsgi_cutelyst_watch_signal(uwsgi.my_signal_socket);
    }

    // start the qt event loop
    qApp->exec();
}

void cuteOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    switch (type) {
    case QtDebugMsg:
        uwsgi_log("%s[debug] %s\n", context.category, localMsg.constData());
        break;
    case QtWarningMsg:
        uwsgi_log("%s[warn] %s\n", context.category, localMsg.constData());
        break;
    case QtCriticalMsg:
        uwsgi_log("%s[crit] %s\n", context.category, localMsg.constData());
        break;
    case QtFatalMsg:
        uwsgi_log("%s[fatal] %s\n", context.category, localMsg.constData());
        abort();
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stack>
using namesspace std;

int evaluateOp(char operator,int numberStack, char operatorStack)
{
	int leftValue = numberStack.pop();
	int rightValue = numberStack.pop();
	int result;
	switch(operator)
	{
		case '+':
		result = leftValue + rightValue;
		return result;
		break;
		case '-':
		result = leftValue - rightValue;
		return result;
		break;

	}
}

int main()
{

	/* code */
	return 0;
}

//changes each token
istringstream tokens();
char nextChar;
stack<int> numberStack;
stack<char> operatorStack;

while (tokens >> nextChar){
	if (isdigit(nextChar)){
		tokens.push()			//add to integer stack
		int number;
		tokens >> number; //converts the characters to ints
		numberStack.push(number);
	}
	else if (isOperator(nextChar)){
		int weight = precedenceOfOperator(nextChar);
		int stackWeight = precedenceOfOperator(operatorStack.top())
		if(weight >= stackWeight)
		{
			operatorStack.push(nextChar);
		}
		else
		{

		}
	}
	else{
		throw caseErrors(" ");
	}
}<commit_msg>almost complete evaluateOp<commit_after>#include <iostream>
#include <cmath>
#include <stack>
using namesspace std;

int evaluateOp(char theOperator,int numberStack, char operatorStack)
{
	int leftValue = numberStack.pop();
	int rightValue = numberStack.pop();
	int result;
	switch(theOperator)
	{
		case '+'://adds the two number and returns the value
			result = leftValue + rightValue;
			return result;
			break;
		case '-'://subtracts the two number and returns the value
			result = leftValue - rightValue;
			return result;
			break;
		case '/'://divides the two number and returns the value
			result = leftValue / rightValue;
			return result;
			break;
		case '*'://multiplies the two number and returns the value
			result = leftValue * rightValue;
			return result;
			break;
		case'^'://exponent
			result = pow(leftValue, rightValue);
			return result;
			break;
		case'%'://mod operator
			result = leftValue % rightValue;
			return result;
			break;
		case'!'://logical not
			result = 0; //false
			return result;
			break;
		case'A'://increments the left value by one ++
			leftValue++;
			return leftValue;
			break;
		case'B'://decrements the left value by one --
			leftValue--;
			return leftValue;
			break;
		case'C'://checks to see if two values are equal ==
			if (leftValue == rightValue)//if they're equal return 1 for true
			{
				result = 1;//true
				return result;
			}
			else//else return 0 for false
			{
				result = 0;//false
				return result;
			}
			break;
		case'D'://checks to see if left value is not equal to right value !=
			if (leftValue != rightValue)//returns true(1) if they are not equal
			{
				result = 1;//true
				return result;
			}
			else//if they are equal returns false(0)
			{
				result = 0;//false
				return result;
			}
			break;
		case'E'://logical and operator &&
			break;
		case'F'://logical or operator ||
			result = 1;//true
			return result;
			break;
		case'G'://greater than or equal
			if (leftValue >= rightValue)
			{
				result = 1;//true
				return result;
			}
			else
			{
				result = 0;//false
				return result;
			}
			break;
		case'H'://less than or equal
			if (leftValue <= rightValue)

			{
				result = 1;//true
				return result;
			}
			else
			{
				result = 0;//false
				return result;
			}
			break;
		case'I'://negative
			result = leftValue * -1;
			return result;
			break;

	}
}

int main()
{

	/* code */
	return 0;
}

//changes each token
istringstream tokens();
char nextChar;
stack<int> numberStack;
stack<char> operatorStack;

while (tokens >> nextChar){
	if (isdigit(nextChar)){
		tokens.push()			//add to integer stack
		int number;
		tokens >> number; //converts the characters to ints
		numberStack.push(number);
	}
	else if (isOperator(nextChar)){
		int weight = precedenceOfOperator(nextChar);
		int stackWeight = precedenceOfOperator(operatorStack.top())
		if(weight >= stackWeight)
		{
			operatorStack.push(nextChar);
		}
		else
		{

		}
	}
	else{
		throw caseErrors(" ");
	}
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "debugutil_p.h"

#include <QEventLoop>
#include <QTimer>

bool QQmlDebugTest::waitForSignal(QObject *receiver, const char *member, int timeout) {
    QEventLoop loop;
    QTimer timer;
    timer.setSingleShot(true);
    QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    QObject::connect(receiver, member, &loop, SLOT(quit()));
    timer.start(timeout);
    loop.exec();
    return timer.isActive();
}

QQmlDebugTestClient::QQmlDebugTestClient(const QString &s, QQmlDebugConnection *c)
    : QQmlDebugClient(s, c)
{
}

QByteArray QQmlDebugTestClient::waitForResponse()
{
    lastMsg.clear();
    QQmlDebugTest::waitForSignal(this, SIGNAL(serverMessage(QByteArray)));
    if (lastMsg.isEmpty()) {
        qWarning() << "no response from server!";
        return QByteArray();
    }
    return lastMsg;
}

void QQmlDebugTestClient::stateChanged(State stat)
{
    QCOMPARE(stat, state());
    emit stateHasChanged();
}

void QQmlDebugTestClient::messageReceived(const QByteArray &ba)
{
    lastMsg = ba;
    emit serverMessage(ba);
}

QQmlDebugProcess::QQmlDebugProcess(const QString &executable, QObject *parent)
    : QObject(parent)
    , m_executable(executable)
    , m_started(false)
{
    m_process.setProcessChannelMode(QProcess::MergedChannels);
    m_timer.setSingleShot(true);
    m_timer.setInterval(5000);
    connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processAppOutput()));
    connect(&m_timer, SIGNAL(timeout()), SLOT(timeout()));
}

QQmlDebugProcess::~QQmlDebugProcess()
{
    stop();
}

QString QQmlDebugProcess::state()
{
    QString stateStr;
    switch (m_process.state()) {
    case QProcess::NotRunning: {
        stateStr = "not running";
        if (m_process.exitStatus() == QProcess::CrashExit)
            stateStr += " (crashed!)";
        else
            stateStr += ", return value" + m_process.exitCode();
        break;
    }
    case QProcess::Starting: stateStr = "starting"; break;
    case QProcess::Running: stateStr = "running"; break;
    }
    return stateStr;
}

void QQmlDebugProcess::start(const QStringList &arguments)
{
    m_mutex.lock();
    m_process.setEnvironment(m_environment);
    m_process.start(m_executable, arguments);
    if (!m_process.waitForStarted()) {
        qWarning() << "QML Debug Client: Could not launch app " << m_executable
                   << ": " << m_process.errorString();
        m_eventLoop.quit();
    } else {
        m_timer.start();
    }
    m_mutex.unlock();
}

void QQmlDebugProcess::stop()
{
    if (m_process.state() != QProcess::NotRunning) {
        m_process.kill();
        m_process.waitForFinished(5000);
    }
}

void QQmlDebugProcess::timeout()
{
    qWarning() << "Timeout while waiting for QML debugging messages "
                  "in application output. Process is in state" << m_process.state() << ".";
    m_eventLoop.quit();
}

bool QQmlDebugProcess::waitForSessionStart()
{
    if (m_process.state() != QProcess::Running) {
        qWarning() << "Could not start up " << m_executable;
        return false;
    }
    m_eventLoop.exec();

    return m_started;
}

void QQmlDebugProcess::setEnvironment(const QStringList &environment)
{
    m_environment = environment;
}

QString QQmlDebugProcess::output() const
{
    return m_output;
}

void QQmlDebugProcess::processAppOutput()
{
    m_mutex.lock();

    QString newOutput = m_process.readAll();
    m_output.append(newOutput);
    m_outputBuffer.append(newOutput);

    while (true) {
        const int nlIndex = m_outputBuffer.indexOf(QLatin1Char('\n'));
        if (nlIndex < 0) // no further complete lines
            break;
        const QString line = m_outputBuffer.left(nlIndex);
        m_outputBuffer = m_outputBuffer.right(m_outputBuffer.size() - nlIndex - 1);

        if (line.contains("QML Debugger:")) {
            if (line.contains("Waiting for connection ")) {
                m_timer.stop();
                m_started = true;
                m_eventLoop.quit();
                continue;
            }
            if (line.contains("Unable to listen")) {
                qWarning() << "App was unable to bind to port!";
                m_timer.stop();
                m_eventLoop.quit();
                continue;
            }
        }
    }
    m_mutex.unlock();
}
<commit_msg>When declarative debug tests fail in CI, confirm timeout as reason<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "debugutil_p.h"

#include <QEventLoop>
#include <QTimer>

bool QQmlDebugTest::waitForSignal(QObject *receiver, const char *member, int timeout) {
    QEventLoop loop;
    QTimer timer;
    timer.setSingleShot(true);
    QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    QObject::connect(receiver, member, &loop, SLOT(quit()));
    timer.start(timeout);
    loop.exec();
    if (!timer.isActive())
        qWarning("waitForSignal %s timed out after %d ms", member, timeout);
    return timer.isActive();
}

QQmlDebugTestClient::QQmlDebugTestClient(const QString &s, QQmlDebugConnection *c)
    : QQmlDebugClient(s, c)
{
}

QByteArray QQmlDebugTestClient::waitForResponse()
{
    lastMsg.clear();
    QQmlDebugTest::waitForSignal(this, SIGNAL(serverMessage(QByteArray)));
    if (lastMsg.isEmpty()) {
        qWarning() << "no response from server!";
        return QByteArray();
    }
    return lastMsg;
}

void QQmlDebugTestClient::stateChanged(State stat)
{
    QCOMPARE(stat, state());
    emit stateHasChanged();
}

void QQmlDebugTestClient::messageReceived(const QByteArray &ba)
{
    lastMsg = ba;
    emit serverMessage(ba);
}

QQmlDebugProcess::QQmlDebugProcess(const QString &executable, QObject *parent)
    : QObject(parent)
    , m_executable(executable)
    , m_started(false)
{
    m_process.setProcessChannelMode(QProcess::MergedChannels);
    m_timer.setSingleShot(true);
    m_timer.setInterval(5000);
    connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processAppOutput()));
    connect(&m_timer, SIGNAL(timeout()), SLOT(timeout()));
}

QQmlDebugProcess::~QQmlDebugProcess()
{
    stop();
}

QString QQmlDebugProcess::state()
{
    QString stateStr;
    switch (m_process.state()) {
    case QProcess::NotRunning: {
        stateStr = "not running";
        if (m_process.exitStatus() == QProcess::CrashExit)
            stateStr += " (crashed!)";
        else
            stateStr += ", return value" + m_process.exitCode();
        break;
    }
    case QProcess::Starting: stateStr = "starting"; break;
    case QProcess::Running: stateStr = "running"; break;
    }
    return stateStr;
}

void QQmlDebugProcess::start(const QStringList &arguments)
{
    m_mutex.lock();
    m_process.setEnvironment(m_environment);
    m_process.start(m_executable, arguments);
    if (!m_process.waitForStarted()) {
        qWarning() << "QML Debug Client: Could not launch app " << m_executable
                   << ": " << m_process.errorString();
        m_eventLoop.quit();
    } else {
        m_timer.start();
    }
    m_mutex.unlock();
}

void QQmlDebugProcess::stop()
{
    if (m_process.state() != QProcess::NotRunning) {
        m_process.kill();
        m_process.waitForFinished(5000);
    }
}

void QQmlDebugProcess::timeout()
{
    qWarning() << "Timeout while waiting for QML debugging messages "
                  "in application output. Process is in state" << m_process.state() << ".";
    m_eventLoop.quit();
}

bool QQmlDebugProcess::waitForSessionStart()
{
    if (m_process.state() != QProcess::Running) {
        qWarning() << "Could not start up " << m_executable;
        return false;
    }
    m_eventLoop.exec();

    return m_started;
}

void QQmlDebugProcess::setEnvironment(const QStringList &environment)
{
    m_environment = environment;
}

QString QQmlDebugProcess::output() const
{
    return m_output;
}

void QQmlDebugProcess::processAppOutput()
{
    m_mutex.lock();

    QString newOutput = m_process.readAll();
    m_output.append(newOutput);
    m_outputBuffer.append(newOutput);

    while (true) {
        const int nlIndex = m_outputBuffer.indexOf(QLatin1Char('\n'));
        if (nlIndex < 0) // no further complete lines
            break;
        const QString line = m_outputBuffer.left(nlIndex);
        m_outputBuffer = m_outputBuffer.right(m_outputBuffer.size() - nlIndex - 1);

        if (line.contains("QML Debugger:")) {
            if (line.contains("Waiting for connection ")) {
                m_timer.stop();
                m_started = true;
                m_eventLoop.quit();
                continue;
            }
            if (line.contains("Unable to listen")) {
                qWarning() << "App was unable to bind to port!";
                m_timer.stop();
                m_eventLoop.quit();
                continue;
            }
        }
    }
    m_mutex.unlock();
}
<|endoftext|>


<commit_before>#include <QApplication>
#include <QDir>
#include <QTextStream>
#include <QTimer>

#include "run-scenario.h"

RunScenario::RunScenario()
{
    _rootDir = QDir::currentPath() + QDir::separator() + "dirs";

    // Set up model.
    _model.setReadOnly(true);
    _model.setRootPath(_rootDir);

    // In the GUI, we cannot select a file or directory until its parent
    // directory has been loaded.  This is not a perfect imitation of that
    // scenario, but it is better than nothing.
    while(needToReadSubdirs(_rootDir))
        QCoreApplication::processEvents(0, 100);
}

RunScenario::~RunScenario()
{
}

bool RunScenario::needToReadSubdirs(const QString dirname)
{
    bool        loadingMore = false;
    QModelIndex dir         = _model.index(dirname);
    // QFileSystemModel::canFetchMore(dir) can apparently lie about whether
    // its has finished loading a directory.  Alternatively, it might be
    // designed to merely report that a directory has been *queued* to be
    // read, but not actually read yet, and the Qt docs were simply written
    // badly.
    // Either way, we must ASSUME that every directory which contains 0 items
    // has not finished being read from disk.
    if(_model.isDir(dir) && _model.rowCount(dir) == 0)
    {
        _model.fetchMore(dir);
        loadingMore = true;
    }
    for(int i = 0; i < _model.rowCount(dir); i++)
    {
        QModelIndex child = dir.child(i, dir.column());
        if(_model.isDir(child))
        {
            if(_model.rowCount(child) == 0)
            {
                _model.fetchMore(child);
                loadingMore = true;
            }
            if(needToReadSubdirs(_model.filePath(child)))
            {
                loadingMore = true;
            }
        }
    }
    return loadingMore;
}

// The format of these lines in the scenario file is:
// X filename
// where X is a single character, followed by a space.
QString RunScenario::getRelname(const QString line)
{
    QString relname = line.right(line.size() - 2);
    return relname;
}

QModelIndex RunScenario::getIndex(const QString line)
{
    QString     relname  = getRelname(line);
    QString     filename = QDir(_rootDir).filePath(relname);
    QModelIndex index    = _model.index(filename);
    return index;
}

int RunScenario::getLineState(const QString line)
{
    int state = line[0].digitValue();
    return state;
}

int RunScenario::getCheckedStateInt(const QString line)
{
    QString     relname  = line.right(line.size() - 2);
    QString     filename = QDir(_rootDir).filePath(relname);
    QModelIndex index    = _model.index(filename);
    int         state    = _model.data(index, Qt::CheckStateRole).toInt();
    return state;
}

int RunScenario::processActions(QTextStream &in)
{
    while(!in.atEnd())
    {
        QString line = in.readLine();
        // Blank lines and comments.
        if((line.size() == 0) || (line[0] == QChar('#')))
            continue;
        else if(line == "actions:")
            continue;
        else if(line == "results:")
            break;
        else if(line[0] == QChar('+'))
            _model.setData(getIndex(line), Qt::Checked, Qt::CheckStateRole);
        else if(line[0] == QChar('-'))
            _model.setData(getIndex(line), Qt::Unchecked, Qt::CheckStateRole);
        else
        {
            QTextStream console(stdout);
            console << "ERROR: Scenario file is broken; parsing died on line:"
                    << endl
                    << line << endl;
            // Don't try to recover.
            QApplication::exit(1);
        }
    }
    return (0);
}

// Returns 0 if success, 1 if a model error, 2 if an emit error.
int RunScenario::processResults(QTextStream &in)
{
    while(!in.atEnd())
    {
        QString line = in.readLine();
        // Blank lines and comments.
        if((line.size() == 0) || (line[0] == QChar('#')))
            continue;
        else if(line == "results:")
            continue;
        else if((line[0] == QChar('0')) || (line[0] == QChar('1'))
                || (line[0] == QChar('2')))
        {
            QString lineRelname  = getRelname(line);
            int     desiredState = getLineState(line);
            int     modelState   = getCheckedStateInt(line);
            if(desiredState != modelState)
            {
                // Test failed!
                return (1);
            }
        }
        else
        {
            QTextStream console(stdout);
            console << "ERROR: Scenario file is broken; parsing died on line:"
                    << endl
                    << line << endl;
            // Don't try to recover.
            QApplication::exit(1);
        }
    }
    return (0);
}

int RunScenario::runScenario(const int num)
{
    int result = -1;
    _model.reset();

    QString scenarioFilename =
        QString("scenario-%1.txt").arg(num, 2, 10, QChar('0'));
    QFile inputFile(scenarioFilename);
    if(inputFile.open(QIODevice::ReadOnly))
    {
        QTextStream in(&inputFile);
        processActions(in);
        result = processResults(in);
        if(result != 0)
        {
            // Test failed!
            QTextStream console(stdout);
            console << "--" << endl
                    << "Test failed: " << scenarioFilename << endl;
            if(result == 1)
            {
                console << "Model internal state does not match "
                        << "desired state.  Model data:" << endl;
                printModel();
            }
            console << "--" << endl << endl;
        }
    }
    else
    {
        QTextStream console(stdout);
        console << "ERROR: could not read file: " << scenarioFilename << endl;
        // Don't try to recover.
        QApplication::exit(1);
    }
    inputFile.close();

    return (result);
}

void RunScenario::printDir(const QString dirname, const int depth)
{
    QTextStream console(stdout);
    QModelIndex index;
    QModelIndex dir;

    dir = _model.index(dirname);
    for(int i = 0; i < _model.rowCount(dir); i++)
    {
        index = dir.child(i, dir.column());
        console << _model.data(index, Qt::CheckStateRole).toInt() << "\t";
        // Add indents to show the directory structure.
        for(int j = 0; j < depth; j++)
            console << "\t";
        console << _model.fileName(index) << endl;
        // Recursively print the subdirectory.
        if(_model.isDir(index))
        {
            printDir(_model.filePath(index), depth + 1);
        }
    }
}

void RunScenario::printModel()
{
    printDir(_model.rootPath(), 0);
}
<commit_msg>tests/customfilesystemmodel: use needToReadSubdirs()<commit_after>#include <QApplication>
#include <QDir>
#include <QTextStream>
#include <QTimer>

#include "run-scenario.h"

RunScenario::RunScenario()
{
    _rootDir = QDir::currentPath() + QDir::separator() + "dirs";

    // Set up model.
    _model.setReadOnly(true);
    _model.setRootPath(_rootDir);

    // In the GUI, we cannot select a file or directory until its parent
    // directory has been loaded.  This is not a perfect imitation of that
    // scenario, but it is better than nothing.
    while(_model.needToReadSubdirs(_rootDir))
        QCoreApplication::processEvents(0, 100);
}

RunScenario::~RunScenario()
{
}

// The format of these lines in the scenario file is:
// X filename
// where X is a single character, followed by a space.
QString RunScenario::getRelname(const QString line)
{
    QString relname = line.right(line.size() - 2);
    return relname;
}

QModelIndex RunScenario::getIndex(const QString line)
{
    QString     relname  = getRelname(line);
    QString     filename = QDir(_rootDir).filePath(relname);
    QModelIndex index    = _model.index(filename);
    return index;
}

int RunScenario::getLineState(const QString line)
{
    int state = line[0].digitValue();
    return state;
}

int RunScenario::getCheckedStateInt(const QString line)
{
    QString     relname  = line.right(line.size() - 2);
    QString     filename = QDir(_rootDir).filePath(relname);
    QModelIndex index    = _model.index(filename);
    int         state    = _model.data(index, Qt::CheckStateRole).toInt();
    return state;
}

int RunScenario::processActions(QTextStream &in)
{
    while(!in.atEnd())
    {
        QString line = in.readLine();
        // Blank lines and comments.
        if((line.size() == 0) || (line[0] == QChar('#')))
            continue;
        else if(line == "actions:")
            continue;
        else if(line == "results:")
            break;
        else if(line[0] == QChar('+'))
            _model.setData(getIndex(line), Qt::Checked, Qt::CheckStateRole);
        else if(line[0] == QChar('-'))
            _model.setData(getIndex(line), Qt::Unchecked, Qt::CheckStateRole);
        else
        {
            QTextStream console(stdout);
            console << "ERROR: Scenario file is broken; parsing died on line:"
                    << endl
                    << line << endl;
            // Don't try to recover.
            QApplication::exit(1);
        }
    }
    return (0);
}

// Returns 0 if success, 1 if a model error, 2 if an emit error.
int RunScenario::processResults(QTextStream &in)
{
    while(!in.atEnd())
    {
        QString line = in.readLine();
        // Blank lines and comments.
        if((line.size() == 0) || (line[0] == QChar('#')))
            continue;
        else if(line == "results:")
            continue;
        else if((line[0] == QChar('0')) || (line[0] == QChar('1'))
                || (line[0] == QChar('2')))
        {
            QString lineRelname  = getRelname(line);
            int     desiredState = getLineState(line);
            int     modelState   = getCheckedStateInt(line);
            if(desiredState != modelState)
            {
                // Test failed!
                return (1);
            }
        }
        else
        {
            QTextStream console(stdout);
            console << "ERROR: Scenario file is broken; parsing died on line:"
                    << endl
                    << line << endl;
            // Don't try to recover.
            QApplication::exit(1);
        }
    }
    return (0);
}

int RunScenario::runScenario(const int num)
{
    int result = -1;
    _model.reset();

    QString scenarioFilename =
        QString("scenario-%1.txt").arg(num, 2, 10, QChar('0'));
    QFile inputFile(scenarioFilename);
    if(inputFile.open(QIODevice::ReadOnly))
    {
        QTextStream in(&inputFile);
        processActions(in);
        result = processResults(in);
        if(result != 0)
        {
            // Test failed!
            QTextStream console(stdout);
            console << "--" << endl
                    << "Test failed: " << scenarioFilename << endl;
            if(result == 1)
            {
                console << "Model internal state does not match "
                        << "desired state.  Model data:" << endl;
                printModel();
            }
            console << "--" << endl << endl;
        }
    }
    else
    {
        QTextStream console(stdout);
        console << "ERROR: could not read file: " << scenarioFilename << endl;
        // Don't try to recover.
        QApplication::exit(1);
    }
    inputFile.close();

    return (result);
}

void RunScenario::printDir(const QString dirname, const int depth)
{
    QTextStream console(stdout);
    QModelIndex index;
    QModelIndex dir;

    dir = _model.index(dirname);
    for(int i = 0; i < _model.rowCount(dir); i++)
    {
        index = dir.child(i, dir.column());
        console << _model.data(index, Qt::CheckStateRole).toInt() << "\t";
        // Add indents to show the directory structure.
        for(int j = 0; j < depth; j++)
            console << "\t";
        console << _model.fileName(index) << endl;
        // Recursively print the subdirectory.
        if(_model.isDir(index))
        {
            printDir(_model.filePath(index), depth + 1);
        }
    }
}

void RunScenario::printModel()
{
    printDir(_model.rootPath(), 0);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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.
 */

#include "src/trace_processor/trace_database.h"

#include <functional>

namespace perfetto {
namespace trace_processor {
namespace {
constexpr uint32_t kTraceChunkSizeB = 16 * 1024 * 1024;  // 16 MB
static const char kUIntColumnName[] = "UNSIGNED INT";
static const char kULongColumnName[] = "UNSIGNED BIG INT";

bool IsColumnUInt(const char* type) {
  return strncmp(type, kUIntColumnName, sizeof(kUIntColumnName)) == 0;
}

bool IsColumnULong(const char* type) {
  return strncmp(type, kULongColumnName, sizeof(kULongColumnName)) == 0;
}
}  // namespace

TraceDatabase::TraceDatabase(base::TaskRunner* task_runner)
    : task_runner_(task_runner), weak_factory_(this) {
  static_assert(offsetof(TraceDatabase, db_) == 0,
                "SQLite database must be the first field.");
  sqlite3_open(":memory:", &db_);

  // Setup the sched slice table.
  static sqlite3_module module = SchedSliceTable::CreateModule();
  sqlite3_create_module(db_, "sched", &module, static_cast<void*>(&storage_));
}

TraceDatabase::~TraceDatabase() {
  sqlite3_close(db_);
}

void TraceDatabase::LoadTrace(BlobReader* reader,
                              std::function<void()> callback) {
  // Reset storage and start a new trace parsing task.
  storage_ = {};
  parser_.reset(new TraceParser(reader, &storage_, kTraceChunkSizeB));
  LoadTraceChunk(callback);
}

void TraceDatabase::ExecuteQuery(
    const protos::RawQueryArgs& args,
    std::function<void(protos::RawQueryResult)> callback) {
  protos::RawQueryResult proto;

  const auto& sql = args.sql_query();
  sqlite3_stmt* stmt;
  int err = sqlite3_prepare_v2(db_, sql.c_str(), static_cast<int>(sql.size()),
                               &stmt, nullptr);
  if (err) {
    callback(std::move(proto));
    return;
  }

  for (int i = 0, size = sqlite3_column_count(stmt); i < size; i++) {
    // Setup the descriptors.
    auto* descriptor = proto.add_column_descriptors();
    descriptor->set_name(sqlite3_column_name(stmt, i));

    const char* type = sqlite3_column_decltype(stmt, i);
    if (IsColumnUInt(type)) {
      descriptor->set_type(protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_INT);
    } else if (IsColumnULong(type)) {
      descriptor->set_type(
          protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_LONG);
    } else {
      PERFETTO_FATAL("Unexpected column type found in SQL query");
    }

    // Add the empty column to the proto.
    proto.add_columns();
  }

  int row_count = 0;
  for (int r = sqlite3_step(stmt); r == SQLITE_ROW; r = sqlite3_step(stmt)) {
    for (int i = 0; i < proto.columns_size(); i++) {
      auto* column = proto.mutable_columns(i);
      switch (proto.column_descriptors(i).type()) {
        case protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_LONG:
          column->add_ulong_values(
              static_cast<uint64_t>(sqlite3_column_int64(stmt, i)));
          break;
        case protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_INT:
          column->add_uint_values(
              static_cast<uint32_t>(sqlite3_column_double(stmt, i)));
          break;
        case protos::RawQueryResult_ColumnDesc_Type_INT:
        case protos::RawQueryResult_ColumnDesc_Type_LONG:
        case protos::RawQueryResult_ColumnDesc_Type_STRING:
          PERFETTO_FATAL("Unexpected column type found in SQL query");
          break;
      }
    }
    row_count++;
  }
  proto.set_num_records(static_cast<uint64_t>(row_count));

  callback(std::move(proto));
}

void TraceDatabase::LoadTraceChunk(std::function<void()> callback) {
  bool has_more = parser_->ParseNextChunk();
  if (!has_more) {
    callback();
    return;
  }

  auto weak_this = weak_factory_.GetWeakPtr();
  task_runner_->PostTask([weak_this, callback] {
    if (!weak_this)
      return;

    weak_this->LoadTraceChunk(callback);
  });
}

}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>trace_processor: fix build when offsetof was being used on non-POD am: 4ce4cb8263 am: 008381a2d7 am: d8f449b543<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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.
 */

#include "src/trace_processor/trace_database.h"

#include <functional>

namespace perfetto {
namespace trace_processor {
namespace {
constexpr uint32_t kTraceChunkSizeB = 16 * 1024 * 1024;  // 16 MB
static const char kUIntColumnName[] = "UNSIGNED INT";
static const char kULongColumnName[] = "UNSIGNED BIG INT";

bool IsColumnUInt(const char* type) {
  return strncmp(type, kUIntColumnName, sizeof(kUIntColumnName)) == 0;
}

bool IsColumnULong(const char* type) {
  return strncmp(type, kULongColumnName, sizeof(kULongColumnName)) == 0;
}
}  // namespace

TraceDatabase::TraceDatabase(base::TaskRunner* task_runner)
    : task_runner_(task_runner), weak_factory_(this) {
  sqlite3_open(":memory:", &db_);

  // Setup the sched slice table.
  static sqlite3_module module = SchedSliceTable::CreateModule();
  sqlite3_create_module(db_, "sched", &module, static_cast<void*>(&storage_));
}

TraceDatabase::~TraceDatabase() {
  sqlite3_close(db_);
}

void TraceDatabase::LoadTrace(BlobReader* reader,
                              std::function<void()> callback) {
  // Reset storage and start a new trace parsing task.
  storage_ = {};
  parser_.reset(new TraceParser(reader, &storage_, kTraceChunkSizeB));
  LoadTraceChunk(callback);
}

void TraceDatabase::ExecuteQuery(
    const protos::RawQueryArgs& args,
    std::function<void(protos::RawQueryResult)> callback) {
  protos::RawQueryResult proto;

  const auto& sql = args.sql_query();
  sqlite3_stmt* stmt;
  int err = sqlite3_prepare_v2(db_, sql.c_str(), static_cast<int>(sql.size()),
                               &stmt, nullptr);
  if (err) {
    callback(std::move(proto));
    return;
  }

  for (int i = 0, size = sqlite3_column_count(stmt); i < size; i++) {
    // Setup the descriptors.
    auto* descriptor = proto.add_column_descriptors();
    descriptor->set_name(sqlite3_column_name(stmt, i));

    const char* type = sqlite3_column_decltype(stmt, i);
    if (IsColumnUInt(type)) {
      descriptor->set_type(protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_INT);
    } else if (IsColumnULong(type)) {
      descriptor->set_type(
          protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_LONG);
    } else {
      PERFETTO_FATAL("Unexpected column type found in SQL query");
    }

    // Add the empty column to the proto.
    proto.add_columns();
  }

  int row_count = 0;
  for (int r = sqlite3_step(stmt); r == SQLITE_ROW; r = sqlite3_step(stmt)) {
    for (int i = 0; i < proto.columns_size(); i++) {
      auto* column = proto.mutable_columns(i);
      switch (proto.column_descriptors(i).type()) {
        case protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_LONG:
          column->add_ulong_values(
              static_cast<uint64_t>(sqlite3_column_int64(stmt, i)));
          break;
        case protos::RawQueryResult_ColumnDesc_Type_UNSIGNED_INT:
          column->add_uint_values(
              static_cast<uint32_t>(sqlite3_column_double(stmt, i)));
          break;
        case protos::RawQueryResult_ColumnDesc_Type_INT:
        case protos::RawQueryResult_ColumnDesc_Type_LONG:
        case protos::RawQueryResult_ColumnDesc_Type_STRING:
          PERFETTO_FATAL("Unexpected column type found in SQL query");
          break;
      }
    }
    row_count++;
  }
  proto.set_num_records(static_cast<uint64_t>(row_count));

  callback(std::move(proto));
}

void TraceDatabase::LoadTraceChunk(std::function<void()> callback) {
  bool has_more = parser_->ParseNextChunk();
  if (!has_more) {
    callback();
    return;
  }

  auto weak_this = weak_factory_.GetWeakPtr();
  task_runner_->PostTask([weak_this, callback] {
    if (!weak_this)
      return;

    weak_this->LoadTraceChunk(callback);
  });
}

}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>