text:
import sys

from mule_local.JobCompileOptions import *
from mule.InfoError import *

__all__ = ['JobRuntimeOptions']

class JobRuntimeOptions(InfoError):

    def __init__(self, dummy_init = False):

        self.init_phase = True

        InfoError.__init__(self, "JobRuntimeOptions")

        # String to job directory.
        # This is required to generate additional files such as REXI coefficients stored separately in each job directory
        self.p_job_dirpath = None

        self.space_res_spectral = None
        self.space_res_physical = None

        self.output_timestep_size = None
        self.output_filename = ''
        self.output_file_mode = ''

        self.f_sphere = None
        self.verbosity = 0

        self.instability_checks = None

        # Use 14 digits per default
        self.floating_point_output_digits = 12

        self.timestepping_method = None
        self.timestepping_order = 1
        self.timestepping_order2 = 1

        self.semi_lagrangian_max_iterations = None
        self.semi_lagrangian_convergence_threshold = None

        self.timestep_size = None
        self.max_timesteps_nr = -1

        self.normal_mode_analysis = None

        #
        # REXI method:
        #
        # 'file': default & can be used to also load terry, cauchy & butcher coefficients via text files
        # 'direct': Use direct solution, if available
        # 'terry': deprecated T-REXI method
        # 'butcher': deprecated Butcher-REXI method
        #
        self.rexi_method = 'file'

        # Generic REXI parameters
        self.rexi_sphere_preallocation = 0

        # List of REXI Coefficients
        self.rexi_files_coefficients = []

        # Parameters for T-REXI method
        self.rexi_terry_m = 0
        self.rexi_terry_h = 0.15
        self.rexi_terry_reduce_to_half = 0

        # Parameters for Cauchy Contour integral method
        self.rexi_ci_primitive = 'circle'
        self.rexi_ci_n = 128
        self.rexi_ci_max_real = None
        self.rexi_ci_max_imag = None
        self.rexi_ci_sx = None
        self.rexi_ci_sy = None
        self.rexi_ci_mu = None

        ## Parameters for direct exp. solver
        self.exp_direct_precompute_phin = 0;

        self.gui = None

        self.polvani_rossby = None
        self.polvani_froude = None

        # Parameters for LibPFASST
        self.libpfasst_nlevels = None
        self.libpfasst_niters = None
        self.libpfasst_nnodes = None
        self.libpfasst_nsweeps = None
        self.libpfasst_nodes_type = None
        self.libpfasst_coarsening_multiplier = None
        self.libpfasst_use_rexi = None
        self.libpfasst_implicit_coriolis_force = None
        self.libpfasst_use_rk_stepper = None
        self.libpfasst_u2 = None
        self.libpfasst_u4 = None
        self.libpfasst_u6 = None
        self.libpfasst_u8 = None
        self.libpfasst_u_fields = None

        self.gravitation= None
        self.h0 = None
        self.sphere_rotating_coriolis_omega = None
        self.sphere_radius = None

        self.plane_domain_size = None    # Plane: Domain size

        # Specify benchmark name
        self.benchmark_name = None

        self.benchmark_galewsky_umax = -1
        self.benchmark_galewsky_hamp = -1
        self.benchmark_galewsky_phi2 = -1

        self.benchmark_normal_modes_case = None

        self.semi_lagrangian_approximate_sphere_geometry = 0

        self.space_grid_use_c_staggering = 0
        self.space_use_spectral_basis_diffs = 1
        self.viscosity = None
        self.viscosity_order = None

        #self.uselineardiv = None
        self.use_nonlinear_only_visc = None
        self.advection_rotation_angle = None
        self.advection_velocity = None
        self.max_simulation_time = 0.001
        self.max_wallclock_time = -1

        self.compute_error = 0

        self.reuse_plans = "quick"
        self.comma_separated_tags = None

        ## parareal parameters
        self.parareal_enabled = 0
        self.parareal_coarse_slices = None
        self.parareal_convergence_threshold = -1
        self.parareal_verbosity = 0
        self.parareal_max_simulation_time = None
        self.parareal_coarse_timestepping_method = None
        self.parareal_coarse_timestepping_order = 1
        self.parareal_coarse_timestepping_order2 = 1
        self.parareal_coarse_timestep_size = -1;
        self.parareal_load_ref_csv_files = 0;
        self.parareal_path_ref_csv_files = "";
        self.parareal_load_fine_csv_files = 0;
        self.parareal_path_fine_csv_files = "";
        self.parareal_store_iterations = 1;

        #
        # User defined parameters
        # Each new entry must set three values:
        #
        # 'id': The id for the unique id
        # 'value': The value of the parameter
        # 'option': The program option
        #
        # example:
        # self.user_defined_parameters['test-mode'] = {'id': 'tm', 'value': 1, 'option': '--test-mode='}
        #
        self.user_defined_parameters = {}

        self.init_phase = False

    def __setattr__(self, name, value):

        if name != 'init_phase':
            if not self.init_phase:
                if not name in self.__dict__:
                    raise Exception("Attribute '"+name+"' does not exist!")

        self.__dict__[name] = value

    def load_from_dict(self, d):
        if 'rexi_method' in d:
            self.rexi_method = d['rexi_method']

        if 'sphere_preallocation' in d:
            self.rexi_sphere_preallocation = d['sphere_preallocation']

        if 'terry_m' in d:
            self.rexi_terry_m = d['terry_m']

        if 'terry_h' in d:
            self.rexi_terry_h = d['terry_h']

        if 'ci_n' in d:
            self.rexi_ci_n = int(d['ci_n'])

        if 'ci_max_real' in d:
            self.rexi_ci_max_real = float(d['ci_max_real'])

        if 'ci_max_imag' in d:
            self.rexi_ci_max_imag = float(d['ci_max_imag'])

        if 'ci_sx' in d:
            self.rexi_ci_sx = float(d['ci_sx'])

        if 'ci_sy' in d:
            self.rexi_ci_sy = float(d['ci_sy'])

        if 'ci_mu' in d:
            self.rexi_ci_mu = float(d['ci_mu'])

        if 'ci_primitive' in d:
            self.rexi_ci_primitive = float(d['ci_primitive'])

        if 'polvani_rossby' in d:
            self.polvani_rossby = float(d['polvani_rossby'])

        if 'polvani_froude' in d:
            self.polvani_froude = float(d['polvani_froude'])

        if 'timestep_size' in d:
            self.timestep_size = float(d['timestep_size'])

        if 'reuse_plans' in d:
            self.reuse_plans = int(d['reuse_plans'])

        if 'comma_separated_tags' in d:
            self.comma_separated_tags = d['comma_separated_tags']

        if 'exp_direct_precompute_phin' in d:
            self.exp_direct_precompute_phin = d['exp_direct_precompute_phin']

    def getUniqueID(self, compileOptions : JobCompileOptions, filter_list : list = []):
        idstr = ''

        if not 'runtime.benchmark' in filter_list:
            if self.benchmark_name != None:
                idstr += '_b'+str(self.benchmark_name)

        if not 'runtime.galewsky_params' in filter_list:
            if self.benchmark_galewsky_umax > 0:
                idstr += '_bgu'+str("{:.4E}".format(self.benchmark_galewsky_umax))

            if self.benchmark_galewsky_hamp > 0:
                idstr += '_bgh'+str("{:.4E}".format(self.benchmark_galewsky_hamp))

            if self.benchmark_galewsky_phi2 > 0:
                idstr += '_bgp'+str("{:.4E}".format(self.benchmark_galewsky_phi2))

        if not 'runtime.normal_modes_params' in filter_list:
            if self.benchmark_normal_modes_case != None:
                idstr += '_bcase'+str(self.benchmark_normal_modes_case)

        if not 'runtime.simparams' in filter_list:
            if self.gravitation!= None:
                idstr += '_g'+str("{:05.2f}".format(self.gravitation))
            if self.h0 != None:
                idstr += '_h'+str("{:010.3f}".format(self.h0))
            if self.sphere_rotating_coriolis_omega != None:
                idstr += '_f'+str("{:e}".format(self.sphere_rotating_coriolis_omega))

            if compileOptions.sphere_spectral_space == 'enable':
                if self.sphere_radius != None:
                    idstr += '_a'+str(self.sphere_radius)
                if self.f_sphere != None:
                    idstr += '_fsph'+str(self.f_sphere)

            if self.viscosity != None:
                idstr += '_u'+str(self.viscosity)
            if self.viscosity_order != None:
                idstr += '_U'+str(self.viscosity_order)

            if self.advection_rotation_angle != None:
                idstr += '_ar'+str(self.advection_rotation_angle)

            if self.advection_velocity != None:
                idstr += '_av'+str(self.advection_velocity).replace(",", "_")

        if 'timestep' in filter_list:
            raise Exception("Deprecated")

        if not 'runtime.timestepping' in filter_list:
            if self.timestepping_method != None:
                if not 'runtime.timestepping_method' in filter_list:
                    idstr += '_tsm_'+self.timestepping_method

                if not 'runtime.timestepping_order' in filter_list:
                    idstr += '_tso'+str(self.timestepping_order)
                    idstr += '_tsob'+str(self.timestepping_order2)

                if not 'runtime.semi_lagrangian' in filter_list:
                    if self.semi_lagrangian_max_iterations != None:
                        idstr += '_sli'+str(self.semi_lagrangian_max_iterations)

                    if self.semi_lagrangian_convergence_threshold != None:
                        idstr += '_slc'+str("{:0.5e}".format(self.semi_lagrangian_convergence_threshold))

            if not 'runtime.timestepping_size' in filter_list:
                if self.timestep_size != None:
                    # Leading number is the total number of digits!
                    if self.timestep_size < 1:
                        idstr += '_dt'+str("{:0.8e}".format(self.timestep_size))
                    else:
                        idstr += '_dt'+str("{:08.2f}".format(self.timestep_size))

            if not 'runtime.max_timesteps_nr' in filter_list:
                if self.max_timesteps_nr != -1:
                    idstr += '_T'+str(self.max_timesteps_nr).zfill(3)

            if not 'runtime.max_wallclock_time' in filter_list:
                idstr += '_W'+str(self.max_wallclock_time).zfill(6)

        if not 'runtime.rexi' in filter_list:
            if self.rexi_method != '' and self.rexi_method != None:
                if self.rexi_method == 'direct':
                    idstr += '_REXIDIRECT'
                else:
                    if self.rexi_method == "file":
                        if len(self.rexi_files_coefficients) != 0:
                            idstr += '_FREXI'
                            if not 'runtime.rexi_params' in filter_list:

                                for i in range(len(self.rexi_files_coefficients)):
                                    r = self.rexi_files_coefficients[i]
                                    if r.unique_id_string == None:
                                        raise Exception("Unique ID String missing for REXI coefficients")

                                    if not 'runtime.rexi_params_phi'+str(i) in filter_list:
                                        idstr += "_"+r.unique_id_string.replace("REXI", "")

                    elif self.rexi_method == "terry":
                        idstr += '_TREXI'
                        if not 'runtime.rexi_params' in filter_list:
                            idstr += '_m'+str(self.rexi_terry_m).zfill(8)
                            idstr += '_h'+str(self.rexi_terry_h)
                            idstr += '_r'+str(self.rexi_terry_reduce_to_half)

                    elif self.rexi_method == "ci":
                        idstr += '_CIREXI'

                        if not 'runtime.rexi_params' in filter_list:
                            idstr += '_n'+str(self.rexi_ci_n).zfill(8)
                            if self.rexi_ci_max_real != None:
                                if self.rexi_ci_max_real != None:
                                    idstr += '_mr'+str(float(self.rexi_ci_max_real))
                                if self.rexi_ci_max_imag != None:
                                    idstr += '_mi'+str(float(self.rexi_ci_max_imag))
                            else:
                                if self.rexi_ci_sx != None:
                                    idstr += '_sx'+str(float(self.rexi_ci_sx))
                                if self.rexi_ci_sy != None:
                                    idstr += '_sy'+str(float(self.rexi_ci_sy))
                                if self.rexi_ci_mu != None:
                                    idstr += '_mu'+str(float(self.rexi_ci_mu))
                            idstr += '_pr'+str(self.rexi_ci_primitive)

                    #idstr += '_rexithreadpar'+str(1 if self.rexi_thread_par else 0)

        if not 'runtime.polvani' in filter_list:
            if self.polvani_rossby != None:
                idstr += '_PR'+str(self.polvani_rossby)

            if self.polvani_froude != None:
                idstr += '_PF'+str(self.polvani_froude)

        # LibPFASST attributes
        if not 'runtime.libpfasst' in filter_list:
            if self.libpfasst_nlevels != None:
                idstr += '_pf_nlev'+str(self.libpfasst_nlevels)
            if self.libpfasst_niters != None:
                idstr += '_pf_nit'+str(self.libpfasst_niters)
            if self.libpfasst_nnodes != None:
                idstr += '_pf_nnod'+str(self.libpfasst_nnodes)
            if self.libpfasst_nsweeps != None:
                idstr += '_pf_nswps'+str(self.libpfasst_nsweeps)
            if self.libpfasst_nodes_type != None:
                idstr += '_'+str(self.libpfasst_nodes_type)
            if self.libpfasst_coarsening_multiplier != None:
                idstr += '_pf_coars'+str(self.libpfasst_coarsening_multiplier)
            if self.libpfasst_use_rexi != None:
                idstr += '_pf_rexi'+str(self.libpfasst_use_rexi)
            if self.libpfasst_implicit_coriolis_force != None:
                idstr += '_pf_icf'+str(self.libpfasst_implicit_coriolis_force)
            if self.libpfasst_use_rk_stepper != None:
                idstr += '_pf_rk'+str(self.libpfasst_use_rk_stepper)

        if not 'runtime.disc_space' in filter_list:
            if self.space_res_spectral != None:
                if isinstance(self.space_res_spectral, (list, tuple)):
                    idstr += '_M'+str("x".join([str(x).zfill(4) for x in self.space_res_spectral]))
                else:
                    idstr += '_M'+str(self.space_res_spectral).zfill(4)

            if self.space_res_physical != None:
                if isinstance(self.space_res_physical, (list, tuple)):
                    idstr += '_N'+str("x".join([str(x).zfill(4) for x in self.space_res_physical]))
                else:
                    idstr += '_N'+str(self.space_res_physical).zfill(4)

            if self.plane_domain_size != None:
                if isinstance(self.plane_domain_size, (list, tuple)):
                    idstr += '_X'+str("x".join([str(x).zfill(4) for x in self.plane_domain_size]))
                else:
                    idstr += '_X'+str(self.plane_domain_size)

            if self.semi_lagrangian_approximate_sphere_geometry == None:
                idstr += '_spap'+str(self.semi_lagrangian_approximate_sphere_geometry)

            if self.space_use_spectral_basis_diffs != 1:
                idstr += '_spd'+str(self.space_use_spectral_basis_diffs)

        if not 'runtime.reuse_plans' in filter_list:
            if self.reuse_plans != -1:
                idstr += '_plans'+str(self.reuse_plans)

        if not 'runtime.comma_separated_tags' in filter_list:
            if self.comma_separated_tags != None:
                idstr += '_tags'+str(self.comma_separated_tags)

        if not 'runtime.parareal' in filter_list:
            if self.parareal_enabled:
                if not 'runtime.parareal_coarse_slices' in filter_list:
                    idstr += '_par_'+str(self.parareal_coarse_slices)
                if not 'runtime.parareal_coarse_timestepping_method' in filter_list:
                    idstr += '_ptsm_'+str(self.parareal_coarse_timestepping_method)
                if not 'runtime.parareal_coarse_timestep_size' in filter_list:
                    idstr += '_pDt_'+str(self.parareal_coarse_timestep_size)
                if not 'runtime.parareal_store_iterations' in filter_list:
                    idstr += '_pStore_'+str(self.parareal_store_iterations)

        if idstr != '':
            idstr = "RT"+idstr

        for key, param in self.user_defined_parameters.items():
            idstr += '_'+param['id']+str(param['value'])

        print(idstr)

        return idstr

    def getRuntimeOptions(self):
        retval = ''

        self.cleanup_options()

        if self.gui != None:
            retval += ' -G '+str(self.gui)

        if self.gravitation!= None:
            retval += ' -g '+str(self.gravitation)
        if self.h0 != None:
            retval += ' -H '+str(self.h0)
        if self.sphere_rotating_coriolis_omega != None:
            retval += ' -f '+str(self.sphere_rotating_coriolis_omega)
        if self.sphere_radius != None:
            retval += ' -a '+str(self.sphere_radius)
        if self.f_sphere != None:
            retval += ' -F '+str(self.f_sphere)

        if self.space_res_spectral != None:
            if isinstance(self.space_res_spectral, (list, tuple)):
                retval += ' -M '+str(",".join([str(x) for x in self.space_res_spectral]))
            else:
                retval += ' -M '+str(self.space_res_spectral)

        if self.space_res_physical != None:
            if isinstance(self.space_res_physical, (list, tuple)):
                retval += ' -N '+str(",".join([str(x) for x in self.space_res_physical]))
            else:
                retval += ' -N '+str(self.space_res_physical)

        retval += ' --space-grid-use-c-staggering='+str(self.space_grid_use_c_staggering)
        retval += ' -S '+str(self.space_use_spectral_basis_diffs)

        if self.plane_domain_size != None:
            if isinstance(self.plane_domain_size, (int, float)):
                retval += ' -X '+str(self.plane_domain_size)
                retval += ' -Y '+str(self.plane_domain_size)
            else:
                retval += ' -X '+str(self.plane_domain_size[0])
                retval += ' -Y '+str(self.plane_domain_size[1])

        if self.benchmark_name != None:
            retval += ' --benchmark-name='+str(self.benchmark_name)

        if self.benchmark_normal_modes_case != None:
            retval += ' --benchmark-normal-modes-case='+str(self.benchmark_normal_modes_case)

        retval += ' -v '+str(self.verbosity)

        if self.timestep_size != None:
            retval += ' --dt='+str(self.timestep_size)

        if self.max_timesteps_nr != -1:
            retval += ' -T '+str(self.max_timesteps_nr)

        if self.output_timestep_size != None:
            retval += ' -o '+str(self.output_timestep_size)

        if self.output_filename != '':
            retval += ' --output-file-name='+self.output_filename
        elif self.output_timestep_size == None:
            retval += ' --output-file-name=-'

        if self.output_file_mode != '':
            retval += ' --output-file-mode='+self.output_file_mode

        if self.viscosity != None:
            retval += ' -u '+str(self.viscosity)

        if self.viscosity_order != None:
            retval += ' -U '+str(self.viscosity_order)

        retval += ' -t '+str(self.max_simulation_time)

        retval += ' --max-wallclock-time '+str(self.max_wallclock_time)

        if self.instability_checks != None:
            retval += ' --instability-checks='+str(self.instability_checks)

        if self.floating_point_output_digits >= 0:
            retval += ' -d '+str(self.floating_point_output_digits)

        #if self.uselineardiv != None:
        #    retval += ' --use-only-linear-div='+str(self.uselineardiv)

        if self.use_nonlinear_only_visc != None:
            retval += ' --use-nonlinear-only-visc='+str(self.use_nonlinear_only_visc)

        if self.advection_rotation_angle != None:
            retval += ' --advection-rotation-angle='+str(self.advection_rotation_angle)

        if self.advection_velocity != None:
            retval += ' --advection-velocity='+str(self.advection_velocity)

        if self.timestepping_method != None:
            retval += ' --timestepping-method='+self.timestepping_method
            retval += ' --timestepping-order='+str(self.timestepping_order)
            retval += ' --timestepping-order2='+str(self.timestepping_order2)

        if self.semi_lagrangian_max_iterations != None:
            retval += ' --semi-lagrangian-max-iterations='+str(self.semi_lagrangian_max_iterations)

        if self.semi_lagrangian_convergence_threshold != None:
            retval += ' --semi-lagrangian-convergence-threshold='+str(self.semi_lagrangian_convergence_threshold)

        if self.normal_mode_analysis != None:
            retval += ' --normal-mode-analysis-generation='+str(self.normal_mode_analysis)

        if self.rexi_method != '' and self.rexi_method != None:
            retval += ' --rexi-method='+str(self.rexi_method)

            if self.rexi_method == 'direct':
                retval += ' --exp-direct-precompute-phin='+str(self.exp_direct_precompute_phin)

            else:
                retval += ' --rexi-sphere-preallocation='+str(self.rexi_sphere_preallocation)

                if self.rexi_method == 'file':

                    if self.p_job_dirpath == None:
                        raise Exception("self.p_job_dirpath not set!")

                    # REXI Files
                    file_params = []
                    for coeffs in self.rexi_files_coefficients:
                        coeff_filepath = self.p_job_dirpath+'/'+coeffs.unique_id_string
                        coeffs.write_file(coeff_filepath)
                        file_params.append(coeffs.function_name+':'+coeff_filepath)

                    retval += ' --rexi-files='+(",".join(file_params))

                elif self.rexi_method == 'terry':

                    # REXI Terry
                    retval += ' --rexi-terry-m='+str(self.rexi_terry_m)
                    retval += ' --rexi-terry-h='+str(self.rexi_terry_h)
                    retval += ' --rexi-terry-reduce-to-half='+str(self.rexi_terry_reduce_to_half)

                elif self.rexi_method == 'ci':

                    retval += ' --rexi-ci-primitive='+str(self.rexi_ci_primitive)
                    retval += ' --rexi-ci-n='+str(self.rexi_ci_n)

                    if self.rexi_ci_max_real != None:
                        retval += ' --rexi-ci-max-real='+str(self.rexi_ci_max_real)
                        if self.rexi_ci_max_imag != None:
                            retval += ' --rexi-ci-max-imag='+str(self.rexi_ci_max_imag)
                    else:
                        if self.rexi_ci_sx != None:
                            retval += ' --rexi-ci-sx='+str(self.rexi_ci_sx)
                        if self.rexi_ci_sy != None:
                            retval += ' --rexi-ci-sy='+str(self.rexi_ci_sy)
                        if self.rexi_ci_mu != None:
                            retval += ' --rexi-ci-mu='+str(self.rexi_ci_mu)

        if self.polvani_rossby != None:
            retval += ' --polvani-rossby='+str(self.polvani_rossby)

        if self.polvani_froude != None:
            retval += ' --polvani-froude='+str(self.polvani_froude)

        # TODO: think about a way to check that we're in LibPFASST mode s.th. we do not have to check every if statement
        if self.libpfasst_nlevels != None:
            retval += ' --libpfasst-nlevels='+str(self.libpfasst_nlevels)
        if self.libpfasst_niters != None:
            retval += ' --libpfasst-niters='+str(self.libpfasst_niters)
        if self.libpfasst_nnodes != None:
            retval += ' --libpfasst-nnodes='+str(self.libpfasst_nnodes)
        if self.libpfasst_nsweeps != None:
            retval += ' --libpfasst-nsweeps='+str(self.libpfasst_nsweeps)
        if self.libpfasst_nodes_type != None:
            retval += ' --libpfasst-nodes-type='+str(self.libpfasst_nodes_type)
        if self.libpfasst_coarsening_multiplier != None:
            retval += ' --libpfasst-coarsening-multiplier='+str(self.libpfasst_coarsening_multiplier)
        if self.libpfasst_use_rexi != None:
            retval += ' --libpfasst-use-rexi='+str(self.libpfasst_use_rexi)
        if self.libpfasst_implicit_coriolis_force != None:
            retval += ' --libpfasst-implicit-coriolis-force='+str(self.libpfasst_implicit_coriolis_force)
        if self.libpfasst_use_rk_stepper != None:
            retval += ' --libpfasst-use-rk-stepper='+str(self.libpfasst_use_rk_stepper)
        if self.libpfasst_u2 != None:
            retval += ' --libpfasst-u2='+str(self.libpfasst_u2)
        if self.libpfasst_u4 != None:
            retval += ' --libpfasst-u4='+str(self.libpfasst_u4)
        if self.libpfasst_u6 != None:
            retval += ' --libpfasst-u6='+str(self.libpfasst_u6)
        if self.libpfasst_u8 != None:
            retval += ' --libpfasst-u8='+str(self.libpfasst_u8)
        if self.libpfasst_u_fields != None:
            retval += ' --libpfasst-u-fields='+str(self.libpfasst_u_fields)

        retval += ' --semi-lagrangian-approximate-sphere-geometry='+str(self.semi_lagrangian_approximate_sphere_geometry)

        retval += ' --compute-error='+str(self.compute_error)

        retval += ' --reuse-plans='+str(self.reuse_plans)

        if self.comma_separated_tags != None:
            retval += ' --comma-separated-tags='+str(self.comma_separated_tags)

        ## Parareal parameters
        if self.parareal_enabled:
            retval += " --parareal-enable=1"
            retval += " --parareal-coarse-slices="+str(self.parareal_coarse_slices)
            retval += " --parareal-convergence-threshold="+str(self.parareal_convergence_threshold)
            retval += " --parareal-verbosity="+str(self.parareal_verbosity)
            retval += " --parareal-max-simulation-time="+str(self.parareal_max_simulation_time)
            retval += " --parareal-coarse-timestepping-method="+str(self.parareal_coarse_timestepping_method)
            retval += " --parareal-coarse-timestepping-order="+str(self.parareal_coarse_timestepping_order)
            retval += " --parareal-coarse-timestepping-order2="+str(self.parareal_coarse_timestepping_order2)
            retval += " --parareal-coarse-timestep-size="+str(self.parareal_coarse_timestep_size);
            retval += " --parareal-load-ref-csv-files="+str(self.parareal_load_ref_csv_files);
            retval += " --parareal-path-ref-csv-files="+str(self.parareal_path_ref_csv_files);
            retval += " --parareal-load-fine-csv-files="+str(self.parareal_load_fine_csv_files);
            retval += " --parareal-path-fine-csv-files="+str(self.parareal_path_fine_csv_files);
            retval += " --parareal-store-iterations="+str(self.parareal_store_iterations);

            ##if self.parareal_coarse_timestep_size > 0:
            ##    retval += " --parareal-coarse-timestep-size="+str(self.parareal_coarse_timestep_size);
            ##else:
            ##    retval += " --parareal-coarse-timestep-size="+str(self.parareal_max_simulation_time/self.parareal_coarse_slices);

        for key, param in self.user_defined_parameters.items():
            retval += ' '+param['option']+str(param['value'])

        return retval

    def cleanup_options(self):

        # Cleanup old format of reuse plans to new one
        if self.reuse_plans == -1:
            self.reuse_plans = "quick"
        elif self.reuse_plans == 0:
            self.reuse_plans = "save"
        elif self.reuse_plans == 1:
            self.reuse_plans = "load"
        elif self.reuse_plans == 2:
            self.reuse_plans = "require_load"

    def get_jobscript_plan_exec_prefix(self, compile, runtime):
        content = ""

        runtime.cleanup_options()

        plan_files = []
        if compile.plane_spectral_space == 'enable':
            plan_files.append('sweet_fftw')

        if compile.sphere_spectral_space == 'enable':
            plan_files.append('shtns_cfg')
            plan_files.append('shtns_cfg_fftw')

        if runtime.reuse_plans == "quick":
            # Quick plan generation mode, nothing to do
            pass

        elif "load" in runtime.reuse_plans:
            content += "\n"
            # Reuse plans if available
            # No error if plans don't exist
            for i in plan_files:
                if runtime.reuse_plans == "require_load":
                    content += "cp ../"+i+" ./ || exit 1\n"
                else:
                    content += "cp ../"+i+" ./ 2>/dev/null\n"

        elif runtime.reuse_plans == "save":
            # Create plans, don't load/store them
            pass

        else:
            raise Exception("Invalid reuse_plans value '"+str(runtime.reuse_plans)+"'")

        return content

    def get_jobscript_plan_exec_suffix(self, compile, runtime):
        content = ""

        runtime.cleanup_options()

        plan_files = []
        if compile.plane_spectral_space == 'enable':
            plan_files.append('sweet_fftw')

        if compile.sphere_spectral_space == 'enable':
            plan_files.append('shtns_cfg')
            plan_files.append('shtns_cfg_fftw')

        #
        # Reusing plans assumes them to be stored in the folder one level up in the hierarchy
        #
        if runtime.reuse_plans == "quick":
            # Quick plan generation mode, nothing to do
            pass

        elif "save" in runtime.reuse_plans:
            # Write back plans to main directory to reuse them
            content += "\n"
            for i in plan_files:
                content += "cp ./"+i+" ../ 2>/dev/null\n"
            content += "\n"
            pass

        elif "load" in runtime.reuse_plans:
            pass

        else:
            raise Exception("Invalid reuse_plans value '"+str(runtime.reuse_plans)+"'")

        return content

if __name__ == "__main__":

    p = JobRuntimeOptions()
    i = p.getRuntimeOptions()
    p.info(i)

    p.info("FIN")


text:
body {
	font-size: 18pt;
}
.editor {
	border: 1px solid black;
	height: 100px;
	width: 600px;
	overflow-x: hidden;
	overflow-y: scroll;
    /* editor must be position parent in order for scroll-to-cursor to work */
    position: relative;
}
.content  {
}
p {
	margin: 0px;
	/* note that paragraph must have height in order for empty lines to show */
	min-height: 18pt;
}
textarea {
	width: 400px;
	height: 100px;
}
#keyboardinput {
	position: absolute;
	background: none;
	border: none;
	width: 1px;
	height: 18pt;
	font-size: 16pt;
}

redpajama_set_name: RedPajamaGithub


text:
interface A { a: string; }
interface B extends A { b: string; }
interface C extends B { c: string; }
interface G<T, U extends B> {
    x: T;
    y: U;
}
var v1: G<A, C>;               // Ok
var v2: G<{ a: string }, C>;   // Ok, equivalent to G<A, C>
var v3: G<A, A>;               // Error, A not valid argument for U
var v4: G<G<A, B>, C>;         // Ok
var v5: G<any, any>;           // Error, any does not satisfy constraint B
var v6: G<any>;                // Error, wrong number of arguments
var v7: G;                     // Error, no type arguments

//// [generics1.js]
var v1; // Ok
var v2; // Ok, equivalent to G<A, C>
var v3; // Error, A not valid argument for U
var v4; // Ok
var v5; // Error, any does not satisfy constraint B
var v6; // Error, wrong number of arguments
var v7; // Error, no type arguments


text:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:ns1="urn:oasis:names:tc:xliff:document:1.2">
    <!-- From: file:/C:/Users/Jon/Dropbox/My%20Documents/android/Notey2_2/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.1.1/res/values-sl/values.xml -->
    <eat-comment/>
    <string msgid="4600421777120114993" name="abc_action_bar_home_description">"Krmarjenje domov"</string>
    <string msgid="1594238315039666878" name="abc_action_bar_up_description">"Krmarjenje navzgor"</string>
    <string msgid="3588849162933574182" name="abc_action_menu_overflow_description">"Več možnosti"</string>
    <string msgid="4076576682505996667" name="abc_action_mode_done">"Končano"</string>
    <string msgid="7468859129482906941" name="abc_activity_chooser_view_see_all">"Pokaži vse"</string>
    <string msgid="2031811694353399454" name="abc_activitychooserview_choose_application">"Izbira aplikacije"</string>
    <string msgid="3691816814315814921" name="abc_searchview_description_clear">"Izbris poizvedbe"</string>
    <string msgid="2550479030709304392" name="abc_searchview_description_query">"Iskalna poizvedba"</string>
    <string msgid="8264924765203268293" name="abc_searchview_description_search">"Iskanje"</string>
    <string msgid="8928215447528550784" name="abc_searchview_description_submit">"Pošiljanje poizvedbe"</string>
    <string msgid="893419373245838918" name="abc_searchview_description_voice">"Glasovno iskanje"</string>
    <string msgid="3421042268587513524" name="abc_shareactionprovider_share_with">"Deljenje z"</string>
    <string msgid="7165123711973476752" name="abc_shareactionprovider_share_with_application">"Deljenje z:"</string>
    <!-- From: file:/C:/Users/Jon/Dropbox/My%20Documents/android/Notey2_2/app/build/intermediates/exploded-aar/com.github.flavienlaurent.datetimepicker/library/0.0.2/res/values-sl/values.xml -->
    <eat-comment/>
    <string msgid="3968620852217927702" name="day_picker_description">"Mesečna mreža dni"</string>
    <string msgid="6908431551612331381" name="deleted_key">"<ns1:g id="KEY">%1$s</ns1:g> je izbrisana"</string>
    <string msgid="7007948707597430919" name="done_label">"Dokončano"</string>
    <string msgid="7586639618712934060" name="hour_picker_description">"Okrogli drsnik za ure"</string>
    <string msgid="2674929164900463786" name="item_is_selected">"Izbrano: <ns1:g id="ITEM">%1$s</ns1:g>"</string>
    <string msgid="6024811202872705251" name="minute_picker_description">"Okrogli drsnik za minute"</string>
    <string msgid="3973338219107019769" name="select_day">"Izberite mesec in dan"</string>
    <string msgid="7651068754188418859" name="select_hours">"Izberite ure"</string>
    <string msgid="8327182090226828481" name="select_minutes">"Izberite minute"</string>
    <string msgid="2603330600102539372" name="select_year">"Izberite leto"</string>
    <string msgid="6963340404644587098" name="year_picker_description">"Seznam let"</string>
</resources>


text:
cask :v1 => 'retas-studio' do
  version '6.6.0'
  sha256 '387d299ac77dad4a4116605e492e7c69614c463cde2ce5df439caaa55c9befb5'

  # clip-studio.com is the official download host per the vendor homepage
  url "http://www.clip-studio.com/clip_site/rental/rental_download/rsrental/dl?f=lib/retasstudio/data/#{version.gsub('.','')}/RS_#{version.gsub('.','')}_app.dmg"
  name 'RETAS STUDIO'
  homepage 'http://www.retasstudio.net/'
  license :commercial

  app 'RETAS STUDIO.app'
end


text:
import os

from networking_bagpipe.tests.common import json_fixtures

from neutron.common import utils
from neutron.tests.fullstack.resources import config as neutron_cfg

ROOTWRAP_DAEMON_CMD_DFLT = ("sudo /usr/local/bin/oslo-rootwrap-daemon "
                            "/etc/bagpipe-bgp/rootwrap.conf")

def bagpipe_agent_config_fixture_init_common(self, env_desc, host_desc,
                                             local_ip):
    agent_config = self.config.get('agent')
    if agent_config is None:
        self.config.update({'agent': {}})
        agent_config = self.config.get('agent')

    agent_exts = agent_config.get('extensions', '').split(',')

    if env_desc.bagpipe_ml2:
        agent_exts.append('bagpipe')
    if env_desc.bgpvpn:
        agent_exts.append('bagpipe_bgpvpn')

    agent_config.update({
        'extensions': ','.join(filter(None, agent_exts))
    })

    self.config.update({
        'bagpipe': {
            'bagpipe_bgp_ip': local_ip
        }
    })

class LinuxBridgeConfigFixture(neutron_cfg.LinuxBridgeConfigFixture):

    def __init__(self, env_desc, host_desc, temp_dir, local_ip,
                 physical_device_name):
        super(LinuxBridgeConfigFixture, self).__init__(env_desc, host_desc,
                                                       temp_dir, local_ip,
                                                       physical_device_name)
        bagpipe_agent_config_fixture_init_common(
            self, env_desc, host_desc, local_ip)

class OVSConfigFixture(neutron_cfg.OVSConfigFixture):

    def __init__(self, env_desc, host_desc, temp_dir, local_ip, mpls_bridge):
        super(OVSConfigFixture, self).__init__(env_desc, host_desc,
                                               temp_dir, local_ip)
        bagpipe_agent_config_fixture_init_common(
            self, env_desc, host_desc, local_ip)

        self.config.bagpipe.update({
            'mpls_bridge': mpls_bridge,
            'tun_to_mpls_peer_patch_port':
                utils.get_rand_device_name(prefix='to-mpls'),
            'mpls_to_tun_peer_patch_port':
                utils.get_rand_device_name(prefix='to-tun'),
            'mpls_to_int_peer_patch_port':
                utils.get_rand_device_name(prefix='mpls-to-int'),
            'int_to_mpls_peer_patch_port':
                utils.get_rand_device_name(prefix='int-to-mpls'),
        })

class JsonFixture(neutron_cfg.ConfigFixture):
    """A fixture that holds a JSON configuration."""
    def _setUp(self):
        cfg_fixture = json_fixtures.JsonFileFixture(
            self.base_filename, self.config, self.temp_dir)
        self.useFixture(cfg_fixture)
        self.filename = cfg_fixture.filename

class BagpipeBGPConfigFixture(neutron_cfg.ConfigFixture):

    def __init__(self, env_desc, host_desc, temp_dir, local_ip, bgp_peer,
                 bgp_port, mpls_bridge, mpls_interface):
        super(BagpipeBGPConfigFixture, self).__init__(
            env_desc, host_desc, temp_dir,
            base_filename='bgp.conf')

        self.config.update({
            'DEFAULT': {
                'debug': True,
            },
            'COMMON': {
                'root_helper_daemon': os.environ.get('OS_ROOTWRAP_DAEMON_CMD',
                                                     ROOTWRAP_DAEMON_CMD_DFLT)
            },
            'BGP': {
                'local_address': local_ip,
                'peers': bgp_peer,
                'my_as': '64512',
                'bgp_port': bgp_port,
            },
            'API': {
                'host': local_ip,
                'port': '8082'
            },
            'DATAPLANE_DRIVER_IPVPN': {
                'dataplane_driver': self.env_desc.ipvpn_driver,
                'ovs_bridge': mpls_bridge,
                'proxy_arp': 'False'
            },
            'DATAPLANE_DRIVER_EVPN': {
                'dataplane_driver': self.env_desc.evpn_driver
            }
        })

        if self.env_desc.ipvpn_driver != 'dummy':
            if self.env_desc.ipvpn_encap == 'vxlan':
                self.config['DATAPLANE_DRIVER_IPVPN'].update({
                    'vxlan_encap': 'True',
                    'mpls_interface': ''
                })
            if 'mpls-gre' in self.env_desc.ipvpn_encap:
                self.config['DATAPLANE_DRIVER_IPVPN'].update({
                    'mpls_interface': '*gre*',
                    'gre_tunnel': self._generate_gre_tunnel()
                })
            if self.env_desc.ipvpn_encap == 'mpls-gre-l3':
                self.config['DATAPLANE_DRIVER_IPVPN'].update({
                    'gre_tunnel_options': "packet_type=legacy_l3"
                })
            if self.env_desc.ipvpn_encap == 'bare-mpls':
                self.config['DATAPLANE_DRIVER_IPVPN'].update({
                    'mpls_interface': mpls_interface
                })

    def _generate_gre_tunnel(self):
        return utils.get_rand_device_name(prefix='mpls-gre')

class GoBGPConfigFixture(JsonFixture):

    def __init__(self, env_desc, host_desc, temp_dir,
                 bgp_peer, bgp_port, host_ips):
        super(GoBGPConfigFixture, self).__init__(
            env_desc, host_desc, temp_dir,
            base_filename='gobgp.conf')

        self.config.update({
            'global': {
                'config': {
                    'as': '64512',
                    'router-id': bgp_peer,
                    'port': bgp_port
                }
            }
        })

        neighbors = list()
        for host_ip in host_ips:
            neighbor = {
                'config': {
                    'neighbor-address': host_ip,
                    'peer-as': '64512'
                },
                'transport': {
                    'config': {
                        'passive-mode': 'true'
                    }
                },
                'route-reflector': {
                    'config': {
                        'route-reflector-client': 'true',
                        'route-reflector-cluster-id': '1.2.3.4'
                    }
                }
            }

            afi_safis = list()
            for afi_safi in ('rtc', 'l2vpn-evpn', 'l3vpn-ipv4-unicast',
                             'l3vpn-ipv4-flowspec'):
                afi_safis.append({
                    'config': {
                        'afi-safi-name': afi_safi
                    }
                })

            neighbor.update({'afi-safis': afi_safis})
            neighbors.append(neighbor)

        self.config.update({'neighbors': neighbors})


text:
module EmpleoyeesHelper
end


text:
<?php
/**
This Example shows how to get the list of existing Emails
**/
require_once 'inc/BMEAPI.class.php';
require_once 'inc/config.php'; //contains username & password

//This hack actually skips the login and lets you choose the API Key to expire.
$api = new BMEAPI($username, $password, $apiURL);
if ($api->errorCode){
  // an error occurred while logging in
  echo "code:".$api->errorCode."\n";
  echo "msg :".$api->errorMessage."\n";
  die();
}

$retval = $api->emailTemplateGetList(1,10);

if (!$retval){
  echo "Error!";
  echo "\n\tCode=".$api->errorCode;
  echo "\n\tMsg=".$api->errorMessage."\n";
} else {
foreach($retval as $rec)
{
  echo $rec['sequence'].")".$rec['template_name']."
";
  echo $rec['template_source']."
";
  echo $rec['preview_small'];
  }

}
?>


text:
@class JavaIoReader;
@class JavaIoWriter;
@class JavaNioCharBuffer;
@protocol ComGoogleCommonIoLineProcessor;
@protocol JavaLangAppendable;
@protocol JavaLangReadable;
@protocol JavaUtilList;

@interface ComGoogleCommonIoCharStreams : NSObject

#pragma mark Public

+ (JavaIoWriter *)asWriterWithJavaLangAppendable:(id<JavaLangAppendable>)target;

+ (jlong)copy__WithJavaLangReadable:(id<JavaLangReadable>)from
             withJavaLangAppendable:(id<JavaLangAppendable>)to OBJC_METHOD_FAMILY_NONE;

+ (jlong)exhaustWithJavaLangReadable:(id<JavaLangReadable>)readable;

+ (JavaIoWriter *)nullWriter;

+ (id<JavaUtilList>)readLinesWithJavaLangReadable:(id<JavaLangReadable>)r;

+ (id)readLinesWithJavaLangReadable:(id<JavaLangReadable>)readable
 withComGoogleCommonIoLineProcessor:(id<ComGoogleCommonIoLineProcessor>)processor;

+ (void)skipFullyWithJavaIoReader:(JavaIoReader *)reader
                         withLong:(jlong)n;

+ (NSString *)toStringWithJavaLangReadable:(id<JavaLangReadable>)r;

#pragma mark Package-Private

+ (JavaNioCharBuffer *)createBuffer;

@end

J2OBJC_EMPTY_STATIC_INIT(ComGoogleCommonIoCharStreams)

FOUNDATION_EXPORT JavaNioCharBuffer *ComGoogleCommonIoCharStreams_createBuffer();

FOUNDATION_EXPORT jlong ComGoogleCommonIoCharStreams_copy__WithJavaLangReadable_withJavaLangAppendable_(id<JavaLangReadable> from, id<JavaLangAppendable> to);

FOUNDATION_EXPORT NSString *ComGoogleCommonIoCharStreams_toStringWithJavaLangReadable_(id<JavaLangReadable> r);

FOUNDATION_EXPORT id<JavaUtilList> ComGoogleCommonIoCharStreams_readLinesWithJavaLangReadable_(id<JavaLangReadable> r);

FOUNDATION_EXPORT id ComGoogleCommonIoCharStreams_readLinesWithJavaLangReadable_withComGoogleCommonIoLineProcessor_(id<JavaLangReadable> readable, id<ComGoogleCommonIoLineProcessor> processor);

FOUNDATION_EXPORT jlong ComGoogleCommonIoCharStreams_exhaustWithJavaLangReadable_(id<JavaLangReadable> readable);

FOUNDATION_EXPORT void ComGoogleCommonIoCharStreams_skipFullyWithJavaIoReader_withLong_(JavaIoReader *reader, jlong n);

FOUNDATION_EXPORT JavaIoWriter *ComGoogleCommonIoCharStreams_nullWriter();

FOUNDATION_EXPORT JavaIoWriter *ComGoogleCommonIoCharStreams_asWriterWithJavaLangAppendable_(id<JavaLangAppendable> target);

J2OBJC_TYPE_LITERAL_HEADER(ComGoogleCommonIoCharStreams)

#endif

#if __has_feature(nullability)
#pragma clang diagnostic pop
#endif
#pragma pop_macro("INCLUDE_ALL_ComGoogleCommonIoCharStreams")


text:
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.Online.SharePoint.TenantManagement;
using Microsoft.SharePoint.Client;
using OfficeDevPnP.Core.Entities;
using OfficeDevPnP.Core.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.SharePoint.Client
{
    /// <summary>
    /// This manager class holds security related methods
    /// </summary>
    public static class SecurityExtensions
    {
        #region Site collection administrator management
        /// <summary>
        /// Get a list of site collection administrators
        /// </summary>
        /// <param name="web">Site to operate on</param>
        /// <returns>List of <see cref="OfficeDevPnP.Core.Entities.UserEntity"/> objects</returns>
        public static List<UserEntity> GetAdministrators(this Web web)
        {
            var users = web.SiteUsers;
            web.Context.Load(users);
            web.Context.ExecuteQuery();

            List<UserEntity> admins = new List<UserEntity>();

            foreach (var u in users)
            {
                if (u.IsSiteAdmin)
                {
                    admins.Add(new UserEntity()
                    {
                        Title = u.Title,
                        LoginName = u.LoginName,
                        Email = u.Email,
                    });
                }
            }

            return admins;
        }

        /// <summary>
        /// Add a site collection administrator to a site collection
        /// </summary>
        /// <param name="web">Site to operate on</param>
        /// <param name="adminLogins">Array of admins loginnames to add</param>
        /// <param name="addToOwnersGroup">Optionally the added admins can also be added to the Site owners group</param>
        public static void AddAdministrators(this Web web, List<UserEntity> adminLogins, bool addToOwnersGroup = false)
        {
            var users = web.SiteUsers;
            web.Context.Load(users);

            foreach (var admin in adminLogins)
            {
                UserCreationInformation newAdmin = new UserCreationInformation();

                newAdmin.LoginName = admin.LoginName;
                //User addedAdmin = users.Add(newAdmin);
                User addedAdmin = web.EnsureUser(newAdmin.LoginName);
                web.Context.Load(addedAdmin);
                web.Context.ExecuteQuery();

                //now that the user exists in the context, update to be an admin
                addedAdmin.IsSiteAdmin = true;
                addedAdmin.Update();

                if (addToOwnersGroup)
                {
                    web.AssociatedOwnerGroup.Users.AddUser(addedAdmin);
                    web.AssociatedOwnerGroup.Update();
                }
                web.Context.ExecuteQuery();
            }
        }

        /// <summary>
        /// Removes an administrators from the site collection
        /// </summary>
        /// <param name="web">Site to operate on</param>
        /// <param name="admin"><see cref="OfficeDevPnP.Core.Entities.UserEntity"/> that describes the admin to be removed</param>
        public static void RemoveAdministrator(this Web web, UserEntity admin)
        {
            var users = web.SiteUsers;
            web.Context.Load(users);
            web.Context.ExecuteQuery();

            var adminToRemove = users.Where(u => u.LoginName == admin.LoginName).FirstOrDefault();
            if (adminToRemove != null && adminToRemove.IsSiteAdmin)
            {
                adminToRemove.IsSiteAdmin = false;
                adminToRemove.Update();
                web.Context.ExecuteQuery();
            }

        }

        /// <summary>
        /// Adds additional administrators to a site collection using the Tenant administration csom. See AddAdministrators for a method
        /// that does not have a dependency on the Tenant administration csom.
        /// </summary>
        /// <param name="web">Site to be processed - can be root web or sub site</param>
        /// <param name="adminLogins">Array of logins for the additional admins</param>
        /// <param name="siteUrl">Url of the site to operate on</param>
        [Obsolete("Use Tenant.AddAdministrators() extension method")]
        public static void AddAdministratorsTenant(this Web web, String[] adminLogins, Uri siteUrl)
        {
            Tenant tenant = new Tenant(web.Context);

            tenant.AddAdministrators(adminLogins, siteUrl);
        }

        /// <summary>
        /// Add a site collection administrator to a site collection
        /// </summary>
        /// <param name="web">Site to operate on</param>
        /// <param name="adminLogins">Array of admins loginnames to add</param>
        /// <param name="siteUrl">Url of the site to operate on</param>
        /// <param name="addToOwnersGroup">Optionally the added admins can also be added to the Site owners group</param>
        [Obsolete("Use Tenant.AddAdministrator() extension method")]
        public static void AddAdministratorsTenant(this Web web, IEnumerable<UserEntity> adminLogins, Uri siteUrl, bool addToOwnersGroup = false)
        {
            Tenant tenant = new Tenant(web.Context);

            tenant.AddAdministrators(adminLogins, siteUrl, addToOwnersGroup);

        }

        #endregion

        #region Permissions management
        /// <summary>
        /// Add read access to the group "Everyone except external users".
        /// </summary>
        /// <param name="web">Site to be processed - can be root web or sub site</param>
        public static void AddReaderAccess(this Web web)
        {
            AddReaderAccessImplementation(web, BuiltInIdentity.EveryoneButExternalUsers);
        }

        /// <summary>
        /// Add read access to the group "Everyone except external users".
        /// </summary>
        /// <param name="web">Site to be processed - can be root web or sub site</param>
        /// <param name="user">Built in user to add to the visitors group</param>
        public static void AddReaderAccess(this Web web, BuiltInIdentity user)
        {
            AddReaderAccessImplementation(web, user);
        }

        private static void AddReaderAccessImplementation(Web web, BuiltInIdentity user)
        {
            switch (user)
            {
                case BuiltInIdentity.Everyone:
                    {
                        string userIdentity = "c:0(.s|true";
                        var spReader = web.EnsureUser(userIdentity);
                        web.Context.Load(spReader);
                        web.Context.ExecuteQuery();

                        web.AssociatedVisitorGroup.Users.AddUser(spReader);
                        web.AssociatedVisitorGroup.Update();
                        web.Context.ExecuteQuery();
                        break;
                    }
                case BuiltInIdentity.EveryoneButExternalUsers:
                    {
                        string userIdentity = string.Format("c:0-.f|rolemanager|spo-grid-all-users/{0}", web.GetAuthenticationRealm());
                        var spReader = web.EnsureUser(userIdentity);
                        web.Context.Load(spReader);
                        web.Context.ExecuteQuery();

                        web.AssociatedVisitorGroup.Users.AddUser(spReader);
                        web.AssociatedVisitorGroup.Update();
                        web.Context.ExecuteQuery();
                        break;
                    }
            }
        }

        #endregion

        #region External sharing management
        /// <summary>
        /// Get the external sharing settings for the provided site. Only works in Office 365 Multi-Tenant
        /// </summary>
        /// <param name="web">Tenant administration web</param>
        /// <param name="siteUrl">Site to get the sharing capabilities from</param>
        /// <returns>Sharing capabilities of the site collection</returns>
        public static string GetSharingCapabilitiesTenant(this Web web, Uri siteUrl)
        {
            if (siteUrl == null)
                throw new ArgumentNullException("siteUrl");

            Tenant tenant = new Tenant(web.Context);
            SiteProperties site = tenant.GetSitePropertiesByUrl(siteUrl.OriginalString, true);
            web.Context.Load(site);
            web.Context.ExecuteQuery();
            return site.SharingCapability.ToString();
        }

        /// <summary>
        /// Returns a list all external users in your tenant
        /// </summary>
        /// <param name="web">Tenant administration web</param>
        /// <returns>A list of <see cref="OfficeDevPnP.Core.Entities.ExternalUserEntity"/> objects</returns>
        public static List<ExternalUserEntity> GetExternalUsersTenant(this Web web)
        {
            Tenant tenantAdmin = new Tenant(web.Context);
            Office365Tenant tenant = new Office365Tenant(web.Context);

            List<ExternalUserEntity> externalUsers = new List<ExternalUserEntity>();
            int pageSize = 50;
            int position = 0;
            GetExternalUsersResults results = null;

            while (true)
            {
                results = tenant.GetExternalUsers(position, pageSize, string.Empty, SortOrder.Ascending);
                web.Context.Load(results, r => r.UserCollectionPosition, r => r.TotalUserCount, r => r.ExternalUserCollection);
                web.Context.ExecuteQuery();

                foreach (var externalUser in results.ExternalUserCollection)
                {
                    externalUsers.Add(new ExternalUserEntity()
                    {
                        DisplayName = externalUser.DisplayName,
                        AcceptedAs = externalUser.AcceptedAs,
                        InvitedAs = externalUser.InvitedAs,
                        InvitedBy = externalUser.InvitedBy,
                        UniqueId = externalUser.UniqueId,
                        WhenCreated = externalUser.WhenCreated
                    });
                }

                position = results.UserCollectionPosition;

                if (position == -1 || position == results.TotalUserCount)
                {
                    break;
                }
            }

            return externalUsers;
        }

        /// <summary>
        /// Returns a list all external users for a given site that have at least the viewpages permission
        /// </summary>
        /// <param name="web">Tenant administration web</param>
        /// <param name="siteUrl">Url of the site fetch the external users for</param>
        /// <returns>A list of <see cref="OfficeDevPnP.Core.Entities.ExternalUserEntity"/> objects</returns>
        public static List<ExternalUserEntity> GetExternalUsersForSiteTenant(this Web web, Uri siteUrl)
        {
            if (siteUrl == null)
                throw new ArgumentNullException("siteUrl");

            Tenant tenantAdmin = new Tenant(web.Context);
            Office365Tenant tenant = new Office365Tenant(web.Context);
            Site site = tenantAdmin.GetSiteByUrl(siteUrl.OriginalString);
            web = site.RootWeb;

            List<ExternalUserEntity> externalUsers = new List<ExternalUserEntity>();
            int pageSize = 50;
            int position = 0;
            GetExternalUsersResults results = null;

            while (true)
            {
                results = tenant.GetExternalUsersForSite(siteUrl.OriginalString, position, pageSize, string.Empty, SortOrder.Ascending);
                web.Context.Load(results, r => r.UserCollectionPosition, r => r.TotalUserCount, r => r.ExternalUserCollection);
                web.Context.ExecuteQuery();

                foreach (var externalUser in results.ExternalUserCollection)
                {

                    User user = web.SiteUsers.GetByEmail(externalUser.AcceptedAs);
                    web.Context.Load(user);
                    web.Context.ExecuteQuery();

                    var permission = web.GetUserEffectivePermissions(user.LoginName);
                    web.Context.ExecuteQuery();
                    var doesUserHavePermission = permission.Value.Has(PermissionKind.ViewPages);
                    if (doesUserHavePermission)
                    {
                        externalUsers.Add(new ExternalUserEntity()
                        {
                            DisplayName = externalUser.DisplayName,
                            AcceptedAs = externalUser.AcceptedAs,
                            InvitedAs = externalUser.InvitedAs,
                            InvitedBy = externalUser.InvitedBy,
                            UniqueId = externalUser.UniqueId,
                            WhenCreated = externalUser.WhenCreated
                        });
                    }

                }

                position = results.UserCollectionPosition;

                if (position == -1 || position == results.TotalUserCount)
                {
                    break;
                }
            }

            return externalUsers;
        }

        #endregion

        #region Group management
        /// <summary>
        /// Returns the integer ID for a given group name
        /// </summary>
        /// <param name="web">Site to be processed - can be root web or sub site</param>
        /// <param name="groupName">SharePoint group name</param>
        /// <returns>Integer group ID</returns>
        public static int GetGroupID(this Web web, string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            return web.GetGroupID(null, groupName);
        }

        /// <summary>
        /// Returns the integer ID for a given group name
        /// </summary>
        /// <param name="web">Site to be processed - can be root web or sub site</param>
        /// <param name="siteUrl">Site to operate on</param>
        /// <param name="groupName">SharePoint group name</param>
        /// <returns>Integer group ID</returns>
        public static int GetGroupID(this Web web, Uri siteUrl, string groupName)
        {
            if (siteUrl == null)
                throw new ArgumentNullException("siteUrl");

            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            int groupID = 0;

            var manageMessageGroup = web.SiteGroups.GetByName(groupName);
            web.Context.Load(manageMessageGroup);
            web.Context.ExecuteQuery();
            if (manageMessageGroup != null)
            {
                groupID = manageMessageGroup.Id;
            }

            return groupID;
        }

        /// <summary>
        /// Adds a group
        /// </summary>
        /// <param name="web">Site to add the group to</param>
        /// <param name="groupName">Name of the group</param>
        /// <param name="groupDescription">Description of the group</param>
        /// <param name="groupIsOwner">Sets the created group as group owner if true</param>
        /// <param name="updateAndExecuteQuery">Set to false to postpone the executequery call</param>
        /// <returns>The created group</returns>
        public static Group AddGroup(this Web web, string groupName, string groupDescription, bool groupIsOwner, bool updateAndExecuteQuery = true)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            GroupCreationInformation groupCreationInformation = new GroupCreationInformation();
            groupCreationInformation.Title = groupName;
            groupCreationInformation.Description = groupDescription;
            Group group = web.SiteGroups.Add(groupCreationInformation);
            if (groupIsOwner)
            {
                group.Owner = group;
            }

            group.OnlyAllowMembersViewMembership = false;
            group.Update();

            if (updateAndExecuteQuery)
            {
                web.Context.ExecuteQuery();
            }

            return group;
        }

        /// <summary>
        /// Associate the provided groups as default owners, members or visitors groups. If a group is null then the
        /// association is not done
        /// </summary>
        /// <param name="web">Site to operate on</param>
        /// <param name="owners">Owners group</param>
        /// <param name="members">Members group</param>
        /// <param name="visitors">Visitors group</param>
        public static void AssociateDefaultGroups(this Web web, Group owners, Group members, Group visitors)
        {
            if (owners != null)
            {
                web.AssociatedOwnerGroup = owners;
                web.AssociatedOwnerGroup.Update();
            }
            if (members != null)
            {
                web.AssociatedMemberGroup = members;
                web.AssociatedMemberGroup.Update();
            }
            if (visitors != null)
            {
                web.AssociatedVisitorGroup = visitors;
                web.AssociatedVisitorGroup.Update();
            }

            web.Update();
            web.Context.ExecuteQuery();
        }

        /// <summary>
        /// Adds a user to a group
        /// </summary>
        /// <param name="web">web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        /// <param name="userLoginName">Loginname of the user</param>
        public static void AddUserToGroup(this Web web, string groupName, string userLoginName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            //Ensure the user is known
            UserCreationInformation userToAdd = new UserCreationInformation();
            userToAdd.LoginName = userLoginName;
            User user = web.EnsureUser(userToAdd.LoginName);
            web.Context.Load(user);
            //web.Context.ExecuteQuery();

            //Add the user to the group
            var group = web.SiteGroups.GetByName(groupName);
            web.Context.Load(group);
            web.Context.ExecuteQuery();
            if (group != null)
            {
                web.AddUserToGroup(group, user);
            }
        }

        /// <summary>
        /// Adds a user to a group
        /// </summary>
        /// <param name="web">web to operate against</param>
        /// /// <param name="groupId">Id of the group</param>
        /// <param name="userLoginName">Login name of the user</param>
        public static void AddUserToGroup(this Web web, int groupId, string userLoginName)
        {
            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            Group group = web.SiteGroups.GetById(groupId);
            web.Context.Load(group);
            User user = web.EnsureUser(userLoginName);
            web.Context.ExecuteQuery();

            if (user != null && group != null)
            {
                AddUserToGroup(web, group, user);
            }
        }

        /// <summary>
        /// Adds a user to a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="group">Group object representing the group</param>
        /// <param name="user">User object representing the user</param>
        public static void AddUserToGroup(this Web web, Group group, User user)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            if (user == null)
                throw new ArgumentNullException("user");

            group.Users.AddUser(user);
            web.Context.ExecuteQuery();
        }

        /// <summary>
        /// Adds a user to a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="group">Group object representing the group</param>
        /// <param name="userLoginName">Login name of the user</param>
        public static void AddUserToGroup(this Web web, Group group, string userLoginName)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            User user = web.EnsureUser(userLoginName);
            web.Context.ExecuteQuery();
            if (user != null)
            {
                group.Users.AddUser(user);
                web.Context.ExecuteQuery();
            }
        }

        /// <summary>
        /// Add a permission level (e.g.Contribute, Reader,...) to a user
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="userLoginName">Loginname of the user</param>
        /// <param name="permissionLevel">Permission level to add</param>
        /// <param name="removeExistingPermissionLevels">Set to true to remove all other permission levels for that user</param>
        public static void AddPermissionLevelToUser(this Web web, string userLoginName, RoleType permissionLevel, bool removeExistingPermissionLevels = false)
        {
            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            User user = web.EnsureUser(userLoginName);
            web.Context.Load(user);
            web.Context.ExecuteQuery();
            web.AddPermissionLevelImplementation(user, permissionLevel, removeExistingPermissionLevels);
        }

        /// <summary>
        /// Add a permission level (e.g.Contribute, Reader,...) to a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        /// <param name="permissionLevel">Permission level to add</param>
        /// <param name="removeExistingPermissionLevels">Set to true to remove all other permission levels for that group</param>
        public static void AddPermissionLevelToGroup(this Web web, string groupName, RoleType permissionLevel, bool removeExistingPermissionLevels = false)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            var group = web.SiteGroups.GetByName(groupName);
            web.Context.Load(group);
            web.Context.ExecuteQuery();
            web.AddPermissionLevelImplementation(group, permissionLevel, removeExistingPermissionLevels);
        }

        private static void AddPermissionLevelImplementation(this Web web, Principal principal, RoleType permissionLevel, bool removeExistingPermissionLevels = false)
        {
            if (principal != null)
            {
                bool processed = false;

                RoleAssignmentCollection rac = web.RoleAssignments;
                web.Context.Load(rac);
                web.Context.ExecuteQuery();

                //Find the roles assigned to the principal
                foreach (RoleAssignment ra in rac)
                {
                    // correct role assignment found
                    if (ra.PrincipalId == principal.Id)
                    {
                        // load the role definitions for this role assignment
                        RoleDefinitionBindingCollection rdc = ra.RoleDefinitionBindings;
                        web.Context.Load(rdc);
                        web.Context.Load(web.RoleDefinitions);
                        web.Context.ExecuteQuery();

                        // Load the role definition to add (e.g. contribute)
                        RoleDefinition roleDefinition = web.RoleDefinitions.GetByType(permissionLevel);
                        if (removeExistingPermissionLevels)
                        {
                            // Remove current role definitions by removing all current role definitions
                            rdc.RemoveAll();
                        }
                        // Add the selected role definition
                        rdc.Add(roleDefinition);

                        //update
                        ra.ImportRoleDefinitionBindings(rdc);
                        ra.Update();
                        web.Context.ExecuteQuery();

                        // Leave the for each loop
                        processed = true;
                        break;
                    }
                }

                // For a principal without role definitions set we follow a different code path
                if (!processed)
                {
                    RoleDefinitionBindingCollection rdc = new RoleDefinitionBindingCollection(web.Context);
                    RoleDefinition roleDefinition = web.RoleDefinitions.GetByType(permissionLevel);
                    rdc.Add(roleDefinition);
                    web.RoleAssignments.Add(principal, rdc);
                    web.Context.ExecuteQuery();
                }
            }
        }

        /// <summary>
        /// Removes a permission level from a user
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="userLoginName">Loginname of user</param>
        /// <param name="permissionLevel">Permission level to remove. If null all permission levels are removed</param>
        /// <param name="removeAllPermissionLevels">Set to true to remove all permission level.</param>
        public static void RemovePermissionLevelFromUser(this Web web, string userLoginName, RoleType permissionLevel, bool removeAllPermissionLevels = false)
        {
            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            User user = web.EnsureUser(userLoginName);
            web.Context.Load(user);
            web.Context.ExecuteQuery();
            web.RemovePermissionLevelImplementation(user, permissionLevel, removeAllPermissionLevels);
        }

        /// <summary>
        /// Removes a permission level from a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">name of the group</param>
        /// <param name="permissionLevel">Permission level to remove. If null all permission levels are removed</param>
        /// <param name="removeAllPermissionLevels">Set to true to remove all permission level.</param>
        public static void RemovePermissionLevelFromGroup(this Web web, string groupName, RoleType permissionLevel, bool removeAllPermissionLevels = false)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            var group = web.SiteGroups.GetByName(groupName);
            web.Context.Load(group);
            web.Context.ExecuteQuery();
            web.RemovePermissionLevelImplementation(group, permissionLevel, removeAllPermissionLevels);
        }

        private static void RemovePermissionLevelImplementation(this Web web, Principal principal, RoleType permissionLevel, bool removeAllPermissionLevels = false)
        {
            if (principal != null)
            {
                RoleAssignmentCollection rac = web.RoleAssignments;
                web.Context.Load(rac);
                web.Context.ExecuteQuery();

                //Find the roles assigned to the principal
                foreach (RoleAssignment ra in rac)
                {
                    // correct role assignment found
                    if (ra.PrincipalId == principal.Id)
                    {
                        // load the role definitions for this role assignment
                        RoleDefinitionBindingCollection rdc = ra.RoleDefinitionBindings;
                        web.Context.Load(rdc);
                        web.Context.Load(web.RoleDefinitions);
                        web.Context.ExecuteQuery();

                        if (removeAllPermissionLevels)
                        {
                            // Remove current role definitions by removing all current role definitions
                            rdc.RemoveAll();
                        }
                        else
                        {
                            // Load the role definition to remove (e.g. contribute)
                            RoleDefinition roleDefinition = web.RoleDefinitions.GetByType(permissionLevel);
                            rdc.Remove(roleDefinition);
                        }

                        //update
                        ra.ImportRoleDefinitionBindings(rdc);
                        ra.Update();
                        web.Context.ExecuteQuery();

                        // Leave the for each loop
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Removes a user from a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        /// <param name="userLoginName">Loginname of the user</param>
        public static void RemoveUserFromGroup(this Web web, string groupName, string userLoginName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            var group = web.SiteGroups.GetByName(groupName);
            web.Context.Load(group);
            web.Context.ExecuteQuery();
            if (group != null)
            {
                User user = group.Users.GetByLoginName(userLoginName);
                if (user != null)
                {
                    web.RemoveUserFromGroup(group, user);
                }
            }
        }

        /// <summary>
        /// Removes a user from a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="group">Group object to operate against</param>
        /// <param name="user">User object that needs to be removed</param>
        public static void RemoveUserFromGroup(this Web web, Group group, User user)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            if (user == null)
                throw new ArgumentNullException("user");

            group.Users.Remove(user);
            group.Update();
            web.Context.ExecuteQuery();
        }

        /// <summary>
        /// Remove a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        public static void RemoveGroup(this Web web, string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            var group = web.SiteGroups.GetByName(groupName);
            web.Context.Load(group);
            web.Context.ExecuteQuery();
            if (group != null)
            {
                web.RemoveGroup(group);
            }
        }

        /// <summary>
        /// Remove a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="group">Group object to remove</param>
        public static void RemoveGroup(this Web web, Group group)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            GroupCollection groups = web.SiteGroups;
            groups.Remove(group);
            web.Context.ExecuteQuery();
        }

        /// <summary>
        /// Checks if a user is member of a group
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        /// <param name="userLoginName">Loginname of the user</param>
        /// <returns>True if the user is in the group, false otherwise</returns>
        public static bool IsUserInGroup(this Web web, string groupName, string userLoginName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            if (string.IsNullOrEmpty(userLoginName))
                throw new ArgumentNullException("userLoginName");

            bool result = false;

            var group = web.SiteGroups.GetByName(groupName);
            var users = group.Users;
            web.Context.Load(group);
            web.Context.Load(users);
            web.Context.ExecuteQuery();
            if (group != null)
            {
                result = users.Any(u => u.LoginName.Contains(userLoginName));
            }

            return result;
        }

        /// <summary>
        /// Checks if a group exists
        /// </summary>
        /// <param name="web">Web to operate against</param>
        /// <param name="groupName">Name of the group</param>
        /// <returns>True if the group exists, false otherwise</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2200:RethrowToPreserveStackDetails")]
        public static bool GroupExists(this Web web, string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
                throw new ArgumentNullException("groupName");

            bool result = false;

            try
            {
                var group = web.SiteGroups.GetByName(groupName);
                web.Context.Load(group);
                web.Context.ExecuteQuery();
                if (group != null)
                {
                    result = true;
                }
            }
            catch (Microsoft.SharePoint.Client.ServerException ex)
            {
                if (ex.Message.IndexOf("Group cannot be found", StringComparison.InvariantCultureIgnoreCase) > -1)
                {
                    //eat the exception
                }
                else
                {
                    //rethrow exception
                    throw;
                }
            }

            return result;
        }

        #endregion

        public static Guid GetAuthenticationRealm(this Web web)
        {
            Guid returnGuid = Guid.Empty;
            if (!web.IsPropertyAvailable("Url"))
            {
                web.Context.Load(web, w => w.Url);
                web.Context.ExecuteQuery();
            }
            WebRequest request = WebRequest.Create(new Uri(web.Url) + "/_vti_bin/client.svc");
            request.Headers.Add("Authorization: Bearer ");

            try
            {
                using (request.GetResponse())
                {
                }
            }
            catch (WebException e)
            {
                if (e.Response == null)
                {
                }

                string bearerResponseHeader = e.Response.Headers["WWW-Authenticate"];
                if (string.IsNullOrEmpty(bearerResponseHeader))
                {
                }

                const string bearer = "Bearer realm=\"";
                int bearerIndex = bearerResponseHeader.IndexOf(bearer, StringComparison.Ordinal);
                if (bearerIndex < 0)
                {
                }

                int realmIndex = bearerIndex + bearer.Length;

                if (bearerResponseHeader.Length >= realmIndex + 36)
                {
                    string targetRealm = bearerResponseHeader.Substring(realmIndex, 36);

                    Guid realmGuid;

                    if (Guid.TryParse(targetRealm, out realmGuid))
                    {
                        returnGuid = realmGuid;
                    }
                }
            }
            return returnGuid;
        }
    }
}


text:
package vreplication

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"

	"vitess.io/vitess/go/vt/log"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/vt/sqlparser"

	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/vt/vtgate/evalengine"
)

const (
	vreplicationLogTableName   = "_vt.vreplication_log"
	createVReplicationLogTable = `CREATE TABLE IF NOT EXISTS _vt.vreplication_log (
		id BIGINT(20) AUTO_INCREMENT,
		vrepl_id INT NOT NULL,
		type VARBINARY(256) NOT NULL,
		state VARBINARY(100) NOT NULL,
		created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
		updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
		message text NOT NULL,
		count BIGINT(20) NOT NULL DEFAULT 1,
		PRIMARY KEY (id))`
)

const (
	// Enum values for type column of _vt.vreplication_log

	// LogStreamCreate is used when a row in _vt.vreplication is inserted via VReplicationExec
	LogStreamCreate = "Stream Created"
	// LogStreamUpdate is used when a row in _vt.vreplication is updated via VReplicationExec
	LogStreamUpdate = "Stream Updated"
	// LogStreamDelete is used when a row in _vt.vreplication is deleted via VReplicationExec
	LogStreamDelete = "Stream Deleted"
	// LogMessage is used for generic log messages
	LogMessage = "Message"
	// LogCopyStart is used when the copy phase is started
	LogCopyStart = "Started Copy Phase"
	// LogCopyEnd is used when the copy phase is done
	LogCopyEnd = "Ended Copy Phase"
	// LogStateChange is used when the state of the stream changes
	LogStateChange = "State Changed"

	// TODO: LogError is not used atm. Currently irrecoverable errors, resumable errors and informational messages
	//  are all treated the same: the message column is updated and state left as Running.
	//  Every five seconds we reset the message and retry streaming so that we can automatically resume from a temporary
	//  loss of connectivity or a reparent. We need to detect if errors are not recoverable and set an Error status.
	//  Since this device (of overloading the message) is strewn across the code, and incorrectly flagging resumable
	//  errors can stall workflows, we have deferred implementing it.

	// LogError indicates that there is an error from which we cannot recover and the operator needs to intervene.
	LogError = "Error"
)

func getLastLog(dbClient *vdbClient, vreplID uint32) (id int64, typ, state, message string, err error) {
	var qr *sqltypes.Result
	query := fmt.Sprintf("select id, type, state, message from _vt.vreplication_log where vrepl_id = %d order by id desc limit 1", vreplID)
	if qr, err = withDDL.Exec(context.Background(), query, dbClient.ExecuteFetch, dbClient.ExecuteFetch); err != nil {
		return 0, "", "", "", err
	}
	if len(qr.Rows) != 1 {
		return 0, "", "", "", nil
	}
	row := qr.Rows[0]
	id, _ = evalengine.ToInt64(row[0])
	typ = row[1].ToString()
	state = row[2].ToString()
	message = row[3].ToString()
	return id, typ, state, message, nil
}

func insertLog(dbClient *vdbClient, typ string, vreplID uint32, state, message string) error {
	// getLastLog returns the last log for a stream. During insertion, if the type/state/message match we do not insert
	// a new log but increment the count. This prevents spamming of the log table in case the same message is logged continuously.
	id, _, lastLogState, lastLogMessage, err := getLastLog(dbClient, vreplID)
	if err != nil {
		return err
	}
	if typ == LogStateChange && state == lastLogState {
		// handles case where current state is Running, controller restarts after an error and initializes the state Running
		return nil
	}
	var query string
	if id > 0 && message == lastLogMessage {
		query = fmt.Sprintf("update _vt.vreplication_log set count = count + 1 where id = %d", id)
	} else {
		buf := sqlparser.NewTrackedBuffer(nil)
		buf.Myprintf("insert into _vt.vreplication_log(vrepl_id, type, state, message) values(%s, %s, %s, %s)",
			strconv.Itoa(int(vreplID)), encodeString(typ), encodeString(state), encodeString(message))
		query = buf.ParsedQuery().Query
	}
	if _, err = withDDL.Exec(context.Background(), query, dbClient.ExecuteFetch, dbClient.ExecuteFetch); err != nil {
		return fmt.Errorf("could not insert into log table: %v: %v", query, err)
	}
	return nil
}

// insertLogWithParams is called when a stream is created. The attributes of the stream are stored as a json string
func insertLogWithParams(dbClient *vdbClient, action string, vreplID uint32, params map[string]string) error {
	var message string
	if params != nil {
		obj, _ := json.Marshal(params)
		message = string(obj)
	}
	if err := insertLog(dbClient, action, vreplID, params["state"], message); err != nil {
		return err
	}
	return nil
}

// isUnrecoverableError returns true if vreplication cannot recover from the given error and should completely terminate
func isUnrecoverableError(err error) bool {
	if err == nil {
		return false
	}
	sqlErr, isSQLErr := err.(*mysql.SQLError)
	if !isSQLErr {
		return false
	}
	switch sqlErr.Num {
	case
		mysql.ERWarnDataOutOfRange,
		mysql.ERDataTooLong,
		mysql.ERWarnDataTruncated,
		mysql.ERTruncatedWrongValue,
		mysql.ERTruncatedWrongValueForField,
		mysql.ERIllegalValueForType,
		mysql.ErrWrongValueForType,
		mysql.ErrCantCreateGeometryObject,
		mysql.ErrGISDataWrongEndianess,
		mysql.ErrNotImplementedForCartesianSRS,
		mysql.ErrNotImplementedForProjectedSRS,
		mysql.ErrNonPositiveRadius,
		mysql.ERBadNullError,
		mysql.ERDupEntry,
		mysql.ERNoDefaultForField,
		mysql.ERInvalidJSONText,
		mysql.ERInvalidJSONTextInParams,
		mysql.ERInvalidJSONBinaryData,
		mysql.ERInvalidJSONCharset,
		mysql.ERInvalidCastToJSON,
		mysql.ERJSONValueTooBig,
		mysql.ERJSONDocumentTooDeep:
		log.Errorf("Got unrecoverable error: %v", sqlErr)
		return true
	}
	return false
}


text:
package br.com.trabalho.bd2.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import br.com.trabalho.bd2.jsf.util.DataConnect;
import br.com.trabalho.bd2.model.Aluguel;
import br.com.trabalho.bd2.model.AluguelRel;

public class AluguelDAO implements Serializable {

	private static final long serialVersionUID = 1L;

	public Aluguel buscarPorId(String id, Integer id2) throws Exception {
		Connection con = null;
		PreparedStatement ps = null;

		try {
			con = DataConnect.getConnection();

			ps = con.prepareStatement(
					"select veiculo, cliente, dataRetirada, dataDevolucao, tipoFranquia, nroCNH, dataVencimentoCNF "
							+ "from bd2.aluguel where veiculo like ? and cliente = ?");
			ps.setString(1, id);
			ps.setInt(2, id2);

			ResultSet rs = ps.executeQuery();

			Aluguel aluguel = new Aluguel();

			while (rs.next()) {

				aluguel.getVeiculo().setPlaca(rs.getString("veiculo"));
				aluguel.getCliente().setCodC(rs.getInt("cliente"));
				aluguel.setDataRetirada(rs.getDate("dataRetirada"));
				aluguel.setDataDevolucao(rs.getDate("dataDevolucao"));
				aluguel.setTipoFranquia(rs.getString("tipoFranquia"));
				aluguel.setNroCnh(rs.getString("nroCNH"));
				aluguel.setDataVencimentoCnf(rs.getDate("dataVencimentoCNF"));
			}
			rs.close();
			con.close();

			return aluguel;

		} catch (Exception e) {
			throw new Exception("Erro ao buscar Aluguel. " + e.getMessage());
		}

	}

	public void salvar(Aluguel aluguel) throws Exception {
		Connection con = null;
		PreparedStatement ps = null;

		try {
			con = DataConnect.getConnection();

			ps = con.prepareStatement(
					"insert into bd2.aluguel(veiculo, cliente, dataRetirada, dataDevolucao, tipoFranquia, nroCNH, dataVencimentoCNF) "
							+ "VALUES (?, ?, ?, ?, ?, ?, ?)");

			ps.setString(1, aluguel.getVeiculo().getPlaca());
			ps.setInt(2, aluguel.getCliente().getCodC());

			Date novaDataRet = new java.sql.Date(aluguel.getDataRetirada().getTime());
			ps.setDate(3, novaDataRet);

			Date novaDataDev = new java.sql.Date(aluguel.getDataDevolucao().getTime());
			ps.setDate(4, novaDataDev);

			ps.setString(5, aluguel.getTipoFranquia());
			ps.setString(6, aluguel.getNroCnh());

			Date novaDataVenc = new java.sql.Date(aluguel.getDataVencimentoCnf().getTime());
			ps.setDate(7, novaDataVenc);

			ps.executeUpdate();
			con.close();
		} catch (Exception e) {
			throw new Exception("Erro ao inserir aluguel. " + e.getMessage());
		}

	}

	public void editar(Aluguel aluguel) throws Exception {
		Connection con = null;
		PreparedStatement ps = null;

		try {
			con = DataConnect.getConnection();
			ps = con.prepareStatement("update bd2.aluguel set dataRetirada = ?, dataDevolucao = ?, tipoFranquia = ?, "
					+ "nroCNH = ?, dataVencimentoCNF = ? " + "where veiculo like ? and cliente = ?");

			Date novaDataRet = new java.sql.Date(aluguel.getDataRetirada().getTime());
			ps.setDate(1, novaDataRet);

			Date novaDataDev = new java.sql.Date(aluguel.getDataDevolucao().getTime());
			ps.setDate(2, novaDataDev);

			ps.setString(3, aluguel.getTipoFranquia());
			ps.setString(4, aluguel.getNroCnh());

			Date novaDataVenc = new java.sql.Date(aluguel.getDataVencimentoCnf().getTime());
			ps.setDate(5, novaDataVenc);

			ps.setString(6, aluguel.getVeiculo().getPlaca());
			ps.setInt(7, aluguel.getCliente().getCodC());

			ps.executeUpdate();

			con.close();
		} catch (Exception e) {
			throw new Exception("Erro ao atualizar Aluguel. " + e.getMessage());
		}

	}

	public void excluir(Aluguel aluguel) throws Exception {
		Connection con = null;
		PreparedStatement ps = null;

		try {
			con = DataConnect.getConnection();
			ps = con.prepareStatement("delete from bd2.aluguel where veiculo like ? and cliente = ?");
			ps.setString(1, aluguel.getVeiculo().getPlaca());
			ps.setInt(2, aluguel.getCliente().getCodC());

			ps.executeUpdate();
			con.close();
		} catch (Exception e) {
			throw new Exception("Erro ao excluir Aluguel. " + e.getMessage());
		}

	}

	public List<Aluguel> buscarTodos() throws Exception {
		Connection con = null;

		try {
			con = DataConnect.getConnection();
			PreparedStatement pstmt = con.prepareStatement(
					"select a.veiculo, a.cliente, c.nome, a.dataRetirada, a.dataDevolucao, a.tipoFranquia, a.nroCNH, a.dataVencimentoCNF "
							+ "from bd2.aluguel a, bd2.cliente c " + "where a.cliente = c.codc "
							+ " order by a.dataRetirada");

			ResultSet rs = pstmt.executeQuery();

			List<Aluguel> aluguels = new ArrayList<Aluguel>();

			while (rs.next()) {
				Aluguel aluguel = new Aluguel();

				aluguel.getVeiculo().setPlaca(rs.getString("veiculo"));
				aluguel.getCliente().setCodC(rs.getInt("cliente"));
				aluguel.getCliente().setNome(rs.getString("nome"));
				aluguel.setDataRetirada(rs.getDate("dataRetirada"));
				aluguel.setDataDevolucao(rs.getDate("dataDevolucao"));
				aluguel.setTipoFranquia(rs.getString("tipoFranquia"));
				aluguel.setNroCnh(rs.getString("nroCNH"));
				aluguel.setDataVencimentoCnf(rs.getDate("dataVencimentoCNF"));

				aluguels.add(aluguel);
			}

			con.close();

			return aluguels;

		} catch (Exception e) {
			throw new Exception("Erro ao buscar lista de aluguéis. " + e.getMessage());
		}

	}

	public List<AluguelRel> relatorioMes(int mes, int ano) throws Exception {
		Connection con = null;

		try {
			con = DataConnect.getConnection();
			PreparedStatement pstmt = con.prepareStatement("select case extract(month from dataretirada) "
					+ "when 1 then 'Janeiro' "
					+ "when 2 then 'Fevereiro' "
					+ "when 3 then 'Março' "
					+ "when 4 then 'Abril' "
					+ "when 5 then 'Maio' "
					+ "when 6 then 'Junho' "
					+ "when 7 then 'Julho' "
					+ "when 8 then 'Agosto' "
					+ "when 9 then 'Setembro' "
					+ "when 10 then 'Outubro' "
					+ "when 11 then 'Novembro' "
					+ "when 12 then 'Dezembro' "
					+ "end AS mes, COUNT(extract('month' from dataretirada)) AS qtd "
					+ "from bd2.aluguel "
					+ "where extract('month' from dataretirada) in (?,?,?) and extract('year' from dataretirada)  = ? "
					+ "group by mes "
					+ "limit 3");
			pstmt.setInt(1, mes-1);
			pstmt.setInt(2, mes);
			pstmt.setInt(3, mes+1);
			pstmt.setInt(4, ano);

			ResultSet rs = pstmt.executeQuery();

			List<AluguelRel> aluguels = new ArrayList<AluguelRel>();

			while (rs.next()) {
				AluguelRel aluguel = new AluguelRel();

				aluguel.setMes(rs.getString("mes"));
				aluguel.setQtdMes(rs.getInt("qtd"));

				aluguels.add(aluguel);
			}

			con.close();

			return aluguels;

		} catch (Exception e) {
			throw new Exception("Erro ao buscar relatorio de aluguéis do mes: " + e.getMessage());
		}

	}

	public List<AluguelRel> relatorioVeiculo(int mes, int ano) throws Exception {
		Connection con = null;

		try {
			con = DataConnect.getConnection();
			PreparedStatement pstmt = con
					.prepareStatement("select veiculo, COUNT(extract('month' from dataretirada)) AS qtd "
							+ "from bd2.aluguel "
							+ "where extract('month' from dataretirada) = ? and extract('year' from dataretirada) = ? "
							+ "group by veiculo "
							+ "limit 3");

			pstmt.setInt(1, mes);
			pstmt.setInt(2, ano);

			ResultSet rs = pstmt.executeQuery();

			List<AluguelRel> aluguels = new ArrayList<AluguelRel>();

			while (rs.next()) {
				AluguelRel aluguel = new AluguelRel();

				aluguel.setVeiculo(rs.getString("veiculo"));
				aluguel.setQtdMesVeiculo(rs.getInt("qtd"));

				aluguels.add(aluguel);
			}

			con.close();

			return aluguels;

		} catch (Exception e) {
			throw new Exception("Erro ao buscar relatorio de aluguéis do Ano: " + e.getMessage());
		}

	}

	public List<AluguelRel> relatorioMediaAnual(int ano) throws Exception {
		Connection con = null;

		try {
			con = DataConnect.getConnection();
			PreparedStatement pstmt = con.prepareStatement("select extract('year' from dataretirada) as ano, "
					+ "COUNT(extract('year' from dataretirada)) AS qtd "
					+ "from bd2.aluguel "
					+ "where extract('year' from dataretirada) in (?,?,?) "
					+ "group by ano "
					+ "limit 3");
			pstmt.setInt(1, ano-1);
			pstmt.setInt(2, ano);
			pstmt.setInt(3, ano+1);

			ResultSet rs = pstmt.executeQuery();

			List<AluguelRel> aluguels = new ArrayList<AluguelRel>();

			while (rs.next()) {
				AluguelRel aluguel = new AluguelRel();

				aluguel.setAno(rs.getInt("ano"));
				aluguel.setQtdAno(rs.getInt("qtd"));

				aluguels.add(aluguel);
			}

			con.close();

			return aluguels;

		} catch (Exception e) {
			throw new Exception("Erro ao buscar relatorio de aluguéis do mes: " + e.getMessage());
		}

	}

}