<commit_before>#include <cassert>
#include <iostream>
#include <cmath>
#include "common.h"
#include GLUT_INCLUDE
#include "Decimate.h"
#include "Array3D.h"

static inline void drawVert(const Isosurface& surface, const Point3D& p1, const Point3D& p2, float isolevel)
{

    float v1 = p1.value;
    float v2 = p2.value;

    float x, y, z;

    if (v2 == v1) {
        x = (p1.x + p2.x) / 2.0f;
        y = (p1.y + p2.y) / 2.0f;
        z = (p1.z + p2.z) / 2.0f;
    } else {

        /*

         <----+-----+---+----->
              v1    |   v2
                 isolevel

         <----+-----+---+----->
              0     |   1
                  interp

         */

        // interp == 0: vert should be at p1
        // interp == 1: vert should be at p2
        float interp = (isolevel - v1) / (v2 - v1);
        float oneMinusInterp = 1 - interp;

        x = p1.x * oneMinusInterp + p2.x * interp;
        y = p1.y * oneMinusInterp + p2.y * interp;
        z = p1.z * oneMinusInterp + p2.z * interp;
    }

    Vector3D normal = surface.gradientAt(x, y, z);

    glNormal3f(normal.x, normal.y, normal.z);
    glVertex3f(x, y, z);
}

static void drawTetrahedron(const Isosurface& surface, const Point3D p[4], float isolevel)
{

    /*

     Tetrahedron layout:

           0
           *
          /|
         / |
      3 *-----* 1
         \ | /
          \|/
           *
           2
     */

    unsigned char index = 0;
    for (int i = 0; i < 4; ++i)
        if (p[i].value < isolevel)
            index |= (1 << i);

    switch (index) {

        // we don't do anything if everyone is inside or outside
        case 0x00:
        case 0x0F:
            break;

        // only vert 0 is inside
        case 0x01:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            break;

        // only vert 1 is inside
        case 0x02:
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            break;

        // only vert 2 is inside
        case 0x04:
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            break;

        // only vert 3 is inside
        case 0x08:
            drawVert(surface, p[3], p[1], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            break;

        // verts 0, 1 are inside
        case 0x03:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);

            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            break;

        // verts 0, 2 are inside
        case 0x05:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[1], p[0], isolevel);

            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            break;

        // verts 0, 3 are inside
        case 0x09:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);

            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            break;

        // verts 1, 2 are inside
        case 0x06:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[1], p[3], isolevel);

            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            break;

        // verts 2, 3 are inside
        case 0x0C:
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[3], p[0], isolevel);

            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            break;

        // verts 1, 3 are inside
        case 0x0A:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);

            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            break;

        // verts 0, 1, 2 are inside
        case 0x07:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[3], p[1], isolevel);
            break;

        // verts 0, 1, 3 are inside
        case 0x0B:
            drawVert(surface, p[2], p[1], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            break;

        // verts 0, 2, 3 are inside
        case 0x0D:
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            break;

        // verts 1, 2, 3 are inside
        case 0x0E:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[0], p[3], isolevel);
            break;

        // what is this I don't even
        default:
            assert(false);
    }

}

void decimate(const Isosurface& surface,
              float xMin, float xMax,
              float yMin, float yMax,
              float zMin, float zMax,
              float isolevel,
              std::size_t resolution) // resolution indicates # of cubes
{

    std::size_t pointRes = resolution + 1; // indicates the # of points per side

    float xrange = xMax - xMin;
    float yrange = yMax - yMin;
    float zrange = zMax - zMin;

    Array3D<float> grid(pointRes, pointRes, pointRes);

    for (std::size_t i = 0; i <= resolution; ++i) {
        float x = (float)i/resolution * xrange + xMin;
        for (std::size_t j = 0; j <= resolution; ++j) {
            float y = (float)j/resolution * yrange + yMin;
            for (std::size_t k = 0; k <= resolution; ++k) {
                float z = (float)k/resolution * zrange + zMin;
                float value = surface.valueAt(x, y, z);
                grid.set(i, j, k, value);
            }
        }
    }

    glBegin(GL_TRIANGLES);
    for (std::size_t i = 0; i < resolution; ++i) {
        float x1 = (float)i/resolution * xrange + xMin;
        float x2 = (float)(i+1)/resolution * xrange + xMin;
        for (std::size_t j = 0; j < resolution; ++j) {
            float y1 = (float)j/resolution * yrange + yMin;
            float y2 = (float)(j+1)/resolution * yrange + yMin;
            for (std::size_t k = 0; k < resolution; ++k) {
                float z1 = (float)k/resolution * zrange + zMin;
                float z2 = (float)(k+1)/resolution * zrange + zMin;

                /*

                 Coordinates:

                      z
                      |
                      |___ y
                      /
                     /
                    x

                 Cube layout:

                    4-------7
                   /|      /|
                  / |     / |
                 5-------6  |
                 |  0----|--3
                 | /     | /
                 |/      |/
                 1-------2

                 Tetrahedrons are:
                     0, 7, 3, 2
                     0, 7, 2, 6
                     0, 4, 6, 7
                     0, 6, 1, 2
                     0, 6, 1, 4
                     5, 6, 1, 4

                 */

                const Point3D v[8] = {
                    {x1, y1, z1, grid.get(i,     j,     k    )},
                    {x2, y1, z1, grid.get(i + 1, j,     k    )},
                    {x2, y2, z1, grid.get(i + 1, j + 1, k    )},
                    {x1, y2, z1, grid.get(i,     j + 1, k    )},
                    {x1, y1, z2, grid.get(i,     j,     k + 1)},
                    {x2, y1, z2, grid.get(i + 1, j,     k + 1)},
                    {x2, y2, z2, grid.get(i + 1, j + 1, k + 1)},
                    {x1, y2, z2, grid.get(i,     j + 1, k + 1)}
                };

                const Point3D tetrahedra[6][4] = {
                    { v[0], v[7], v[3], v[2] },
                    { v[0], v[7], v[2], v[6] },
                    { v[0], v[4], v[7], v[6] },
                    { v[0], v[1], v[6], v[2] },
                    { v[0], v[4], v[6], v[1] },
                    { v[5], v[1], v[6], v[4] }
                };

                for (int t = 0; t < 6; ++t)
                    drawTetrahedron(surface, tetrahedra[t], isolevel);

            }
        }
    }
    glEnd();

}
<commit_msg>Fix an ASCII diagram<commit_after>#include <cassert>
#include <iostream>
#include <cmath>
#include "common.h"
#include GLUT_INCLUDE
#include "Decimate.h"
#include "Array3D.h"

static inline void drawVert(const Isosurface& surface, const Point3D& p1, const Point3D& p2, float isolevel)
{

    float v1 = p1.value;
    float v2 = p2.value;

    float x, y, z;

    if (v2 == v1) {
        x = (p1.x + p2.x) / 2.0f;
        y = (p1.y + p2.y) / 2.0f;
        z = (p1.z + p2.z) / 2.0f;
    } else {

        /*

         <----+-----+---+----->
              v1    |   v2
                 isolevel

         <----+-----+---+----->
              0     |   1
                  interp

         */

        // interp == 0: vert should be at p1
        // interp == 1: vert should be at p2
        float interp = (isolevel - v1) / (v2 - v1);
        float oneMinusInterp = 1 - interp;

        x = p1.x * oneMinusInterp + p2.x * interp;
        y = p1.y * oneMinusInterp + p2.y * interp;
        z = p1.z * oneMinusInterp + p2.z * interp;
    }

    Vector3D normal = surface.gradientAt(x, y, z);

    glNormal3f(normal.x, normal.y, normal.z);
    glVertex3f(x, y, z);
}

static void drawTetrahedron(const Isosurface& surface, const Point3D p[4], float isolevel)
{

    /*

     Tetrahedron layout:

           0
           *
          /|\
         / | \
      3 *-----* 1
         \ | /
          \|/
           *
           2
     */

    unsigned char index = 0;
    for (int i = 0; i < 4; ++i)
        if (p[i].value < isolevel)
            index |= (1 << i);

    switch (index) {

        // we don't do anything if everyone is inside or outside
        case 0x00:
        case 0x0F:
            break;

        // only vert 0 is inside
        case 0x01:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            break;

        // only vert 1 is inside
        case 0x02:
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            break;

        // only vert 2 is inside
        case 0x04:
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            break;

        // only vert 3 is inside
        case 0x08:
            drawVert(surface, p[3], p[1], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            break;

        // verts 0, 1 are inside
        case 0x03:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);

            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            break;

        // verts 0, 2 are inside
        case 0x05:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[1], p[0], isolevel);

            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            break;

        // verts 0, 3 are inside
        case 0x09:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);

            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            break;

        // verts 1, 2 are inside
        case 0x06:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[1], p[3], isolevel);

            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            break;

        // verts 2, 3 are inside
        case 0x0C:
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[3], p[0], isolevel);

            drawVert(surface, p[2], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[2], p[1], isolevel);
            break;

        // verts 1, 3 are inside
        case 0x0A:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[2], isolevel);

            drawVert(surface, p[1], p[2], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[3], p[0], isolevel);
            break;

        // verts 0, 1, 2 are inside
        case 0x07:
            drawVert(surface, p[3], p[0], isolevel);
            drawVert(surface, p[3], p[2], isolevel);
            drawVert(surface, p[3], p[1], isolevel);
            break;

        // verts 0, 1, 3 are inside
        case 0x0B:
            drawVert(surface, p[2], p[1], isolevel);
            drawVert(surface, p[2], p[3], isolevel);
            drawVert(surface, p[2], p[0], isolevel);
            break;

        // verts 0, 2, 3 are inside
        case 0x0D:
            drawVert(surface, p[1], p[0], isolevel);
            drawVert(surface, p[1], p[3], isolevel);
            drawVert(surface, p[1], p[2], isolevel);
            break;

        // verts 1, 2, 3 are inside
        case 0x0E:
            drawVert(surface, p[0], p[1], isolevel);
            drawVert(surface, p[0], p[2], isolevel);
            drawVert(surface, p[0], p[3], isolevel);
            break;

        // what is this I don't even
        default:
            assert(false);
    }

}

void decimate(const Isosurface& surface,
              float xMin, float xMax,
              float yMin, float yMax,
              float zMin, float zMax,
              float isolevel,
              std::size_t resolution) // resolution indicates # of cubes
{

    std::size_t pointRes = resolution + 1; // indicates the # of points per side

    float xrange = xMax - xMin;
    float yrange = yMax - yMin;
    float zrange = zMax - zMin;

    Array3D<float> grid(pointRes, pointRes, pointRes);

    for (std::size_t i = 0; i <= resolution; ++i) {
        float x = (float)i/resolution * xrange + xMin;
        for (std::size_t j = 0; j <= resolution; ++j) {
            float y = (float)j/resolution * yrange + yMin;
            for (std::size_t k = 0; k <= resolution; ++k) {
                float z = (float)k/resolution * zrange + zMin;
                float value = surface.valueAt(x, y, z);
                grid.set(i, j, k, value);
            }
        }
    }

    glBegin(GL_TRIANGLES);
    for (std::size_t i = 0; i < resolution; ++i) {
        float x1 = (float)i/resolution * xrange + xMin;
        float x2 = (float)(i+1)/resolution * xrange + xMin;
        for (std::size_t j = 0; j < resolution; ++j) {
            float y1 = (float)j/resolution * yrange + yMin;
            float y2 = (float)(j+1)/resolution * yrange + yMin;
            for (std::size_t k = 0; k < resolution; ++k) {
                float z1 = (float)k/resolution * zrange + zMin;
                float z2 = (float)(k+1)/resolution * zrange + zMin;

                /*

                 Coordinates:

                      z
                      |
                      |___ y
                      /
                     /
                    x

                 Cube layout:

                    4-------7
                   /|      /|
                  / |     / |
                 5-------6  |
                 |  0----|--3
                 | /     | /
                 |/      |/
                 1-------2

                 Tetrahedrons are:
                     0, 7, 3, 2
                     0, 7, 2, 6
                     0, 4, 6, 7
                     0, 6, 1, 2
                     0, 6, 1, 4
                     5, 6, 1, 4

                 */

                const Point3D v[8] = {
                    {x1, y1, z1, grid.get(i,     j,     k    )},
                    {x2, y1, z1, grid.get(i + 1, j,     k    )},
                    {x2, y2, z1, grid.get(i + 1, j + 1, k    )},
                    {x1, y2, z1, grid.get(i,     j + 1, k    )},
                    {x1, y1, z2, grid.get(i,     j,     k + 1)},
                    {x2, y1, z2, grid.get(i + 1, j,     k + 1)},
                    {x2, y2, z2, grid.get(i + 1, j + 1, k + 1)},
                    {x1, y2, z2, grid.get(i,     j + 1, k + 1)}
                };

                const Point3D tetrahedra[6][4] = {
                    { v[0], v[7], v[3], v[2] },
                    { v[0], v[7], v[2], v[6] },
                    { v[0], v[4], v[7], v[6] },
                    { v[0], v[1], v[6], v[2] },
                    { v[0], v[4], v[6], v[1] },
                    { v[5], v[1], v[6], v[4] }
                };

                for (int t = 0; t < 6; ++t)
                    drawTetrahedron(surface, tetrahedra[t], isolevel);

            }
        }
    }
    glEnd();

}
<|endoftext|>


<commit_before>/*
 * test_sphere_advection.cpp
 *
 *  Created on: 3 Apr 2018
 *      Author: martin
 */

#ifndef SWEET_GUI
	#define SWEET_GUI 1
#endif

#include <sweet/sphere/SphereData.hpp>
#if SWEET_GUI
	#include "sweet/VisSweet.hpp"
#endif
#include <benchmarks_sphere/SWESphereBenchmarksCombined.hpp>
#include <sweet/SimulationVariables.hpp>
#include <sweet/sphere/SphereOperators.hpp>
#include <sweet/Convert_SphereData_To_PlaneData.hpp>
#include <sweet/Convert_SphereDataPhysical_To_PlaneData.hpp>

#include "../programs/advection_sphere/Adv_Sphere_TimeSteppers.hpp"

// Sphere data config
SphereDataConfig sphereDataConfigInstance;
SphereDataConfig *sphereDataConfig = &sphereDataConfigInstance;

#if SWEET_GUI
	PlaneDataConfig planeDataConfigInstance;
	PlaneDataConfig *planeDataConfig = &planeDataConfigInstance;
#endif

SimulationVariables simVars;

class SimulationInstance
{
public:
	SphereData prog_h;
	SphereData prog_h0;	// at t0
	SphereData prog_vort, prog_div;

	Adv_Sphere_TimeSteppers timeSteppers;

	SphereOperators op;

	/*
	 * LMax error to h0
	 */
	double max_error_h0;
	/*
	 * RMS error to h0
	 */
	double rms_error_h0;

#if SWEET_GUI
	PlaneData viz_plane_data;

	int render_primitive_id = 1;
#endif

	SWESphereBenchmarksCombined sphereBenchmarksCombined;

public:
	SimulationInstance()	:
		prog_h(sphereDataConfig),
		prog_h0(sphereDataConfig),

		prog_vort(sphereDataConfig),
		prog_div(sphereDataConfig),

		op(sphereDataConfig, simVars.sim.sphere_radius)

#if SWEET_GUI
		,
		viz_plane_data(planeDataConfig)
#endif
	{
		reset();
	}

	void reset()
	{
		simVars.reset();

		sphereBenchmarksCombined.setup(simVars, op);
		sphereBenchmarksCombined.setupInitialConditions(prog_h, prog_vort, prog_div);

		prog_h0 = prog_h;

		// setup sphereDataconfig instance again
		sphereDataConfigInstance.setupAuto(simVars.disc.space_res_physical, simVars.disc.space_res_spectral, simVars.misc.reuse_spectral_transformation_plans);

		timeSteppers.setup(simVars.disc.timestepping_method, op, simVars);

		//simVars.outputConfig();
	}

	void run_timestep()
	{
		if (simVars.timecontrol.current_simulation_time + simVars.timecontrol.current_timestep_size > simVars.timecontrol.max_simulation_time)
			simVars.timecontrol.current_timestep_size = simVars.timecontrol.max_simulation_time - simVars.timecontrol.current_simulation_time;

		timeSteppers.master->run_timestep(
				prog_h, prog_vort, prog_div,
				simVars.timecontrol.current_timestep_size,
				simVars.timecontrol.current_simulation_time
			);

		double dt = simVars.timecontrol.current_timestep_size;

		// advance in time
		simVars.timecontrol.current_simulation_time += dt;
		simVars.timecontrol.current_timestep_nr++;

		if (simVars.misc.verbosity >= 10)
			std::cout << simVars.timecontrol.current_timestep_nr << ": " << simVars.timecontrol.current_simulation_time/(60*60*24.0) << std::endl;

		max_error_h0 = (prog_h0-prog_h).physical_reduce_max_abs();
		rms_error_h0 = (prog_h0-prog_h).physical_reduce_rms();
	}

	void compute_error()
	{
#if 0
		double t = simVars.timecontrol.current_simulation_time;

		SphereData prog_testh(sphereDataConfig);
		prog_testh.physical_update_lambda_array_indices(
			[&](int i, int j, double &io_data)
			{
				double x = (((double)i)/(double)simVars.disc.space_res_physical[0])*simVars.sim.domain_size[0];
				double y = (((double)j)/(double)simVars.disc.space_res_physical[1])*simVars.sim.domain_size[1];

				x -= param_velocity_u*t;
				y -= param_velocity_v*t;

				while (x < 0)
					x += simVars.sim.domain_size[0];

				while (y < 0)
					y += simVars.sim.domain_size[1];

				x = std::fmod(x, simVars.sim.domain_size[0]);
				y = std::fmod(y, simVars.sim.domain_size[1]);

				io_data = SWESphereBenchmarks::return_h(simVars, x, y);
			}
		);

		std::cout << "Lmax Error: " << (prog_h-prog_testh).reduce_maxAbs() << std::endl;
#endif
	}

	bool should_quit()
	{
		if (simVars.timecontrol.max_timesteps_nr != -1 && simVars.timecontrol.max_timesteps_nr <= simVars.timecontrol.current_timestep_nr)
			return true;

		double diff = std::abs(simVars.timecontrol.max_simulation_time - simVars.timecontrol.current_simulation_time);

		if (	simVars.timecontrol.max_simulation_time != -1 &&
				(
						simVars.timecontrol.max_simulation_time <= simVars.timecontrol.current_simulation_time	||
						diff/simVars.timecontrol.max_simulation_time < 1e-11	// avoid numerical issues in time stepping if current time step is 1e-14 smaller than max time step
				)
			)
			return true;

		return false;
	}

#if SWEET_GUI
	/**
	 * postprocessing of frame: do time stepping
	 */
	void vis_post_frame_processing(int i_num_iterations)
	{
		if (simVars.timecontrol.run_simulation_timesteps)
			for (int i = 0; i < i_num_iterations && !should_quit(); i++)
				run_timestep();

		compute_error();
	}

	void vis_get_vis_data_array(
			const PlaneData **o_dataArray,
			double *o_aspect_ratio,
			int *o_render_primitive_id,
			void **o_bogus_data
	)
	{
		*o_render_primitive_id = render_primitive_id;
		*o_bogus_data = sphereDataConfig;

		int id = simVars.misc.vis_id % 5;
		switch (id)
		{
		case 0:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_h, planeDataConfig);
			break;

		case 1:
			{
				SphereDataPhysical u(sphereDataConfig);
				SphereDataPhysical v(sphereDataConfig);

//				op.robert_vortdiv_to_uv(prog_vort, prog_div, u, v);
				op.vortdiv_to_uv(prog_vort, prog_div, u, v);
				viz_plane_data = Convert_SphereDataPhysical_To_PlaneData::physical_convert(u, planeDataConfig);
			}
			break;

		case 2:
			{
				SphereDataPhysical u(sphereDataConfig);
				SphereDataPhysical v(sphereDataConfig);

//				op.robert_vortdiv_to_uv(prog_vort, prog_div, u, v);
				op.vortdiv_to_uv(prog_vort, prog_div, u, v);
				viz_plane_data = Convert_SphereDataPhysical_To_PlaneData::physical_convert(v, planeDataConfig);
			}
			break;

		case 3:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_vort, planeDataConfig);
			break;

		case 4:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_div, planeDataConfig);
			break;
		}

		*o_dataArray = &viz_plane_data;
		*o_aspect_ratio = 0.5;
	}

	const char* vis_get_status_string()
	{
		const char* description = "";
		int id = simVars.misc.vis_id % 3;

		switch (id)
		{
		default:
		case 0:
			description = "H";
			break;

		case 1:
			description = "vort";
			break;

		case 2:
			description = "div";
			break;
		}

		static char title_string[2048];

		//sprintf(title_string, "Time (days): %f (%.2f d), Timestep: %i, timestep size: %.14e, Vis: %s, Mass: %.14e, Energy: %.14e, Potential Entrophy: %.14e",
		sprintf(title_string,
#if SWEET_MPI
				"Rank %i - "
#endif
				"Time: %f (%.2f d), k: %i, dt: %.3e, Vis: %s, TMass: %.6e, TEnergy: %.6e, PotEnstrophy: %.6e, MaxVal: %.6e, MinVal: %.6e ",
#if SWEET_MPI
				mpi_rank,
#endif
				simVars.timecontrol.current_simulation_time,
				simVars.timecontrol.current_simulation_time/(60.0*60.0*24.0),
				simVars.timecontrol.current_timestep_nr,
				simVars.timecontrol.current_timestep_size,
				description,
				simVars.diag.total_mass,
				simVars.diag.total_energy,
				simVars.diag.total_potential_enstrophy,
				viz_plane_data.reduce_max(),
				viz_plane_data.reduce_min()
		);

		return title_string;
	}

	void vis_pause()
	{
		simVars.timecontrol.run_simulation_timesteps = !simVars.timecontrol.run_simulation_timesteps;
	}

	void vis_keypress(int i_key)
	{
		switch(i_key)
		{
		case 'v':
			simVars.misc.vis_id++;
			break;

		case 'V':
			simVars.misc.vis_id--;
			break;

		case 'b':
			render_primitive_id = (render_primitive_id + 1) % 2;
			break;
		}
	}
#endif
};

int main(int i_argc, char *i_argv[])
{
	if (!simVars.setupFromMainParameters(i_argc, i_argv))
	{
		std::cout << std::endl;
		return -1;
	}

	int initial_spectral_modes = simVars.disc.space_res_spectral[0];

	if (simVars.timecontrol.current_timestep_size < 0)
		FatalError("Timestep size not set");

	SphereDataSemiLagrangian::alpha() = simVars.benchmark.advection_rotation_angle;

	int max_modes = 256;

	if (simVars.disc.timestepping_order == 1)
		max_modes = 512;
	else if (simVars.disc.timestepping_order == 2)
		max_modes = 256;

	double prev_max_error = -1;
	for (int i = initial_spectral_modes; i <= max_modes; i *= 2)
	{
		simVars.timecontrol.current_timestep_size *= 0.5;

		if (simVars.disc.timestepping_method == "na_sl")
		{
			simVars.disc.space_res_spectral[0] = i;
			simVars.disc.space_res_spectral[1] = i;

			simVars.disc.space_res_physical[0] = 2*i;
			simVars.disc.space_res_physical[1] = i;
		}
		else
		{
			simVars.disc.space_res_spectral[0] = initial_spectral_modes;
			simVars.disc.space_res_spectral[1] = initial_spectral_modes;

			simVars.disc.space_res_physical[0] = 0;
			simVars.disc.space_res_physical[1] = 0;
		}

		sphereDataConfigInstance.setupAuto(simVars.disc.space_res_physical, simVars.disc.space_res_spectral, simVars.misc.reuse_spectral_transformation_plans);

		std::cout << "Testing with " << sphereDataConfigInstance.getUniqueIDString() << std::endl;
		std::cout << "Testing with dt=" << simVars.timecontrol.current_timestep_size << std::endl;

		SimulationInstance simulation;

	#if SWEET_GUI
		if (simVars.misc.gui_enabled)
		{
			planeDataConfigInstance.setupAutoSpectralSpace(
					simVars.disc.space_res_physical,
					simVars.misc.reuse_spectral_transformation_plans,
					simVars.misc.reuse_spectral_transformation_plans
				);
			VisSweet<SimulationInstance> visSweet(&simulation);
			return 0;
		}
		else
	#endif
		{
//			simulation.reset();
			while (!simulation.should_quit())
				simulation.run_timestep();

			std::cout << "Error compared to initial condition" << std::endl;
			std::cout << "Lmax error: " << simulation.max_error_h0 << std::endl;
			std::cout << "RMS error: " << simulation.rms_error_h0 << std::endl;

			if (prev_max_error >= 0)
			{
				//double conv = (prev_max_error - simulation.max_error) / simulation.max_error;
				double conv = prev_max_error / simulation.max_error_h0;
				std::cout << "Convergence: " << conv << std::endl;

				if (conv*1.1 < std::pow(2.0, (double)simVars.disc.timestepping_order))
					FatalError("Convergence not given!");
			}

			if (simulation.max_error_h0  > 1e10)
				FatalError("Lmax error exceeded threshold!");

			prev_max_error = simulation.max_error_h0;

			std::cout << "*********************************************" << std::endl;
		}
	}

	return 0;
}
<commit_msg>fixed compile bug<commit_after>/*
 * test_sphere_advection.cpp
 *
 *  Created on: 3 Apr 2018
 *      Author: martin
 */

#ifndef SWEET_GUI
	#define SWEET_GUI 1
#endif

#include <sweet/sphere/SphereData.hpp>
#if SWEET_GUI
	#include "sweet/VisSweet.hpp"
#endif
#include <benchmarks_sphere/SWESphereBenchmarksCombined.hpp>
#include <sweet/SimulationVariables.hpp>
#include <sweet/sphere/SphereOperators.hpp>
#include <sweet/Convert_SphereData_To_PlaneData.hpp>
#include <sweet/Convert_SphereDataPhysical_To_PlaneData.hpp>

#include "../programs/advection_sphere/Adv_Sphere_TimeSteppers.hpp"

// Sphere data config
SphereDataConfig sphereDataConfigInstance;
SphereDataConfig *sphereDataConfig = &sphereDataConfigInstance;

#if SWEET_GUI
	PlaneDataConfig planeDataConfigInstance;
	PlaneDataConfig *planeDataConfig = &planeDataConfigInstance;
#endif

SimulationVariables simVars;

class SimulationInstance
{
public:
	SphereData prog_h;
	SphereData prog_h0;	// at t0
	SphereData prog_vort, prog_div;

	Adv_Sphere_TimeSteppers timeSteppers;

	SphereOperators op;

	/*
	 * LMax error to h0
	 */
	double max_error_h0;
	/*
	 * RMS error to h0
	 */
	double rms_error_h0;

#if SWEET_GUI
	PlaneData viz_plane_data;

	int render_primitive_id = 1;
#endif

	SWESphereBenchmarksCombined sphereBenchmarksCombined;

public:
	SimulationInstance()	:
		prog_h(sphereDataConfig),
		prog_h0(sphereDataConfig),

		prog_vort(sphereDataConfig),
		prog_div(sphereDataConfig),

		op(sphereDataConfig, simVars.sim.sphere_radius)

#if SWEET_GUI
		,
		viz_plane_data(planeDataConfig)
#endif
	{
		reset();
	}

	void reset()
	{
		simVars.reset();

		sphereBenchmarksCombined.setup(simVars, op);
		sphereBenchmarksCombined.setupInitialConditions(prog_h, prog_vort, prog_div);

		prog_h0 = prog_h;

		// setup sphereDataconfig instance again
		sphereDataConfigInstance.setupAuto(simVars.disc.space_res_physical, simVars.disc.space_res_spectral, simVars.misc.reuse_spectral_transformation_plans);

		timeSteppers.setup(simVars.disc.timestepping_method, op, simVars);

		//simVars.outputConfig();
	}

	void run_timestep()
	{
		if (simVars.timecontrol.current_simulation_time + simVars.timecontrol.current_timestep_size > simVars.timecontrol.max_simulation_time)
			simVars.timecontrol.current_timestep_size = simVars.timecontrol.max_simulation_time - simVars.timecontrol.current_simulation_time;

		timeSteppers.master->run_timestep(
				prog_h, prog_vort, prog_div,
				simVars.timecontrol.current_timestep_size,
				simVars.timecontrol.current_simulation_time
			);

		double dt = simVars.timecontrol.current_timestep_size;

		// advance in time
		simVars.timecontrol.current_simulation_time += dt;
		simVars.timecontrol.current_timestep_nr++;

		if (simVars.misc.verbosity >= 10)
			std::cout << simVars.timecontrol.current_timestep_nr << ": " << simVars.timecontrol.current_simulation_time/(60*60*24.0) << std::endl;

		max_error_h0 = (prog_h0-prog_h).physical_reduce_max_abs();
		rms_error_h0 = (prog_h0-prog_h).physical_reduce_rms();
	}

	void compute_error()
	{
#if 0
		double t = simVars.timecontrol.current_simulation_time;

		SphereData prog_testh(sphereDataConfig);
		prog_testh.physical_update_lambda_array_indices(
			[&](int i, int j, double &io_data)
			{
				double x = (((double)i)/(double)simVars.disc.space_res_physical[0])*simVars.sim.domain_size[0];
				double y = (((double)j)/(double)simVars.disc.space_res_physical[1])*simVars.sim.domain_size[1];

				x -= param_velocity_u*t;
				y -= param_velocity_v*t;

				while (x < 0)
					x += simVars.sim.domain_size[0];

				while (y < 0)
					y += simVars.sim.domain_size[1];

				x = std::fmod(x, simVars.sim.domain_size[0]);
				y = std::fmod(y, simVars.sim.domain_size[1]);

				io_data = SWESphereBenchmarks::return_h(simVars, x, y);
			}
		);

		std::cout << "Lmax Error: " << (prog_h-prog_testh).reduce_maxAbs() << std::endl;
#endif
	}

	bool should_quit()
	{
		if (simVars.timecontrol.max_timesteps_nr != -1 && simVars.timecontrol.max_timesteps_nr <= simVars.timecontrol.current_timestep_nr)
			return true;

		double diff = std::abs(simVars.timecontrol.max_simulation_time - simVars.timecontrol.current_simulation_time);

		if (	simVars.timecontrol.max_simulation_time != -1 &&
				(
						simVars.timecontrol.max_simulation_time <= simVars.timecontrol.current_simulation_time	||
						diff/simVars.timecontrol.max_simulation_time < 1e-11	// avoid numerical issues in time stepping if current time step is 1e-14 smaller than max time step
				)
			)
			return true;

		return false;
	}

#if SWEET_GUI
	/**
	 * postprocessing of frame: do time stepping
	 */
	void vis_post_frame_processing(int i_num_iterations)
	{
		if (simVars.timecontrol.run_simulation_timesteps)
			for (int i = 0; i < i_num_iterations && !should_quit(); i++)
				run_timestep();

		compute_error();
	}

	void vis_get_vis_data_array(
			const PlaneData **o_dataArray,
			double *o_aspect_ratio,
			int *o_render_primitive_id,
			void **o_bogus_data
	)
	{
		*o_render_primitive_id = render_primitive_id;
		*o_bogus_data = sphereDataConfig;

		int id = simVars.misc.vis_id % 5;
		switch (id)
		{
		case 0:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_h, planeDataConfig);
			break;

		case 1:
			{
				SphereDataPhysical u(sphereDataConfig);
				SphereDataPhysical v(sphereDataConfig);

//				op.robert_vortdiv_to_uv(prog_vort, prog_div, u, v);
				op.vortdiv_to_uv(prog_vort, prog_div, u, v);
				viz_plane_data = Convert_SphereDataPhysical_To_PlaneData::physical_convert(u, planeDataConfig);
			}
			break;

		case 2:
			{
				SphereDataPhysical u(sphereDataConfig);
				SphereDataPhysical v(sphereDataConfig);

//				op.robert_vortdiv_to_uv(prog_vort, prog_div, u, v);
				op.vortdiv_to_uv(prog_vort, prog_div, u, v);
				viz_plane_data = Convert_SphereDataPhysical_To_PlaneData::physical_convert(v, planeDataConfig);
			}
			break;

		case 3:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_vort, planeDataConfig);
			break;

		case 4:
			viz_plane_data = Convert_SphereData_To_PlaneData::physical_convert(prog_div, planeDataConfig);
			break;
		}

		*o_dataArray = &viz_plane_data;
		*o_aspect_ratio = 0.5;
	}

	const char* vis_get_status_string()
	{
		const char* description = "";
		int id = simVars.misc.vis_id % 3;

		switch (id)
		{
		default:
		case 0:
			description = "H";
			break;

		case 1:
			description = "vort";
			break;

		case 2:
			description = "div";
			break;
		}

		static char title_string[2048];

		//sprintf(title_string, "Time (days): %f (%.2f d), Timestep: %i, timestep size: %.14e, Vis: %s, Mass: %.14e, Energy: %.14e, Potential Entrophy: %.14e",
		sprintf(title_string,
#if SWEET_MPI
				"Rank %i - "
#endif
				"Time: %f (%.2f d), k: %i, dt: %.3e, Vis: %s, TMass: %.6e, TEnergy: %.6e, PotEnstrophy: %.6e, MaxVal: %.6e, MinVal: %.6e ",
#if SWEET_MPI
				mpi_rank,
#endif
				simVars.timecontrol.current_simulation_time,
				simVars.timecontrol.current_simulation_time/(60.0*60.0*24.0),
				simVars.timecontrol.current_timestep_nr,
				simVars.timecontrol.current_timestep_size,
				description,
				simVars.diag.total_mass,
				simVars.diag.total_energy,
				simVars.diag.total_potential_enstrophy,
				viz_plane_data.reduce_max(),
				viz_plane_data.reduce_min()
		);

		return title_string;
	}

	void vis_pause()
	{
		simVars.timecontrol.run_simulation_timesteps = !simVars.timecontrol.run_simulation_timesteps;
	}

	void vis_keypress(int i_key)
	{
		switch(i_key)
		{
		case 'v':
			simVars.misc.vis_id++;
			break;

		case 'V':
			simVars.misc.vis_id--;
			break;

		case 'b':
			render_primitive_id = (render_primitive_id + 1) % 2;
			break;
		}
	}
#endif
};

int main(int i_argc, char *i_argv[])
{
	if (!simVars.setupFromMainParameters(i_argc, i_argv))
	{
		std::cout << std::endl;
		return -1;
	}

	int initial_spectral_modes = simVars.disc.space_res_spectral[0];

	if (simVars.timecontrol.current_timestep_size < 0)
		FatalError("Timestep size not set");

	SphereDataSemiLagrangian::alpha() = simVars.benchmark.sphere_advection_rotation_angle;

	int max_modes = 256;

	if (simVars.disc.timestepping_order == 1)
		max_modes = 512;
	else if (simVars.disc.timestepping_order == 2)
		max_modes = 256;

	double prev_max_error = -1;
	for (int i = initial_spectral_modes; i <= max_modes; i *= 2)
	{
		simVars.timecontrol.current_timestep_size *= 0.5;

		if (simVars.disc.timestepping_method == "na_sl")
		{
			simVars.disc.space_res_spectral[0] = i;
			simVars.disc.space_res_spectral[1] = i;

			simVars.disc.space_res_physical[0] = 2*i;
			simVars.disc.space_res_physical[1] = i;
		}
		else
		{
			simVars.disc.space_res_spectral[0] = initial_spectral_modes;
			simVars.disc.space_res_spectral[1] = initial_spectral_modes;

			simVars.disc.space_res_physical[0] = 0;
			simVars.disc.space_res_physical[1] = 0;
		}

		sphereDataConfigInstance.setupAuto(simVars.disc.space_res_physical, simVars.disc.space_res_spectral, simVars.misc.reuse_spectral_transformation_plans);

		std::cout << "Testing with " << sphereDataConfigInstance.getUniqueIDString() << std::endl;
		std::cout << "Testing with dt=" << simVars.timecontrol.current_timestep_size << std::endl;

		SimulationInstance simulation;

	#if SWEET_GUI
		if (simVars.misc.gui_enabled)
		{
			planeDataConfigInstance.setupAutoSpectralSpace(
					simVars.disc.space_res_physical,
					simVars.misc.reuse_spectral_transformation_plans,
					simVars.misc.reuse_spectral_transformation_plans
				);
			VisSweet<SimulationInstance> visSweet(&simulation);
			return 0;
		}
		else
	#endif
		{
//			simulation.reset();
			while (!simulation.should_quit())
				simulation.run_timestep();

			std::cout << "Error compared to initial condition" << std::endl;
			std::cout << "Lmax error: " << simulation.max_error_h0 << std::endl;
			std::cout << "RMS error: " << simulation.rms_error_h0 << std::endl;

			if (prev_max_error >= 0)
			{
				//double conv = (prev_max_error - simulation.max_error) / simulation.max_error;
				double conv = prev_max_error / simulation.max_error_h0;
				std::cout << "Convergence: " << conv << std::endl;

				if (conv*1.1 < std::pow(2.0, (double)simVars.disc.timestepping_order))
					FatalError("Convergence not given!");
			}

			if (simulation.max_error_h0  > 1e10)
				FatalError("Lmax error exceeded threshold!");

			prev_max_error = simulation.max_error_h0;

			std::cout << "*********************************************" << std::endl;
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>//  Copyright 2011 Gregory Szorc
//
//  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 <zippylog/persisted_state_manager.hpp>

#include <gtest/gtest.h>

namespace zippylog {

} // namespaces
<commit_msg>start to implement tests<commit_after>//  Copyright 2011 Gregory Szorc
//
//  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 <zippylog/persisted_state_manager.hpp>
#include <zippylog/platform.hpp>

#include <gtest/gtest.h>

#include <string>

using ::std::invalid_argument;
using ::std::string;

namespace zippylog {

class PersistedStateManagerTest : public ::testing::Test
{
protected:

    string id;
    string path;
    string store_uri;

    void SetUp()
    {
        this->id = platform::CreateUUID(true);
        this->path = "test/stores/" + id;
        this->store_uri = "simpledirectory://" + this->path;

        ASSERT_FALSE(platform::PathIsDirectory(this->path));
        ASSERT_TRUE(platform::MakeDirectory(this->path));
    }

    void TearDown()
    {
        if (platform::PathIsDirectory(this->path)) {
            EXPECT_TRUE(platform::RemoveDirectoryA(this->path));
        }
    }
};

TEST_F(PersistedStateManagerTest, Constructor)
{
    PersistedStateManagerStartParams p;

    EXPECT_THROW(PersistedStateManager m(p), invalid_argument);

    p.store_uri = this->store_uri;
    EXPECT_NO_THROW(PersistedStateManager m(p));
}

} // namespaces
<|endoftext|>


<commit_before>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file LogMessageCallback.cpp
 * @brief Implementation of the class LogMessageCallback
 */

#include "LogMessageCallback.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_sorts.h"

/**
 * Create a LogMessageCallback object
 * @param jcallback the Java callback object.
 */
LogMessageCallback::LogMessageCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a LogMessageCallback object
 */
LogMessageCallback::~LogMessageCallback()
{
  // The m_callback does not need to be destroyed because it is the
  // passed in parameter to the Java SVNClientInterface.logMessages
  // method.
}

svn_error_t *
LogMessageCallback::callback(void *baton,
                             svn_log_entry_t *log_entry,
                             apr_pool_t *pool)
{
  if (baton)
    return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);

  return SVN_NO_ERROR;
}

/**
 * Callback called for a single log message
 */
svn_error_t *
LogMessageCallback::singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool)
{
  JNIEnv *env = JNIUtil::getEnv();

  // The method id will not change during the time this library is
  // loaded, so it can be cached.
  static jmethodID sm_mid = 0;
  if (sm_mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/LogMessageCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      sm_mid = env->GetMethodID(clazz,
                                "singleMessage",
                                "([L"JAVA_PACKAGE"/ChangePath;"
                                "JLjava/lang/String;"
                                "JLjava/lang/String;J)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jclass clazzCP = env->FindClass(JAVA_PACKAGE"/ChangePath");
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  static jmethodID midCP = 0;
  if (midCP == 0)
    {
      midCP = env->GetMethodID(clazzCP,
                               "<init>",
                               "(Ljava/lang/String;JLjava/lang/String;C)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  apr_time_t commit_time = -1;
  if (log_entry->date != NULL && *log_entry->date != '\0')
    SVN_ERR(svn_time_from_cstring(&commit_time, log_entry->date, pool));

  jstring jauthor = JNIUtil::makeJString(log_entry->author);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  jobjectArray jChangedPaths = NULL;
  if (log_entry->changed_paths)
    {
      apr_array_header_t *sorted_paths;
      int i;

      /* Get an array of sorted hash keys. */
      sorted_paths = svn_sort__hash(log_entry->changed_paths,
                                    svn_sort_compare_items_as_paths,
                                    pool);

      jChangedPaths = env->NewObjectArray(sorted_paths->nelts,
                                          clazzCP,
                                          NULL);

      for (i = 0; i < sorted_paths->nelts; ++i)
        {
          svn_sort__item_t *item = &(APR_ARRAY_IDX(sorted_paths, i,
                                                   svn_sort__item_t));
          const char *path = (const char *)item->key;
          svn_log_changed_path_t *log_item
            = (svn_log_changed_path_t *)
            apr_hash_get(log_entry->changed_paths, item->key, item->klen);

          jstring jpath = JNIUtil::makeJString(path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jstring jcopyFromPath =
            JNIUtil::makeJString(log_item->copyfrom_path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jlong jcopyFromRev = log_item->copyfrom_rev;
          jchar jaction = log_item->action;

          jobject cp = env->NewObject(clazzCP, midCP, jpath, jcopyFromRev,
                                      jcopyFromPath, jaction);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->SetObjectArrayElement(jChangedPaths, i, cp);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(cp);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jpath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jcopyFromPath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
        }
    }

  jstring jmessage = JNIUtil::makeJString(log_entry->message);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->CallVoidMethod(m_callback,
                      sm_mid,
                      jChangedPaths,
                      (jlong)log_entry->revision,
                      jauthor,
                      (jlong)commit_time,
                      jmessage,
                      (jlong)log_entry->nbr_children);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jauthor);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jmessage);
  // No need to check for an exception here, because we return anyway.

  return SVN_NO_ERROR;
}
<commit_msg>Followup to 26426: Fix compile error<commit_after>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file LogMessageCallback.cpp
 * @brief Implementation of the class LogMessageCallback
 */

#include "LogMessageCallback.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_sorts.h"

/**
 * Create a LogMessageCallback object
 * @param jcallback the Java callback object.
 */
LogMessageCallback::LogMessageCallback(jobject jcallback)
{
  m_callback = jcallback;
}

/**
 * Destroy a LogMessageCallback object
 */
LogMessageCallback::~LogMessageCallback()
{
  // The m_callback does not need to be destroyed because it is the
  // passed in parameter to the Java SVNClientInterface.logMessages
  // method.
}

svn_error_t *
LogMessageCallback::callback(void *baton,
                             svn_log_entry_t *log_entry,
                             apr_pool_t *pool)
{
  if (baton)
    return ((LogMessageCallback *)baton)->singleMessage(log_entry, pool);

  return SVN_NO_ERROR;
}

/**
 * Callback called for a single log message
 */
svn_error_t *
LogMessageCallback::singleMessage(svn_log_entry_t *log_entry, apr_pool_t *pool)
{
  JNIEnv *env = JNIUtil::getEnv();

  // The method id will not change during the time this library is
  // loaded, so it can be cached.
  static jmethodID sm_mid = 0;
  if (sm_mid == 0)
    {
      jclass clazz = env->FindClass(JAVA_PACKAGE"/LogMessageCallback");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      sm_mid = env->GetMethodID(clazz,
                                "singleMessage",
                                "([L"JAVA_PACKAGE"/ChangePath;"
                                "JLjava/lang/String;"
                                "JLjava/lang/String;J)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

      env->DeleteLocalRef(clazz);
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  jclass clazzCP = env->FindClass(JAVA_PACKAGE"/ChangePath");
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  static jmethodID midCP = 0;
  if (midCP == 0)
    {
      midCP = env->GetMethodID(clazzCP,
                               "<init>",
                               "(Ljava/lang/String;JLjava/lang/String;C)V");
      if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;
    }

  apr_time_t commit_time = -1;
  if (log_entry->date != NULL && *log_entry->date != '\0')
    SVN_ERR(svn_time_from_cstring(&commit_time, log_entry->date, pool));

  jstring jauthor = JNIUtil::makeJString(log_entry->author);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  jobjectArray jChangedPaths = NULL;
  if (log_entry->changed_paths)
    {
      apr_array_header_t *sorted_paths;
      int i;

      /* Get an array of sorted hash keys. */
      sorted_paths = svn_sort__hash(log_entry->changed_paths,
                                    svn_sort_compare_items_as_paths,
                                    pool);

      jChangedPaths = env->NewObjectArray(sorted_paths->nelts,
                                          clazzCP,
                                          NULL);

      for (i = 0; i < sorted_paths->nelts; ++i)
        {
          svn_sort__item_t *item = &(APR_ARRAY_IDX(sorted_paths, i,
                                                   svn_sort__item_t));
          const char *path = (const char *)item->key;
          svn_log_changed_path_t *log_item
            = (svn_log_changed_path_t *)
            apr_hash_get(log_entry->changed_paths, item->key, item->klen);

          jstring jpath = JNIUtil::makeJString(path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jstring jcopyFromPath =
            JNIUtil::makeJString(log_item->copyfrom_path);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          jlong jcopyFromRev = log_item->copyfrom_rev;
          jchar jaction = log_item->action;

          jobject cp = env->NewObject(clazzCP, midCP, jpath, jcopyFromRev,
                                      jcopyFromPath, jaction);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->SetObjectArrayElement(jChangedPaths, i, cp);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(cp);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jpath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

          env->DeleteLocalRef(jcopyFromPath);
          if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
        }
    }

  jstring jmessage = JNIUtil::makeJString(log_entry->message);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->CallVoidMethod(m_callback,
                      sm_mid,
                      jChangedPaths,
                      (jlong)log_entry->revision,
                      jauthor,
                      (jlong)commit_time,
                      jmessage,
                      (jboolean)log_entry->has_children);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jauthor);
  if (JNIUtil::isJavaExceptionThrown())
    return SVN_NO_ERROR;

  env->DeleteLocalRef(jmessage);
  // No need to check for an exception here, because we return anyway.

  return SVN_NO_ERROR;
}
<|endoftext|>


<commit_before>//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
#include <string>
#include <cmath>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include "util/testharness.h"
#include "util/auto_roll_logger.h"
#include "rocksdb/db.h"
#include <sys/stat.h>
#include <errno.h>

using namespace std;

namespace rocksdb {

class AutoRollLoggerTest {
 public:
  static void InitTestDb() {
    string deleteCmd = "rm -rf " + kTestDir;
    ASSERT_TRUE(system(deleteCmd.c_str()) == 0);
    Env::Default()->CreateDir(kTestDir);
  }

  void RollLogFileBySizeTest(AutoRollLogger* logger,
                             size_t log_max_size,
                             const string& log_message);
  uint64_t RollLogFileByTimeTest(AutoRollLogger* logger,
                                 size_t time,
                                 const string& log_message);

  static const string kSampleMessage;
  static const string kTestDir;
  static const string kLogFile;
  static Env* env;
};

const string AutoRollLoggerTest::kSampleMessage(
    "this is the message to be written to the log file!!");
const string AutoRollLoggerTest::kTestDir(test::TmpDir() + "/db_log_test");
const string AutoRollLoggerTest::kLogFile(test::TmpDir() + "/db_log_test/LOG");
Env* AutoRollLoggerTest::env = Env::Default();

// In this test we only want to Log some simple log message with
// no format. LogMessage() provides such a simple interface and
// avoids the [format-security] warning which occurs when you
// call Log(logger, log_message) directly.
namespace {
void LogMessage(Logger* logger, const char* message) {
  Log(logger, "%s", message);
}

void LogMessage(const InfoLogLevel log_level, Logger* logger,
                const char* message) {
  Log(log_level, logger, "%s", message);
}
}  // namespace

namespace {
void GetFileCreateTime(const std::string& fname, uint64_t* file_ctime) {
  struct stat s;
  if (stat(fname.c_str(), &s) != 0) {
    *file_ctime = (uint64_t)0;
  }
  *file_ctime = static_cast<uint64_t>(s.st_ctime);
}
}  // namespace

void AutoRollLoggerTest::RollLogFileBySizeTest(AutoRollLogger* logger,
                                               size_t log_max_size,
                                               const string& log_message) {
  logger->SetInfoLogLevel(InfoLogLevel::INFO_LEVEL);
  // measure the size of each message, which is supposed
  // to be equal or greater than log_message.size()
  LogMessage(logger, log_message.c_str());
  size_t message_size = logger->GetLogFileSize();
  size_t current_log_size = message_size;

  // Test the cases when the log file will not be rolled.
  while (current_log_size + message_size < log_max_size) {
    LogMessage(logger, log_message.c_str());
    current_log_size += message_size;
    ASSERT_EQ(current_log_size, logger->GetLogFileSize());
  }

  // Now the log file will be rolled
  LogMessage(logger, log_message.c_str());
  // Since rotation is checked before actual logging, we need to
  // trigger the rotation by logging another message.
  LogMessage(logger, log_message.c_str());

  ASSERT_TRUE(message_size == logger->GetLogFileSize());
}

uint64_t AutoRollLoggerTest::RollLogFileByTimeTest(
    AutoRollLogger* logger, size_t time, const string& log_message) {
  uint64_t expected_create_time;
  uint64_t actual_create_time;
  uint64_t total_log_size;
  ASSERT_OK(env->GetFileSize(kLogFile, &total_log_size));
  GetFileCreateTime(kLogFile, &expected_create_time);
  logger->SetCallNowMicrosEveryNRecords(0);

  // -- Write to the log for several times, which is supposed
  // to be finished before time.
  for (int i = 0; i < 10; ++i) {
     LogMessage(logger, log_message.c_str());
     ASSERT_OK(logger->GetStatus());
     // Make sure we always write to the same log file (by
     // checking the create time);
     GetFileCreateTime(kLogFile, &actual_create_time);

     // Also make sure the log size is increasing.
     ASSERT_EQ(expected_create_time, actual_create_time);
     ASSERT_GT(logger->GetLogFileSize(), total_log_size);
     total_log_size = logger->GetLogFileSize();
  }

  // -- Make the log file expire
  sleep(time);
  LogMessage(logger, log_message.c_str());

  // At this time, the new log file should be created.
  GetFileCreateTime(kLogFile, &actual_create_time);
  ASSERT_GT(actual_create_time, expected_create_time);
  ASSERT_LT(logger->GetLogFileSize(), total_log_size);
  expected_create_time = actual_create_time;

  return expected_create_time;
}

TEST(AutoRollLoggerTest, RollLogFileBySize) {
    InitTestDb();
    size_t log_max_size = 1024 * 5;

    AutoRollLogger logger(Env::Default(), kTestDir, "", log_max_size, 0);

    RollLogFileBySizeTest(&logger, log_max_size,
                          kSampleMessage + ":RollLogFileBySize");
}

TEST(AutoRollLoggerTest, RollLogFileByTime) {
    size_t time = 1;
    size_t log_size = 1024 * 5;

    InitTestDb();
    // -- Test the existence of file during the server restart.
    ASSERT_TRUE(!env->FileExists(kLogFile));
    AutoRollLogger logger(Env::Default(), kTestDir, "", log_size, 1);
    ASSERT_TRUE(env->FileExists(kLogFile));

    RollLogFileByTimeTest(&logger, time, kSampleMessage + ":RollLogFileByTime");
}

TEST(AutoRollLoggerTest,
     OpenLogFilesMultipleTimesWithOptionLog_max_size) {
  // If only 'log_max_size' options is specified, then every time
  // when rocksdb is restarted, a new empty log file will be created.
  InitTestDb();
  // WORKAROUND:
  // avoid complier's complaint of "comparison between signed
  // and unsigned integer expressions" because literal 0 is
  // treated as "singed".
  size_t kZero = 0;
  size_t log_size = 1024;

  AutoRollLogger* logger = new AutoRollLogger(
    Env::Default(), kTestDir, "", log_size, 0);

  LogMessage(logger, kSampleMessage.c_str());
  ASSERT_GT(logger->GetLogFileSize(), kZero);
  delete logger;

  // reopens the log file and an empty log file will be created.
  logger = new AutoRollLogger(
    Env::Default(), kTestDir, "", log_size, 0);
  ASSERT_EQ(logger->GetLogFileSize(), kZero);
  delete logger;
}

TEST(AutoRollLoggerTest, CompositeRollByTimeAndSizeLogger) {
  size_t time = 1, log_max_size = 1024 * 5;

  InitTestDb();

  AutoRollLogger logger(Env::Default(), kTestDir, "", log_max_size, time);

  // Test the ability to roll by size
  RollLogFileBySizeTest(
      &logger, log_max_size,
      kSampleMessage + ":CompositeRollByTimeAndSizeLogger");

  // Test the ability to roll by Time
  RollLogFileByTimeTest( &logger, time,
      kSampleMessage + ":CompositeRollByTimeAndSizeLogger");
}

TEST(AutoRollLoggerTest, CreateLoggerFromOptions) {
  DBOptions options;
  shared_ptr<Logger> logger;

  // Normal logger
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  ASSERT_TRUE(dynamic_cast<PosixLogger*>(logger.get()));

  // Only roll by size
  InitTestDb();
  options.max_log_file_size = 1024;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  AutoRollLogger* auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  ASSERT_TRUE(auto_roll_logger);
  RollLogFileBySizeTest(
      auto_roll_logger, options.max_log_file_size,
      kSampleMessage + ":CreateLoggerFromOptions - size");

  // Only roll by Time
  InitTestDb();
  options.max_log_file_size = 0;
  options.log_file_time_to_roll = 1;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  RollLogFileByTimeTest(
      auto_roll_logger, options.log_file_time_to_roll,
      kSampleMessage + ":CreateLoggerFromOptions - time");

  // roll by both Time and size
  InitTestDb();
  options.max_log_file_size = 1024 * 5;
  options.log_file_time_to_roll = 1;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  RollLogFileBySizeTest(
      auto_roll_logger, options.max_log_file_size,
      kSampleMessage + ":CreateLoggerFromOptions - both");
  RollLogFileByTimeTest(
      auto_roll_logger, options.log_file_time_to_roll,
      kSampleMessage + ":CreateLoggerFromOptions - both");
}

TEST(AutoRollLoggerTest, InfoLogLevel) {
  InitTestDb();

  size_t log_size = 8192;
  size_t log_lines = 0;
  // an extra-scope to force the AutoRollLogger to flush the log file when it
  // becomes out of scope.
  {
    AutoRollLogger logger(Env::Default(), kTestDir, "", log_size, 0);
    for (int log_level = InfoLogLevel::FATAL_LEVEL;
         log_level >= InfoLogLevel::DEBUG_LEVEL; log_level--) {
      logger.SetInfoLogLevel((InfoLogLevel)log_level);
      for (int log_type = InfoLogLevel::DEBUG_LEVEL;
           log_type <= InfoLogLevel::FATAL_LEVEL; log_type++) {
        // log messages with log level smaller than log_level will not be
        // logged.
        LogMessage((InfoLogLevel)log_type, &logger, kSampleMessage.c_str());
      }
      log_lines += InfoLogLevel::FATAL_LEVEL - log_level + 1;
    }
    for (int log_level = InfoLogLevel::FATAL_LEVEL;
         log_level >= InfoLogLevel::DEBUG_LEVEL; log_level--) {
      logger.SetInfoLogLevel((InfoLogLevel)log_level);

      // again, messages with level smaller than log_level will not be logged.
      Debug(&logger, "%s", kSampleMessage.c_str());
      Info(&logger, "%s", kSampleMessage.c_str());
      Warn(&logger, "%s", kSampleMessage.c_str());
      Error(&logger, "%s", kSampleMessage.c_str());
      Fatal(&logger, "%s", kSampleMessage.c_str());
      log_lines += InfoLogLevel::FATAL_LEVEL - log_level + 1;
    }
  }
  std::ifstream inFile(AutoRollLoggerTest::kLogFile.c_str());
  size_t lines = std::count(std::istreambuf_iterator<char>(inFile),
                         std::istreambuf_iterator<char>(), '\n');
  ASSERT_EQ(log_lines, lines);
  inFile.close();
}

TEST(AutoRollLoggerTest, LogFileExistence) {
  rocksdb::DB* db;
  rocksdb::Options options;
  string deleteCmd = "rm -rf " + kTestDir;
  ASSERT_EQ(system(deleteCmd.c_str()), 0);
  options.max_log_file_size = 100 * 1024 * 1024;
  options.create_if_missing = true;
  ASSERT_OK(rocksdb::DB::Open(options, kTestDir, &db));
  ASSERT_TRUE(env->FileExists(kLogFile));
  delete db;
}

}  // namespace rocksdb

int main(int argc, char** argv) {
  return rocksdb::test::RunAllTests();
}
<commit_msg>attempt to fix auto_roll_logger_test<commit_after>//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
#include <string>
#include <cmath>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include "util/testharness.h"
#include "util/auto_roll_logger.h"
#include "rocksdb/db.h"
#include <sys/stat.h>
#include <errno.h>

using namespace std;

namespace rocksdb {

class AutoRollLoggerTest {
 public:
  static void InitTestDb() {
    string deleteCmd = "rm -rf " + kTestDir;
    ASSERT_TRUE(system(deleteCmd.c_str()) == 0);
    Env::Default()->CreateDir(kTestDir);
  }

  void RollLogFileBySizeTest(AutoRollLogger* logger,
                             size_t log_max_size,
                             const string& log_message);
  uint64_t RollLogFileByTimeTest(AutoRollLogger* logger,
                                 size_t time,
                                 const string& log_message);

  static const string kSampleMessage;
  static const string kTestDir;
  static const string kLogFile;
  static Env* env;
};

const string AutoRollLoggerTest::kSampleMessage(
    "this is the message to be written to the log file!!");
const string AutoRollLoggerTest::kTestDir(test::TmpDir() + "/db_log_test");
const string AutoRollLoggerTest::kLogFile(test::TmpDir() + "/db_log_test/LOG");
Env* AutoRollLoggerTest::env = Env::Default();

// In this test we only want to Log some simple log message with
// no format. LogMessage() provides such a simple interface and
// avoids the [format-security] warning which occurs when you
// call Log(logger, log_message) directly.
namespace {
void LogMessage(Logger* logger, const char* message) {
  Log(logger, "%s", message);
}

void LogMessage(const InfoLogLevel log_level, Logger* logger,
                const char* message) {
  Log(log_level, logger, "%s", message);
}
}  // namespace

namespace {
void GetFileCreateTime(const std::string& fname, uint64_t* file_ctime) {
  struct stat s;
  if (stat(fname.c_str(), &s) != 0) {
    *file_ctime = (uint64_t)0;
  }
  *file_ctime = static_cast<uint64_t>(s.st_ctime);
}
}  // namespace

void AutoRollLoggerTest::RollLogFileBySizeTest(AutoRollLogger* logger,
                                               size_t log_max_size,
                                               const string& log_message) {
  logger->SetInfoLogLevel(InfoLogLevel::INFO_LEVEL);
  // measure the size of each message, which is supposed
  // to be equal or greater than log_message.size()
  LogMessage(logger, log_message.c_str());
  size_t message_size = logger->GetLogFileSize();
  size_t current_log_size = message_size;

  // Test the cases when the log file will not be rolled.
  while (current_log_size + message_size < log_max_size) {
    LogMessage(logger, log_message.c_str());
    current_log_size += message_size;
    ASSERT_EQ(current_log_size, logger->GetLogFileSize());
  }

  // Now the log file will be rolled
  LogMessage(logger, log_message.c_str());
  // Since rotation is checked before actual logging, we need to
  // trigger the rotation by logging another message.
  LogMessage(logger, log_message.c_str());

  ASSERT_TRUE(message_size == logger->GetLogFileSize());
}

uint64_t AutoRollLoggerTest::RollLogFileByTimeTest(
    AutoRollLogger* logger, size_t time, const string& log_message) {
  uint64_t expected_create_time;
  uint64_t actual_create_time;
  uint64_t total_log_size;
  ASSERT_OK(env->GetFileSize(kLogFile, &total_log_size));
  GetFileCreateTime(kLogFile, &expected_create_time);
  logger->SetCallNowMicrosEveryNRecords(0);

  // -- Write to the log for several times, which is supposed
  // to be finished before time.
  for (int i = 0; i < 10; ++i) {
     LogMessage(logger, log_message.c_str());
     ASSERT_OK(logger->GetStatus());
     // Make sure we always write to the same log file (by
     // checking the create time);
     GetFileCreateTime(kLogFile, &actual_create_time);

     // Also make sure the log size is increasing.
     ASSERT_EQ(expected_create_time, actual_create_time);
     ASSERT_GT(logger->GetLogFileSize(), total_log_size);
     total_log_size = logger->GetLogFileSize();
  }

  // -- Make the log file expire
  sleep(time);
  LogMessage(logger, log_message.c_str());

  // At this time, the new log file should be created.
  GetFileCreateTime(kLogFile, &actual_create_time);
  ASSERT_GT(actual_create_time, expected_create_time);
  ASSERT_LT(logger->GetLogFileSize(), total_log_size);
  expected_create_time = actual_create_time;

  return expected_create_time;
}

TEST(AutoRollLoggerTest, RollLogFileBySize) {
    InitTestDb();
    size_t log_max_size = 1024 * 5;

    AutoRollLogger logger(Env::Default(), kTestDir, "", log_max_size, 0);

    RollLogFileBySizeTest(&logger, log_max_size,
                          kSampleMessage + ":RollLogFileBySize");
}

TEST(AutoRollLoggerTest, RollLogFileByTime) {
    size_t time = 2;
    size_t log_size = 1024 * 5;

    InitTestDb();
    // -- Test the existence of file during the server restart.
    ASSERT_TRUE(!env->FileExists(kLogFile));
    AutoRollLogger logger(Env::Default(), kTestDir, "", log_size, time);
    ASSERT_TRUE(env->FileExists(kLogFile));

    RollLogFileByTimeTest(&logger, time, kSampleMessage + ":RollLogFileByTime");
}

TEST(AutoRollLoggerTest,
     OpenLogFilesMultipleTimesWithOptionLog_max_size) {
  // If only 'log_max_size' options is specified, then every time
  // when rocksdb is restarted, a new empty log file will be created.
  InitTestDb();
  // WORKAROUND:
  // avoid complier's complaint of "comparison between signed
  // and unsigned integer expressions" because literal 0 is
  // treated as "singed".
  size_t kZero = 0;
  size_t log_size = 1024;

  AutoRollLogger* logger = new AutoRollLogger(
    Env::Default(), kTestDir, "", log_size, 0);

  LogMessage(logger, kSampleMessage.c_str());
  ASSERT_GT(logger->GetLogFileSize(), kZero);
  delete logger;

  // reopens the log file and an empty log file will be created.
  logger = new AutoRollLogger(
    Env::Default(), kTestDir, "", log_size, 0);
  ASSERT_EQ(logger->GetLogFileSize(), kZero);
  delete logger;
}

TEST(AutoRollLoggerTest, CompositeRollByTimeAndSizeLogger) {
  size_t time = 2, log_max_size = 1024 * 5;

  InitTestDb();

  AutoRollLogger logger(Env::Default(), kTestDir, "", log_max_size, time);

  // Test the ability to roll by size
  RollLogFileBySizeTest(
      &logger, log_max_size,
      kSampleMessage + ":CompositeRollByTimeAndSizeLogger");

  // Test the ability to roll by Time
  RollLogFileByTimeTest( &logger, time,
      kSampleMessage + ":CompositeRollByTimeAndSizeLogger");
}

TEST(AutoRollLoggerTest, CreateLoggerFromOptions) {
  DBOptions options;
  shared_ptr<Logger> logger;

  // Normal logger
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  ASSERT_TRUE(dynamic_cast<PosixLogger*>(logger.get()));

  // Only roll by size
  InitTestDb();
  options.max_log_file_size = 1024;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  AutoRollLogger* auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  ASSERT_TRUE(auto_roll_logger);
  RollLogFileBySizeTest(
      auto_roll_logger, options.max_log_file_size,
      kSampleMessage + ":CreateLoggerFromOptions - size");

  // Only roll by Time
  InitTestDb();
  options.max_log_file_size = 0;
  options.log_file_time_to_roll = 2;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  RollLogFileByTimeTest(
      auto_roll_logger, options.log_file_time_to_roll,
      kSampleMessage + ":CreateLoggerFromOptions - time");

  // roll by both Time and size
  InitTestDb();
  options.max_log_file_size = 1024 * 5;
  options.log_file_time_to_roll = 2;
  ASSERT_OK(CreateLoggerFromOptions(kTestDir, "", env, options, &logger));
  auto_roll_logger =
    dynamic_cast<AutoRollLogger*>(logger.get());
  RollLogFileBySizeTest(
      auto_roll_logger, options.max_log_file_size,
      kSampleMessage + ":CreateLoggerFromOptions - both");
  RollLogFileByTimeTest(
      auto_roll_logger, options.log_file_time_to_roll,
      kSampleMessage + ":CreateLoggerFromOptions - both");
}

TEST(AutoRollLoggerTest, InfoLogLevel) {
  InitTestDb();

  size_t log_size = 8192;
  size_t log_lines = 0;
  // an extra-scope to force the AutoRollLogger to flush the log file when it
  // becomes out of scope.
  {
    AutoRollLogger logger(Env::Default(), kTestDir, "", log_size, 0);
    for (int log_level = InfoLogLevel::FATAL_LEVEL;
         log_level >= InfoLogLevel::DEBUG_LEVEL; log_level--) {
      logger.SetInfoLogLevel((InfoLogLevel)log_level);
      for (int log_type = InfoLogLevel::DEBUG_LEVEL;
           log_type <= InfoLogLevel::FATAL_LEVEL; log_type++) {
        // log messages with log level smaller than log_level will not be
        // logged.
        LogMessage((InfoLogLevel)log_type, &logger, kSampleMessage.c_str());
      }
      log_lines += InfoLogLevel::FATAL_LEVEL - log_level + 1;
    }
    for (int log_level = InfoLogLevel::FATAL_LEVEL;
         log_level >= InfoLogLevel::DEBUG_LEVEL; log_level--) {
      logger.SetInfoLogLevel((InfoLogLevel)log_level);

      // again, messages with level smaller than log_level will not be logged.
      Debug(&logger, "%s", kSampleMessage.c_str());
      Info(&logger, "%s", kSampleMessage.c_str());
      Warn(&logger, "%s", kSampleMessage.c_str());
      Error(&logger, "%s", kSampleMessage.c_str());
      Fatal(&logger, "%s", kSampleMessage.c_str());
      log_lines += InfoLogLevel::FATAL_LEVEL - log_level + 1;
    }
  }
  std::ifstream inFile(AutoRollLoggerTest::kLogFile.c_str());
  size_t lines = std::count(std::istreambuf_iterator<char>(inFile),
                         std::istreambuf_iterator<char>(), '\n');
  ASSERT_EQ(log_lines, lines);
  inFile.close();
}

TEST(AutoRollLoggerTest, LogFileExistence) {
  rocksdb::DB* db;
  rocksdb::Options options;
  string deleteCmd = "rm -rf " + kTestDir;
  ASSERT_EQ(system(deleteCmd.c_str()), 0);
  options.max_log_file_size = 100 * 1024 * 1024;
  options.create_if_missing = true;
  ASSERT_OK(rocksdb::DB::Open(options, kTestDir, &db));
  ASSERT_TRUE(env->FileExists(kLogFile));
  delete db;
}

}  // namespace rocksdb

int main(int argc, char** argv) {
  return rocksdb::test::RunAllTests();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: accel.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "vcl/arrange.hxx"

#include "osl/diagnose.h"

using namespace vcl;

// ----------------------------------------
// vcl::WindowArranger
//-----------------------------------------

WindowArranger::~WindowArranger()
{}

void WindowArranger::setParent( WindowArranger* i_pParent )
{
    OSL_VERIFY( i_pParent->m_pParentWindow == m_pParentWindow || m_pParentWindow == NULL );

    m_pParentArranger = i_pParent;
    m_pParentWindow = i_pParent->m_pParentWindow;
    setParentWindow( m_pParentWindow );
}

// ----------------------------------------
// vcl::RowOrColumn
//-----------------------------------------

RowOrColumn::~RowOrColumn()
{
    for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        it->deleteChild();
    }
}

WindowArranger* RowOrColumn::getChild( size_t i_nIndex ) const
{
    return i_nIndex < m_aElements.size() ? m_aElements[i_nIndex].m_pChild.get() : NULL;
}

Window* RowOrColumn::getWindow( size_t i_nIndex ) const
{
    return i_nIndex < m_aElements.size() ? m_aElements[i_nIndex].m_pElement : NULL;
}

Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
{
    Size aRet( 0, 0 );
    if( ! m_aElements.empty() )
    {
        if( m_bColumn )
            aRet.Height() -= m_nBorderWidth;
        else
            aRet.Width() -= m_nBorderWidth;
    }

    for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        // get the size of type of the managed element
        Size aElementSize( it->m_pElement
                           ? it->m_pElement->GetOptimalSize( i_eType )
                           : it->m_pChild
                             ? it->m_pChild->getOptimalSize( i_eType )
                             : Size() );
        if( m_bColumn )
        {
            // add the distance between elements
            aRet.Height() += m_nBorderWidth;
            // check if the width needs adjustment
            if( aRet.Width() < aElementSize.Width() )
                aRet.Width() = aElementSize.Width();
            aRet.Height() += aElementSize.Height();
        }
        else
        {
            // add the distance between elements
            aRet.Width() += m_nBorderWidth;
            // check if the height needs adjustment
            if( aRet.Height() < aElementSize.Height() )
                aRet.Height() = aElementSize.Height();
            aRet.Width() += aElementSize.Width();
        }
    }

    // add the outer border
    aRet.Width() += 2*m_nOuterBorder;
    aRet.Height() += 2*m_nOuterBorder;

    return aRet;
}

void RowOrColumn::distributeRowWidth( std::vector<Size>& io_rSizes, long /*i_nUsedWidth*/, long i_nExtraWidth )
{
    if( ! io_rSizes.empty() )
    {
        // distribute extra space evenly among elements
        size_t nElements = io_rSizes.size();
        long nDelta = i_nExtraWidth / nElements;
        for( size_t i = 0; i < nElements; i++ )
        {
            io_rSizes[i].Width() += nDelta;
            i_nExtraWidth -= nDelta;
        }
        // add the last pixels to the last row element
        if( i_nExtraWidth > 0 && nElements > 0 )
            io_rSizes.back().Width() += i_nExtraWidth;
    }
}

void RowOrColumn::resize()
{
    // check if we can get optimal size, else fallback to minimal size
    Size aOptSize( getOptimalSize( WINDOWSIZE_PREFERRED ) );
    WindowSizeType eType = WINDOWSIZE_PREFERRED;
    if( m_bColumn )
    {
        if( aOptSize.Height() > m_aManagedArea.GetHeight() )
            eType = WINDOWSIZE_MINIMUM;
    }
    else
    {
        if( aOptSize.Width() > m_aManagedArea.GetWidth() )
            eType = WINDOWSIZE_MINIMUM;
    }

    size_t nElements = m_aElements.size();
    // get all element sizes for sizing
    std::vector<Size> aElementSizes( nElements );
    long nUsedWidth = 2*m_nOuterBorder - (nElements ? m_nBorderWidth : 0);
    for( size_t i = 0; i < nElements; i++ )
    {
        aElementSizes[i] = m_aElements[i].m_pElement
                           ? m_aElements[i].m_pElement->GetOptimalSize( eType )
                           : m_aElements[i].m_pChild
                             ? m_aElements[i].m_pChild->getOptimalSize( eType )
                             : Size();
        if( m_bColumn )
        {
            aElementSizes[i].Width() = m_aManagedArea.GetWidth() - 2* m_nOuterBorder;
            nUsedWidth += aElementSizes[i].Height() + m_nBorderWidth;
        }
        else
        {
            aElementSizes[i].Height() = m_aManagedArea.GetHeight() - 2* m_nOuterBorder;
            nUsedWidth += aElementSizes[i].Width() + m_nBorderWidth;
        }
    }

    long nExtraWidth = m_aManagedArea.GetWidth() - nUsedWidth;
    if( nExtraWidth > 0 )
        if( ! m_bColumn )
            distributeRowWidth( aElementSizes, nUsedWidth, nExtraWidth );

    // get starting position
    Point aElementPos( m_aManagedArea.TopLeft() );
    // outer border
    aElementPos.X() += m_nOuterBorder;
    aElementPos.Y() += m_nOuterBorder;

    // position managed windows
    for( size_t i = 0; i < nElements; i++ )
    {
        // get the size of type of the managed element

        if( m_aElements[i].m_pElement ) // this actually is a window
        {
            m_aElements[i].m_pElement->SetPosSizePixel( aElementPos, aElementSizes[i] );
        }
        else if( m_aElements[i].m_pChild )
        {
            m_aElements[i].m_pChild->setManagedArea( Rectangle( aElementPos, aElementSizes[i] ) );
        }
        if( m_bColumn )
            aElementPos.Y() += m_nBorderWidth + aElementSizes[i].Height();
        else
            aElementPos.X() += m_nBorderWidth + aElementSizes[i].Width();
    }
}

void RowOrColumn::setParentWindow( Window* i_pNewParent )
{
    m_pParentWindow = i_pNewParent;
    for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        #if OSL_DEBUG_LEVEL > 0
        if( it->m_pElement )
        {
            OSL_VERIFY( it->m_pElement->GetParent() == i_pNewParent );
        }
        #endif
        if( it->m_pChild )
            it->m_pChild->setParentWindow( i_pNewParent );
    }
}

void RowOrColumn::addWindow( Window* i_pWindow, sal_Int32 i_nIndex )
{
    if( i_nIndex < 0 || size_t(i_nIndex) >= m_aElements.size() )
        m_aElements.push_back( WindowArranger::Element( i_pWindow, NULL ) );
    else
    {
        std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
        while( i_nIndex-- )
            ++it;
        m_aElements.insert( it, WindowArranger::Element( i_pWindow, NULL ) );
    }
}

void RowOrColumn::addChild( WindowArranger* i_pChild, sal_Int32 i_nIndex )
{
    if( i_nIndex < 0 || size_t(i_nIndex) >= m_aElements.size() )
        m_aElements.push_back( WindowArranger::Element( NULL, i_pChild ) );
    else
    {
        std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
        while( i_nIndex-- )
            ++it;
        m_aElements.insert( it, WindowArranger::Element( NULL, i_pChild ) );
    }
}

void RowOrColumn::remove( Window* i_pWindow )
{
    if( i_pWindow )
    {
        for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
            it != m_aElements.end(); ++it )
        {
            if( it->m_pElement == i_pWindow )
            {
                m_aElements.erase( it );
                return;
            }
        }
    }
}

void RowOrColumn::remove( WindowArranger* i_pChild )
{
    if( i_pChild )
    {
        for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
            it != m_aElements.end(); ++it )
        {
            if( it->m_pChild.get() == i_pChild )
            {
                m_aElements.erase( it );
                return;
            }
        }
    }
}

// ----------------------------------------
// vcl::Indenter
//-----------------------------------------

Indenter::~Indenter()
{
    m_aElement.deleteChild();
}

Size Indenter::getOptimalSize( WindowSizeType i_eType ) const
{
    Size aSize( m_aElement.m_pElement
                ? m_aElement.m_pElement->GetOptimalSize( i_eType )
                : m_aElement.m_pChild
                  ? m_aElement.m_pChild->getOptimalSize( i_eType )
                  : Size() );
    aSize.Width()  += 2*m_nOuterBorder + m_nIndent;
    aSize.Height() += 2*m_nOuterBorder;
    return aSize;
}

void Indenter::resize()
{
    Point aPt( m_aManagedArea.TopLeft() );
    aPt.X() += m_nOuterBorder + m_nIndent;
    aPt.Y() += m_nOuterBorder;
    Size aSz( m_aManagedArea.GetSize() );
    aSz.Width()  -= 2*m_nOuterBorder - m_nIndent;
    aSz.Height() -= 2*m_nOuterBorder;
    if( m_aElement.m_pElement )
        m_aElement.m_pElement->SetPosSizePixel( aPt, aSz );
    else if( m_aElement.m_pChild )
        m_aElement.m_pChild->setManagedArea( Rectangle( aPt, aSz ) );
}

void Indenter::setWindow( Window* i_pWindow )
{
    OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0) || i_pWindow == 0 );
    OSL_VERIFY( i_pWindow == 0 || i_pWindow->GetParent() == m_pParentWindow );
    m_aElement.m_pElement = i_pWindow;
}

void Indenter::setChild( WindowArranger* i_pChild )
{
    OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0 ) || i_pChild == 0 );
    m_aElement.m_pChild.reset( i_pChild );
}

void Indenter::setParentWindow( Window* i_pNewParent )
{
    m_pParentWindow = i_pNewParent;
    #if OSL_DEBUG_LEVEL > 0
    if( m_aElement.m_pElement )
    {
        OSL_VERIFY( m_aElement.m_pElement->GetParent() == i_pNewParent );
    }
    #endif
    if( m_aElement.m_pChild )
        m_aElement.m_pChild->setParentWindow( i_pNewParent );
}
<commit_msg>add completely useless PCH directive to satisfy stupid windows compiler<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: accel.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "precompiled_vcl.hxx"

#include "vcl/arrange.hxx"

#include "osl/diagnose.h"

using namespace vcl;

// ----------------------------------------
// vcl::WindowArranger
//-----------------------------------------

WindowArranger::~WindowArranger()
{}

void WindowArranger::setParent( WindowArranger* i_pParent )
{
    OSL_VERIFY( i_pParent->m_pParentWindow == m_pParentWindow || m_pParentWindow == NULL );

    m_pParentArranger = i_pParent;
    m_pParentWindow = i_pParent->m_pParentWindow;
    setParentWindow( m_pParentWindow );
}

// ----------------------------------------
// vcl::RowOrColumn
//-----------------------------------------

RowOrColumn::~RowOrColumn()
{
    for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        it->deleteChild();
    }
}

WindowArranger* RowOrColumn::getChild( size_t i_nIndex ) const
{
    return i_nIndex < m_aElements.size() ? m_aElements[i_nIndex].m_pChild.get() : NULL;
}

Window* RowOrColumn::getWindow( size_t i_nIndex ) const
{
    return i_nIndex < m_aElements.size() ? m_aElements[i_nIndex].m_pElement : NULL;
}

Size RowOrColumn::getOptimalSize( WindowSizeType i_eType ) const
{
    Size aRet( 0, 0 );
    if( ! m_aElements.empty() )
    {
        if( m_bColumn )
            aRet.Height() -= m_nBorderWidth;
        else
            aRet.Width() -= m_nBorderWidth;
    }

    for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        // get the size of type of the managed element
        Size aElementSize( it->m_pElement
                           ? it->m_pElement->GetOptimalSize( i_eType )
                           : it->m_pChild
                             ? it->m_pChild->getOptimalSize( i_eType )
                             : Size() );
        if( m_bColumn )
        {
            // add the distance between elements
            aRet.Height() += m_nBorderWidth;
            // check if the width needs adjustment
            if( aRet.Width() < aElementSize.Width() )
                aRet.Width() = aElementSize.Width();
            aRet.Height() += aElementSize.Height();
        }
        else
        {
            // add the distance between elements
            aRet.Width() += m_nBorderWidth;
            // check if the height needs adjustment
            if( aRet.Height() < aElementSize.Height() )
                aRet.Height() = aElementSize.Height();
            aRet.Width() += aElementSize.Width();
        }
    }

    // add the outer border
    aRet.Width() += 2*m_nOuterBorder;
    aRet.Height() += 2*m_nOuterBorder;

    return aRet;
}

void RowOrColumn::distributeRowWidth( std::vector<Size>& io_rSizes, long /*i_nUsedWidth*/, long i_nExtraWidth )
{
    if( ! io_rSizes.empty() )
    {
        // distribute extra space evenly among elements
        size_t nElements = io_rSizes.size();
        long nDelta = i_nExtraWidth / nElements;
        for( size_t i = 0; i < nElements; i++ )
        {
            io_rSizes[i].Width() += nDelta;
            i_nExtraWidth -= nDelta;
        }
        // add the last pixels to the last row element
        if( i_nExtraWidth > 0 && nElements > 0 )
            io_rSizes.back().Width() += i_nExtraWidth;
    }
}

void RowOrColumn::resize()
{
    // check if we can get optimal size, else fallback to minimal size
    Size aOptSize( getOptimalSize( WINDOWSIZE_PREFERRED ) );
    WindowSizeType eType = WINDOWSIZE_PREFERRED;
    if( m_bColumn )
    {
        if( aOptSize.Height() > m_aManagedArea.GetHeight() )
            eType = WINDOWSIZE_MINIMUM;
    }
    else
    {
        if( aOptSize.Width() > m_aManagedArea.GetWidth() )
            eType = WINDOWSIZE_MINIMUM;
    }

    size_t nElements = m_aElements.size();
    // get all element sizes for sizing
    std::vector<Size> aElementSizes( nElements );
    long nUsedWidth = 2*m_nOuterBorder - (nElements ? m_nBorderWidth : 0);
    for( size_t i = 0; i < nElements; i++ )
    {
        aElementSizes[i] = m_aElements[i].m_pElement
                           ? m_aElements[i].m_pElement->GetOptimalSize( eType )
                           : m_aElements[i].m_pChild
                             ? m_aElements[i].m_pChild->getOptimalSize( eType )
                             : Size();
        if( m_bColumn )
        {
            aElementSizes[i].Width() = m_aManagedArea.GetWidth() - 2* m_nOuterBorder;
            nUsedWidth += aElementSizes[i].Height() + m_nBorderWidth;
        }
        else
        {
            aElementSizes[i].Height() = m_aManagedArea.GetHeight() - 2* m_nOuterBorder;
            nUsedWidth += aElementSizes[i].Width() + m_nBorderWidth;
        }
    }

    long nExtraWidth = m_aManagedArea.GetWidth() - nUsedWidth;
    if( nExtraWidth > 0 )
        if( ! m_bColumn )
            distributeRowWidth( aElementSizes, nUsedWidth, nExtraWidth );

    // get starting position
    Point aElementPos( m_aManagedArea.TopLeft() );
    // outer border
    aElementPos.X() += m_nOuterBorder;
    aElementPos.Y() += m_nOuterBorder;

    // position managed windows
    for( size_t i = 0; i < nElements; i++ )
    {
        // get the size of type of the managed element

        if( m_aElements[i].m_pElement ) // this actually is a window
        {
            m_aElements[i].m_pElement->SetPosSizePixel( aElementPos, aElementSizes[i] );
        }
        else if( m_aElements[i].m_pChild )
        {
            m_aElements[i].m_pChild->setManagedArea( Rectangle( aElementPos, aElementSizes[i] ) );
        }
        if( m_bColumn )
            aElementPos.Y() += m_nBorderWidth + aElementSizes[i].Height();
        else
            aElementPos.X() += m_nBorderWidth + aElementSizes[i].Width();
    }
}

void RowOrColumn::setParentWindow( Window* i_pNewParent )
{
    m_pParentWindow = i_pNewParent;
    for( std::vector< WindowArranger::Element >::const_iterator it = m_aElements.begin();
         it != m_aElements.end(); ++it )
    {
        #if OSL_DEBUG_LEVEL > 0
        if( it->m_pElement )
        {
            OSL_VERIFY( it->m_pElement->GetParent() == i_pNewParent );
        }
        #endif
        if( it->m_pChild )
            it->m_pChild->setParentWindow( i_pNewParent );
    }
}

void RowOrColumn::addWindow( Window* i_pWindow, sal_Int32 i_nIndex )
{
    if( i_nIndex < 0 || size_t(i_nIndex) >= m_aElements.size() )
        m_aElements.push_back( WindowArranger::Element( i_pWindow, NULL ) );
    else
    {
        std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
        while( i_nIndex-- )
            ++it;
        m_aElements.insert( it, WindowArranger::Element( i_pWindow, NULL ) );
    }
}

void RowOrColumn::addChild( WindowArranger* i_pChild, sal_Int32 i_nIndex )
{
    if( i_nIndex < 0 || size_t(i_nIndex) >= m_aElements.size() )
        m_aElements.push_back( WindowArranger::Element( NULL, i_pChild ) );
    else
    {
        std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
        while( i_nIndex-- )
            ++it;
        m_aElements.insert( it, WindowArranger::Element( NULL, i_pChild ) );
    }
}

void RowOrColumn::remove( Window* i_pWindow )
{
    if( i_pWindow )
    {
        for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
            it != m_aElements.end(); ++it )
        {
            if( it->m_pElement == i_pWindow )
            {
                m_aElements.erase( it );
                return;
            }
        }
    }
}

void RowOrColumn::remove( WindowArranger* i_pChild )
{
    if( i_pChild )
    {
        for( std::vector< WindowArranger::Element >::iterator it = m_aElements.begin();
            it != m_aElements.end(); ++it )
        {
            if( it->m_pChild.get() == i_pChild )
            {
                m_aElements.erase( it );
                return;
            }
        }
    }
}

// ----------------------------------------
// vcl::Indenter
//-----------------------------------------

Indenter::~Indenter()
{
    m_aElement.deleteChild();
}

Size Indenter::getOptimalSize( WindowSizeType i_eType ) const
{
    Size aSize( m_aElement.m_pElement
                ? m_aElement.m_pElement->GetOptimalSize( i_eType )
                : m_aElement.m_pChild
                  ? m_aElement.m_pChild->getOptimalSize( i_eType )
                  : Size() );
    aSize.Width()  += 2*m_nOuterBorder + m_nIndent;
    aSize.Height() += 2*m_nOuterBorder;
    return aSize;
}

void Indenter::resize()
{
    Point aPt( m_aManagedArea.TopLeft() );
    aPt.X() += m_nOuterBorder + m_nIndent;
    aPt.Y() += m_nOuterBorder;
    Size aSz( m_aManagedArea.GetSize() );
    aSz.Width()  -= 2*m_nOuterBorder - m_nIndent;
    aSz.Height() -= 2*m_nOuterBorder;
    if( m_aElement.m_pElement )
        m_aElement.m_pElement->SetPosSizePixel( aPt, aSz );
    else if( m_aElement.m_pChild )
        m_aElement.m_pChild->setManagedArea( Rectangle( aPt, aSz ) );
}

void Indenter::setWindow( Window* i_pWindow )
{
    OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0) || i_pWindow == 0 );
    OSL_VERIFY( i_pWindow == 0 || i_pWindow->GetParent() == m_pParentWindow );
    m_aElement.m_pElement = i_pWindow;
}

void Indenter::setChild( WindowArranger* i_pChild )
{
    OSL_VERIFY( (m_aElement.m_pElement == 0 && m_aElement.m_pChild == 0 ) || i_pChild == 0 );
    m_aElement.m_pChild.reset( i_pChild );
}

void Indenter::setParentWindow( Window* i_pNewParent )
{
    m_pParentWindow = i_pNewParent;
    #if OSL_DEBUG_LEVEL > 0
    if( m_aElement.m_pElement )
    {
        OSL_VERIFY( m_aElement.m_pElement->GetParent() == i_pNewParent );
    }
    #endif
    if( m_aElement.m_pChild )
        m_aElement.m_pChild->setParentWindow( i_pNewParent );
}
<|endoftext|>


<commit_before><commit_msg>Be more specific in warning<commit_after><|endoftext|>