MySql (MariaDB) crashes on small RAM VPS, what to do

Recently I encountered one weird problem, my MariaDB database started to crash from time to time on one of my small RAM (512mb) virtual private servers. After some short googling I found out what what is potential problem with MariaDB on small RAM machines and how to fix it.

First of all, if you have this kind of problem, check MariaDB logs

tail -n 100 /var/log/mariadb/mariadb.log

you may find something like this:

160608 12:08:05 InnoDB: Completed initialization of buffer pool
160608 12:08:05 InnoDB: Fatal error: cannot allocate memory for the buffer pool
160608 12:08:05 [ERROR] Plugin 'InnoDB' init function returned error.
160608 12:08:05 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
160608 12:08:05 [ERROR] mysqld: Out of memory (Needed 128917504 bytes)

After some research I figured out that mysql require a lot resources for performance schema, and disabling it will help on small memory machines. source

sudo vim /etc/my.cnf

add

performance_schema = off

to section

[mysqld]

To ensure that database server will restart on crash, on OS with Systemd like CentOS 7 you need to do following

Open following file for edit

sudo vim /etc/systemd/system/mariadb.service

and add following lines

.include /lib/systemd/system/mariadb.service

[Service]
Restart=always
RestartSec=3

Then you need to restart reload Systemd configuration

sudo systemctl daemon-reload

and restart MariaDB service

systemctl restart mariadb

To ensure that Systemd restarts service you can do following:

ps -ef|grep maria

You will see something like this

mysql    26647 26368  0 Jun12 ?        00:06:22 /usr/libexec/mysqld ....

Try to kill the process using

kill 26647

Wait 3 seconds and check if MariaDB started again

ps -ef|grep maria

Using WordPress Media Library in Widgets options

So how to add WordPress media uploader popup to our custom widget?

That’s not so hard, hovewer there are a few caveats.

Let’s start from our simple widget class, I’d recommend to get example from https://codex.wordpress.org/Widgets_API#Example. Then we will need to add our new option, it will be called “image”. Just copy and paste fields in the “form” function, to render widget form and “update” function, to save this option.

I would recommend to catch php output buffer, it may be helpful if you will want to cache widget output. So our “widget” function will look like this:


	public function widget( $args, $instance ) {
		// Our variables from the widget settings
		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Default title', 'text_domain' ) : $instance['title'] );
		$image = ! empty( $instance['image'] ) ? $instance['image'] : '';

		ob_start();
		echo $args['before_widget'];
		if ( ! empty( $instance['title'] ) ) {
			echo $args['before_title'] . $title . $args['after_title'];
		}
		?>

		<?php if($image): ?>
			<img src="<?php echo esc_url($image); ?>" alt="">
		<?php endif; ?>

		<?php
		echo $args['after_widget'];
		ob_end_flush();
	}

Our “form” function will be:


	public function form( $instance ) {
		$title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'New title', 'text_domain' );
		$image = ! empty( $instance['image'] ) ? $instance['image'] : '';
		?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
		</p>
		<p>
			<label for="<?php echo $this->get_field_id( 'image' ); ?>"><?php _e( 'Image:' ); ?></label>
			<input class="widefat" id="<?php echo $this->get_field_id( 'image' ); ?>" name="<?php echo $this->get_field_name( 'image' ); ?>" type="text" value="<?php echo esc_url( $image ); ?>" />
			<button class="upload_image_button button button-primary">Upload Image</button>
		</p>
		<?php
	}

And our update function:


	public function update( $new_instance, $old_instance ) {
		$instance = array();
		$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
		$instance['image'] = ( ! empty( $new_instance['image'] ) ) ? $new_instance['image'] : '';

		return $instance;
	}

As you can see, I’ve added a button underneath image input field with class “.upload_image_button”, but it will not work for now and to make it work we will need to add our custom admin javascript.

First what we need is to create our javascript file and put it into our theme, let’s create a file, called our_admin.js in assets/js under our theme folder.

Next we will need to register and enqueue our script to make it load in the admin panel, so lets add few lines to our widget class constructor function:


	function __construct() {

		// Add Widget scripts
		add_action('admin_enqueue_scripts', array($this, 'scripts'));

		parent::__construct(
			'our_widget', // Base ID
			__( 'Our Widget Title', 'text_domain' ), // Name
			array( 'description' => __( 'Our Widget with media files', 'text_domain' ), ) // Args
		);
	}

And we will need then “scripts” function in our widget class:


	public function scripts()
	{
		wp_enqueue_script( 'media-upload' );
		wp_enqueue_media();
		wp_enqueue_script('our_admin', get_template_directory_uri() . '/assets/js/our_admin.js', array('jquery'));
	}

As you can notice, we also added wp_enqueue_script( ‘media-upload’ ); and wp_enqueue_media(); to enqueue media library popup scripts.

And finally, here is our script, that will call WordPress media library popup and put selected image into the input field:


jQuery(document).ready(function ($) {

	$(document).on("click", ".upload_image_button", function (e) {
		e.preventDefault();
		var $button = $(this);


		// Create the media frame.
		var file_frame = wp.media.frames.file_frame = wp.media({
			title: 'Select or upload image',
			library: { // remove these to show all
				type: 'image' // specific mime
			},
			button: {
				text: 'Select'
			},
			multiple: false  // Set to true to allow multiple files to be selected
		});

		// When an image is selected, run a callback.
		file_frame.on('select', function () {
			// We set multiple to false so only get one image from the uploader

			var attachment = file_frame.state().get('selection').first().toJSON();

			$button.siblings('input').val(attachment.url);

		});

		// Finally, open the modal
		file_frame.open();
	});
});

So thats it, now, when you click on “Upload Image” button, WordPress media library popup will open and you will be able easily upload or select already uploaded image for widget options form.

CSS vertical centering techniques

So what is the best way to center blocks vertically using CSS?

There are bunch of techniques, lets try each of them!

1. “line-height” property

HTML code:

<div class="outer-block">
   <div class="inner-block">
      <p>Some text</p>
      <p>Some more text</p>
   </div>
</div>

CSS code:

.outer-block { 
   height: 200px; 
   line-height: 200px; 
   text-align: center; 
}
.inner-block { 
   display: inline-block; 
   line-height: 1.5;
   text-align: left; 
   vertical-align: middle; 
}

Here is the result:

Some text

Some more text

 
So it works just good, quite simple, but it doesn’t support variable height.

2. “position: absolute” and negative margins

HTML code:

<div class="outer-block">
   <div class="inner-block">
      <div class="inner-text">
         <p>Some text</p>
         <p>Some more text</p>
      </div>
   </div>
</div>

CSS code:

.outer-block {
   position: relative;
   height: 200px; 
   text-align: center; 
}
.inner-block { 
   position: absolute;
   top: 50%;
   left: 0;
   margin-top: -30px;
   width: 100%;
   height: 60px;
   text-align: center; 
}

Here is the result:

Some text

Some more text

 
Another good approach, not so simple as line-height though. However it needs inner block to by fixed height so negative margin-top can be set. And it needs additional block to center text block horizontally.

3. Table cell method

HTML code:


<div class="some-container">
   <div class="outer-block">
      <div class="inner-block">
         <div class="inner-text">
            <p>Some text</p>
            <p>Some more text</p>
         </div>
      </div>
   </div>
</div>

CSS code:

.some-container {
   height: 200px;
}
.outer-block { 
   width: 100%; 
   height: 100%;
   display: table;
}
.inner-block { 
   width: 100%; 
   height: 100%;
   display: table-cell;
   vertical-align: middle;
   text-align: center;
}

Here is the result:

Some text

Some more text

 
This is a great approach if you have container with variable height, this method will certainly work in this case! Downside of this method is that it will not work in older versions of IE. Also it needs additional block to center text block horizontally. Another pros is that it will expand if inner-block content height will became bigger than outer block.

If you need it to work in older IE versions you can use explicit table tags instead of div blocks:

HTML code:

<div class="some-container">
   <table class="outer-block">
      <tr>
         <td class="inner-block">
            <div class="inner-text">
               <p>Some text</p>
               <p>Some more text</p>
            </div>
         </td>
      </tr>
   </table>
</div>

CSS code:

.some-container {
   height: 200px;
}
.outer-block { 
   width: 100%; 
   height: 100%; 
}
.inner-block {
   vertical-align: middle;
   text-align: center;
}

Here is the result:

Some text

Some more text

Summary

To summary this methods, I would say the best way for responsive designs is table cell method. Despite it doesn’t support old versions of IE this is virtually the only method to fully center block vertically for responsive design without JavaScript snippets. Two other ways always require outer or inner block to have fixes height value.

Image slider on pure CSS3

Recently I’ve read one article about slider without any JS code and I decided to extend this idea and here is what i’ve got.

First, we will need basic HTML layout for slider:

<ul class="css-slider">
    <li><img src="slides/1.jpg" alt=""></li>
    <li><img src="slides/2.jpg" alt=""></li>
    <li><img src="slides/3.jpg" alt=""></li>
    <li><img src="slides/4.jpg" alt=""></li>
    <li><img src="slides/5.jpg" alt=""></li>
</ul>

Quite simple and straightforward.

Next step, lets style our sliders container, and add some other styles:

.css-slider{
   position: relative; /* All slides will have absolute position */
   width: 100%; /* Make it responsive */
   padding: 0; margin: 0; 
   padding-bottom: 75%; /* Height will be 75% from width */
   list-style-type: none; 
   overflow: hidden; /* In case images will have wrong aspect ratio */
}

.css-slider li img{width: 100%;} /* And make images responsive as well */

The whole idea of this slider is to use keyframe animation for changing slides.

To make this work we will create keyframes that have to do following: show slide, keep it some time, hide slide, wait while all other slides will show.

This is how it looks:

@-webkit-keyframes css-slider {
  10%{opacity: 1;} /* This is where slide becomes visible, duration 10 % of 20 sec */
  20%{opacity: 1;} /* Still visible, little more then middle point (100 % / 5 slides) */
  40%{opacity: 0;} /* Now its hidden, when next slide is fully visible */
}

Some explanations about percents and durations.

Our slide has 5 slides, delay between slides is 4s, this means that whole animation have to take 5 slides * 4s = 20s.

Then we can calculate how long will take 1%, 20s / 100% = 0.2s, or 10% will take 2s and this is our transition duration from opacity: 0 to opacity: 1.

Next step to get middle point: 4s / 0.2s = 20 % or just 100% / 5 slides = 20%, this is when next slide will start it’s transition, and current slide have to stay visible until that.

At last we have to hide our slide when next slide is fully shown, it’s the middle of next slide, 20% + 20% = 40%.

Then we add styles and keyframes to slides:

.css-slider li{
   position: absolute; top:0; right: 0; bottom: 0; left: 0; /* Make it fill whole slider container */
   opacity: 0; /* Hide it */
   -webkit-animation: css-slider 20s infinite; /* Use keyframe animation from above */
}

And at last we set different delays for each slide to make it work. Each slide must have slides delay durations multiplied by slide position – 1, or just each next slide’s delay equals previous plus delay duration.

.css-slider li:nth-child(1){-webkit-animation-delay: 0s;}
.css-slider li:nth-child(2){-webkit-animation-delay: 4s;}
.css-slider li:nth-child(3){-webkit-animation-delay: 8s;}
.css-slider li:nth-child(4){-webkit-animation-delay: 12s;}
.css-slider li:nth-child(5){-webkit-animation-delay: 16s;}

And here is result:

 

Ok it looks good, but it has a big con, if you want to change slides count, delays or transitions duration you have to recalculate keyframes positions change duration and add or remove delays for each slide. That’s why it’s not very usable in real production projects.

Until some generator will be used, I will add SASS generator here next time.

And here is promised SASS mixin, I’ve improved it a little by adding z-indexes:


@mixin css-slider($count, $duration, $delay) {

	$delay: $duration + $delay;
	$total_duration: $delay * $count;
	$start_visible: $duration / $total_duration * 100;
	$mid_visible: 100 / $count;
	$end_visible: $mid_visible * 2;

	@-webkit-keyframes css-slider {
		#{$start_visible + '%'}{opacity: 1; z-index: 100;}
		#{$mid_visible + '%'}{opacity: 1; z-index: 2}
		#{$end_visible + '%'}{opacity: 0; z-index: 1;}
	}

	@keyframes css-slider {
		#{$start_visible + '%'}{opacity: 1; z-index: 100;}
		#{$mid_visible + '%'}{opacity: 1; z-index: 2}
		#{$end_visible + '%'}{opacity: 0; z-index: 1;}
	}


	position: relative;
	width: 100%; padding: 0 0 75% 0; margin: 0;
	list-style-type: none; overflow: hidden;

	li{
		position: absolute; top:0; right: 0; bottom: 0; left: 0; z-index: 1;
		opacity: 0;
		-webkit-animation: css-slider #{$delay * $count}s infinite;
		animation: css-slider #{$delay * $count}s infinite;
	}

	li img{width: 100%;}

	@for $i from 0 through $count - 1 {
		li:nth-child(#{$i+1}){-webkit-animation-delay: #{$i * $delay}s; animation-delay: #{$i * $delay}s;}
	}

}

/* Apply our minix for .css-slider */
.css-slider{
	@include css-slider(5, 2, 2);
}