<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Записки искателей</title>
	
	<link>http://voituk.kiev.ua</link>
	<description>while ( isAlive() ) {doCode(); doFun();}</description>
	<lastBuildDate>Tue, 01 Dec 2009 23:01:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/researchers" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Разминка для хвоста</title>
		<link>http://voituk.kiev.ua/2009/12/02/razminka-dlya-xvosta/</link>
		<comments>http://voituk.kiev.ua/2009/12/02/razminka-dlya-xvosta/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 23:01:49 +0000</pubDate>
		<dc:creator>juriy</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Задачки]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1303</guid>
		<description><![CDATA[Ух, как же давно ничего не писал в блог! Отчасти тому виной твиттер. Я обязательно напишу отдельную заметку об этом &#8220;убийце блогов&#8221;. А сейчас, хочу представить вам пару свеженьких Java задачек.

1. Не изменяя код первго метода сделать так, чтобы программа компилировалась и печатала &#8220;This is right&#8221;. У этой задачки, как минимум, 3 решения. Комментировать код [...]]]></description>
			<content:encoded><![CDATA[<p>Ух, как же давно ничего не писал в блог! Отчасти тому виной твиттер. Я обязательно напишу отдельную заметку об этом &#8220;убийце блогов&#8221;. А сейчас, хочу представить вам пару свеженьких Java задачек.<br />
<span id="more-1303"></span><br />
1. Не изменяя код первго метода сделать так, чтобы программа компилировалась и печатала &#8220;This is right&#8221;. У этой задачки, как минимум, 3 решения. Комментировать код первого метода тоже нельзя.</p>
<pre>
public class A {

	public static void main(String[] args) {
		System.out.println("This is wrong");
	}

	public static void main(String[] args) {
		System.out.println("This is right");
	}
}
</pre>
<p>2. Написать стандартный Hello World на Java. При этом нельзя использовать ни одной точки с запятой. Закодированные UTF символы тоже использовать нельзя.</p>
<p>Ответы я опубликую через сутки, а пока что жду комментариев.</p>
<p>P.S. За мной уже закрепилась слава человека, обожающего абсолютно бесполезные, с практической точки зрения, задачи. Я пришел к выводу, что для таких &#8220;упражнений&#8221; слово &#8220;задача&#8221; совсем не подходит. Все привыкли, что &#8220;задачи&#8221; это упражнения, которые развивают какие-то практические навыки. К примеру &#8220;реализовать генератор случайных чисел на Java&#8221; это задачка. А для того, что публикую я, лучше подходит слово &#8220;загадка&#8221;. Так что вот вам свежая &#8220;без окон без дверей полна горница людей&#8221;.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=oMx25BhA3lg:Fczfm7BlZXU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=oMx25BhA3lg:Fczfm7BlZXU:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=oMx25BhA3lg:Fczfm7BlZXU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=oMx25BhA3lg:Fczfm7BlZXU:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/12/02/razminka-dlya-xvosta/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Mac OS X: Usefull tips &amp; hints 2</title>
		<link>http://voituk.kiev.ua/2009/11/18/mac-os-x-usefull-tips-hints-2/</link>
		<comments>http://voituk.kiev.ua/2009/11/18/mac-os-x-usefull-tips-hints-2/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 15:53:35 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1087</guid>
		<description><![CDATA[Следующая порция советов по обустройству вашей комфортной жизни в Mac OS X.
Первая часть доступна тут.
1. Указать место для складирования ScreenShots (по умолчанию &#8211; ~/Desktop )
(те что создаются системным shortcut-ом Command+Shift+4 &#38; Command+Shift+3)
vadim@Voituk:~&#62;defaults write com.apple.screencapture location ~/Pictures/Screenshots
vadim@Voituk:~&#62;killall SystemUIServer
Аналогично меняется и формат скриншотов (злые языки говорят что поддерживается png, jpg, tiff, pdf):
vadim@Voituk:~&#62;defaults write com.apple.screencapture type jpg
vadim@Voituk:~&#62;killall SystemUIServer
2. [...]]]></description>
			<content:encoded><![CDATA[<p>Следующая порция советов по обустройству вашей комфортной жизни в Mac OS X.<br />
Первая часть <a href="http://voituk.kiev.ua/2009/06/11/usefull-max-os-hints/">доступна тут</a>.</p>
<p>1. Указать место для складирования ScreenShots (по умолчанию &#8211; ~/Desktop )<br />
(те что создаются системным shortcut-ом Command+Shift+4 &amp; Command+Shift+3)</p>
<p>vadim@Voituk:~&gt;defaults write com.apple.screencapture location ~/Pictures/Screenshots<br />
vadim@Voituk:~&gt;killall SystemUIServer</p>
<p>Аналогично меняется и формат скриншотов (злые языки говорят что поддерживается png, jpg, tiff, pdf):</p>
<p>vadim@Voituk:~&gt;defaults write com.apple.screencapture type jpg<br />
vadim@Voituk:~&gt;killall SystemUIServer</p>
<p>2. Иногда при перезагрузке (часто если подключен внешний монитор) пропадает Bluetooth.<br />
Решение сродни &#8220;давайте выйдем и зайдем &#8211; авось заведется&#8221; &#8211; выключаю Мак, отключаю все внешние устройства, вынимаю батарею.<br />
Жду минуты 2-3 и включаю.<br />
Время &#8220;простоя&#8221; использую для протирания ноутбука влажной салфеткой :)</p>
<p>3. Поначалу очень непривычно было, что в column mode Finder, в списках, директории и файлы идут вперемешку.<br />
Частично эту проблему можно решить, нажав Command+J и выбрав &#8220;Arrange by Kind&#8221;.<br />
В результате  директории будут в списке рядом, но не всегда в начале списка.<br />
Окончательно можно решить проблему &#8220;грязным хаком&#8221;: сделать чтоб при сортировке по типу, директория (тип Folder) шла самой первой.</p>
<p>Для этого открываем файл<strong><br />
/System/Library/CoreServices/Finder.app/Contents/Resources/English.lproj/InfoPlist.strings</strong><br />
и сразу за комментарием /* General kind strings */ меняем строку<br />
<strong>&#8220;Folder&#8221; = &#8220;Folder&#8221;;</strong><br />
на<br />
<strong>&#8220;Folder&#8221; = &#8221; Folder&#8221;; </strong><br />
(с пробелом перед буквой &#8220;F&#8221;)</p>
<p>После редактирования перезапускаем &#8220;Finder&#8221;. /me счастлив</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=kpWaNN4VtF8:t1QUI567SH4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=kpWaNN4VtF8:t1QUI567SH4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=kpWaNN4VtF8:t1QUI567SH4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=kpWaNN4VtF8:t1QUI567SH4:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/11/18/mac-os-x-usefull-tips-hints-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Useful TODO-list service – GMail Hack</title>
		<link>http://voituk.kiev.ua/2009/11/06/useful-todo-list-service-gmail-hack/</link>
		<comments>http://voituk.kiev.ua/2009/11/06/useful-todo-list-service-gmail-hack/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 09:44:29 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Разное]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1113</guid>
		<description><![CDATA[Самые неотложные дела очень удобно записывать на желтых стикерах, и клеить на монитор.
Единственный минус &#8211; через 3-4 месяца они отваливаются.
(с) Народная шутка
За последние несколько лет я перепробовал порядка 2х десятков разных сервисов для формирования TODO-листов. Больше 2х дней ни одим не пользовался, и во всех случах по одной причине &#8211; о списке забывается, если он [...]]]></description>
			<content:encoded><![CDATA[<blockquote style="text-align:right; font-style:italic; "><p>Самые неотложные дела очень удобно записывать на желтых стикерах, и клеить на монитор.<br />
Единственный минус &#8211; через 3-4 месяца они отваливаются.<br />
(с) Народная шутка</p></blockquote>
<p>За последние несколько лет я перепробовал порядка 2х десятков разных сервисов для формирования TODO-листов. Больше 2х дней ни одим не пользовался, и во всех случах по одной причине &#8211; о списке забывается, если он не находится постояно перед глазами.<br />
Для примера, сегодня я нашел записи полу-годичной (!!!) давности в своем GMail Tasklist :) Тут уже и шутка из эпиграфа статьи превращается совсем не в шутку.<br />
И это GMail, которым я пользуюсь ежедневно! А что уже говорить про всякие &#8220;оторванные&#8221; от рабочего процесса TadaList, TooDoo и им подобные?</p>
<p>В результате уже больше года я вынашиваю идею <span style="text-decoration: line-through;">взять Юру, пива и за вечер налабать</span> реализовать нормальный удобный web-ориентированный TODO-лист, который можно будет спокойно загрузить в sidebar браузера и он всегда будет на виду.</p>
<p>Уже даже начал писать functional overview и requirements specification, и наверное даже через недельку-две уже и приступил бы к реализации, если бы не сегодняшний утренний твит <a href="http://twitter.com/maxua/status/5457812503">Макса Ищенко</a>:</p>
<p><img class="alignnone size-full wp-image-1173" title="sreenshot" src="http://voituk.kiev.ua/wp-content/uploads/2009/11/Picture-56.png" alt="sreenshot" width="572" height="207" /></p>
<p>После чего необходимость реализовывать что-то свое попросту отпало &#8211; все уже <span style="text-decoration: line-through;">украдено</span> изобрели до нас:<br />
Открываем Firefox, создаем новый Bookmark на видимой панели закладок, называем его TODO (ну или по желанию), как URL указываем &#8220;http://mail.google.com/tasks/ig?pli=1&#8243;, ставим галочку &#8220;Load this bookmark in the sidebar&#8221; &#8211; и вуаля!</p>
<p>Получится что-то вроде:</p>
<p><img class="alignnone size-full wp-image-1193" title="Gmail Tasks Screenshot" src="http://voituk.kiev.ua/wp-content/uploads/2009/11/Picture-57.png" alt="Gmail Tasks Screenshot" width="574" height="345" /></p>
<p>Т.е. на 100% то &#8211; что я искал.</p>
<p>Единственное, что смущает &#8211; не придумал как перенести этот sidebar  на правую сторону браузера, но думаю это решаемо.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=hzbRK6vAAlQ:qNv4giJWTTA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=hzbRK6vAAlQ:qNv4giJWTTA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=hzbRK6vAAlQ:qNv4giJWTTA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=hzbRK6vAAlQ:qNv4giJWTTA:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/11/06/useful-todo-list-service-gmail-hack/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>MySQL: Slave could not parse relay log event entry</title>
		<link>http://voituk.kiev.ua/2009/09/17/mysql-slave-could-not-parse-relay-log-event-entry/</link>
		<comments>http://voituk.kiev.ua/2009/09/17/mysql-slave-could-not-parse-relay-log-event-entry/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 08:09:31 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1079</guid>
		<description><![CDATA[При использованиии MySQL Master-Slave (или же Master-Master) репликации бывает ситуация что по разным причинам версия слейва ниже чем версия мастера.
Если при этом используется опция binlog_format=MIXED, в результате возможна ситуация когда мастер запишет в свой binlog запись вида:
BINLOG 'XMawShMEAAAARwAAAEp5UwUAAGkAAAAAAAAACHNhblahblahblah'
Которую слейв не сможет выполнить, ибо он ее попросту &#8220;еще не умеет&#8221;.
Первой ласточкой того, что это произошло станет [...]]]></description>
			<content:encoded><![CDATA[<p>При использованиии MySQL Master-Slave (или же Master-Master) репликации бывает ситуация что по разным причинам версия слейва ниже чем версия мастера.<br />
Если при этом используется опция <em>binlog_format=MIXED</em>, в результате возможна ситуация когда мастер запишет в свой binlog запись вида:<br />
<code>BINLOG 'XMawShMEAAAARwAAAEp5UwUAAGkAAAAAAAAACHNhblahblahblah'</code><br />
Которую слейв не сможет выполнить, ибо он ее попросту &#8220;еще не умеет&#8221;.</p>
<p>Первой ласточкой того, что это произошло станет сообщение &#8220;SLAVE DOWN&#8221; от мониторинговой системы и запись в MySQL-логе слейва сродни этой:</p>
<p><code>090917 14:55:51 [ERROR] Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 71, event_type: 19<br />
090917 14:55:51 [ERROR] Error reading relay log event: slave SQL thread aborted because of I/O error<br />
090917 14:55:51 [ERROR] Slave: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' o<br />
n the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL<br />
code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave. Error_code: 0<br />
090917 14:55:51 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'bin-us1.000022' position 17007149<br />
</code></p>
<p>Попытки пропустить неугодные записи старым добрым методом:<br />
<code>slave stop;<br />
set global sql_slave_skip_counter=1;<br />
slave start;</code><br />
в данном случае не помогают.</p>
<p>Как вариант решения предлагаю:</p>
<ol>
<li>Останавливаем slave: <em>&#8220;SLAVE STOP;&#8221;</em></li>
<li>&#8220;Выуживаем&#8221; из текста ошибки имя бинлога и позицию, на которой произошла ошибка.<br />
В данном случае это <em>bin-us1.000022</em> и позиция <em>17007149</em></li>
<li>На мастере выполняем запрос <em>&#8220;FLUSH LOGS;&#8221;</em></li>
<li>Делаем дамп бинлога начиная с найденной позиции:<br />
<code>mysqlbinlog --start-position=17007149 bin-us1.000022  &gt;  bin-us1-from17007149.sql</code></li>
<li>Загружаем полученный дамп на слейве с ключем &#8220;&#8211;force&#8221;<br />
<code>mysql --force -uuser -ppassword database &lt;  bin-us1-from17007149.sql</code></li>
<li>Выполняем на слейве &#8220;FLUSH LOGS;&#8221;</li>
<li>В data-директории находим relay-log с максимальным номером и размером около 100 байт (в моем случае это mysqld-relay-bin.000037)</li>
<li>В той же директории в файле relay-log.info<br />
первую строку заменяем на имя только что найденного relay-log-а, во вторую вписываем 0, в третью &#8211; следующий после &#8220;испорченного&#8221; бинлог, в четвертую &#8211; 0<br />
Получится что-то вроде:<br />
<code>/var/lib/mysql/mysqld-relay-bin.000037<br />
0<br />
bin-us1.000023<br />
0</code></li>
<li>Дальше на слейве выполняем:<br />
<code>CHANGE MASTER TO MASTER_LOG_FILE='bin-us1.000023', MASTER_LOG_POS=0;<br />
SLAVE START;</code></li>
<li>Ну и потом чтоб удостоверится что все &#8220;завелось&#8221;<br />
<code>SHOW SLAVE STATUS\G</code></li>
</ol>
<p>Должно работать.<br />
Подозреваю что пункты 4 и 5 можно обьеденить в один, более простой и элегантный.<br />
Но как это сделать &#8211; не гуглил.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=C-Ls-K90sJI:4FaFA7ZM8QU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=C-Ls-K90sJI:4FaFA7ZM8QU:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=C-Ls-K90sJI:4FaFA7ZM8QU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=C-Ls-K90sJI:4FaFA7ZM8QU:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/09/17/mysql-slave-could-not-parse-relay-log-event-entry/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Code WTF: JavaScript HTML entities</title>
		<link>http://voituk.kiev.ua/2009/07/02/javascript-html-entities/</link>
		<comments>http://voituk.kiev.ua/2009/07/02/javascript-html-entities/#comments</comments>
		<pubDate>Thu, 02 Jul 2009 08:49:43 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Юмор]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1075</guid>
		<description><![CDATA[Извините за &#8220;неформат&#8221; для данного блога, но не смог удержаться.
Вот так вот мой &#8220;юннат&#8221; реализует замену html-entities на JavaScript:

function properHtmlFromText(text){
	while (text.search(/\&#60;/) != -1)
		text = text.replace(/\&#60;/, '&#38;lt;');
	while (text.search(/\&#38;/) != -1)
		text = text.replace(/\&#38;/, '&#38;amp;');
	while (text.search(/\r/) != -1)
		text = text.replace(/\r/, '');
	while (text.search(/\n/) != -1)
		text = text.replace(/\n/, '&#60;br /&#62;');
	return text;
}

Как увидел &#8211; плакал&#8230;
Наверное все-таки будем возобновлять ежедневные code-review&#8230;
P.S. В [...]]]></description>
			<content:encoded><![CDATA[<p>Извините за &#8220;неформат&#8221; для данного блога, но не смог удержаться.<br />
Вот так вот мой &#8220;юннат&#8221; реализует замену html-entities на JavaScript:</p>
<pre><code>
function properHtmlFromText(text){
	while (text.search(/\&lt;/) != -1)
		text = text.replace(/\&lt;/, '&amp;lt;');
	while (text.search(/\&amp;/) != -1)
		text = text.replace(/\&amp;/, '&amp;amp;');
	while (text.search(/\r/) != -1)
		text = text.replace(/\r/, '');
	while (text.search(/\n/) != -1)
		text = text.replace(/\n/, '&lt;br /&gt;');
	return text;
}
</code></pre>
<p>Как увидел &#8211; плакал&#8230;<br />
Наверное все-таки будем возобновлять ежедневные code-review&#8230;</p>
<p>P.S. В комментариях предлагаю поделиться &#8220;правильным&#8221; решением :)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=_pA8E5afOX8:lp_tbKl1XsM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=_pA8E5afOX8:lp_tbKl1XsM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=_pA8E5afOX8:lp_tbKl1XsM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=_pA8E5afOX8:lp_tbKl1XsM:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/07/02/javascript-html-entities/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>MySQL: Single row lock implementation</title>
		<link>http://voituk.kiev.ua/2009/06/24/mysql-single-row-lock-implementation/</link>
		<comments>http://voituk.kiev.ua/2009/06/24/mysql-single-row-lock-implementation/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 14:01:35 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1066</guid>
		<description><![CDATA[При разработке приложений с использованием баз данных, часто возникает сценарий &#8220;insert if not exists&#8221;: 
if ( &#60;row exists in table&#62; )
   then &#60;insert new record into table&#62;
Из-за того, что данный блок псевдо-кода не выполяняется атомано, может возникнуть ситуация, когда между проверкой &#60;row exists in table&#62; и выполнением действия &#60;insert new record&#62; паралельный поток [...]]]></description>
			<content:encoded><![CDATA[<p>При разработке приложений с использованием баз данных, часто возникает сценарий &#8220;insert if not exists&#8221;: </p>
<pre><code class="sql">if ( &lt;row exists in table&gt; )
   then &lt;insert new record into table&gt;</code></pre>
<p>Из-за того, что данный блок псевдо-кода не выполяняется атомано, может возникнуть ситуация, когда между проверкой <em>&lt;row exists in table&gt;</em> и выполнением действия <em>&lt;insert new record&gt;</em> паралельный поток (клиент)  выполнит добавление новой записи и в итоге в БД окажется 2 одинаковых записи (или произойдет ошибка &#8220;duplicate key&#8221;).</p>
<p>Такой, не самый приятный case, в книгах по паралельному программированию называют race condition и обходят путем создания синхронизирующих блокировок , использованием &#8220;выпрямителей&#8221; и тд.<br />
<span id="more-1066"></span><br />
С точки зрения MySQL надо бы переписать приведенный псевдокод в таком виде:</p>
<pre><code class="sql">mysql_query('LOCK TABLE `table` WRITE')

if ( &lt;row exists in table&gt; )
   then &lt;insert new record into table&gt;

mysql_query('UNLOCK TABLES') </code></pre>
<p>В таком случае таблица будет заблокирована для записи и мы будем уверены что во время выполнения нашего кода, никто, кроме текущего потока, ничего в таблицу не &#8220;дозапишет&#8221; и race condition не возникнет.</p>
<p>Способ вроде простой, и если мне не изменяет память, даже рекомендовался в какой-то книге по разработке web-приложений.<br />
Самый же существенный его минус &#8211; он блокирует <strong>ВСЮ</strong> таблицу и все запросы на запись в эту таблицу будут ждать окончания выполнения блока кода и вызова &#8220;UNLOCK TABLES&#8221;.<br />
Это, в условиях интенсивной записи в таблицу, может создать весьма критичный bottleneck в производительности всей системы.</p>
<p>Очень неплохо бы в таком случае выполнять блокировку на уровне не всей таблицы, а только определенной строки. Немного покопавшись в мануале MySQL, отыскал несколько встроенных функций, которые помогают это реализовать:</p>
<dl>
<dt><a href="http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock" rel="nofollow">GET_LOCK(str, timeout)</a></dt>
<dd>Создает глобальный мютекс с именем <em>str</em> и временем жизни <em>timeout</em>. При попытке другого потока &#8220;занять&#8221; уже созданный мютекс, он будет ожидать пока он не освободится вызовом RELEASE_LOCK() или не пройдет <em>timeout</em> секунд</dd>
<dt><a href="http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock" rel="nofollow">RELEASE_LOCK(str)</a></dt>
<dd>Освобождает глобальный мютекс с именем <em>str</em></dd>
</dl>
<p>Кроме того есть еще 2 вспомогательные фунцкции для проверки создан ли уже мютекс, и если создан, то каким ProcessID: <a href="http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_is-free-lock" rel="nofollow">IS_FREE_LOCK()</a> и <a href="http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_is-used-lock" rel="nofollow">IS_USED_LOCK()</a></p>
<p>С учетом вышесказанного описанный выше псевдокод, с использованием row-based блокировки будет выглядеть таким образом:</p>
<pre><code class="sql">mysql_query('DO GET_LOCK("my-prefix.my-row-id", 60)')

if ( &lt;row exists in table&gt; )
   then &lt;insert new record into table&gt;

mysql_query('DO RELEASE_LOCK("my-prefix.my-row-id")') </code></pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=8DeG588nH_Q:x8_ksTjA4eQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=8DeG588nH_Q:x8_ksTjA4eQ:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=8DeG588nH_Q:x8_ksTjA4eQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=8DeG588nH_Q:x8_ksTjA4eQ:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/06/24/mysql-single-row-lock-implementation/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Using iptables to prevent SSH brute force</title>
		<link>http://voituk.kiev.ua/2009/06/21/using-iptables-to-prevent-ssh-brute-force/</link>
		<comments>http://voituk.kiev.ua/2009/06/21/using-iptables-to-prevent-ssh-brute-force/#comments</comments>
		<pubDate>Sun, 21 Jun 2009 14:34:37 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1061</guid>
		<description><![CDATA[Себе на заметку, дабы потом опять не гуглить.
Эти 2 простых iptables-правила спасают сервер от brute force перебора пароля от SSH:
iptables -I INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsourceiptables -I INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -m [...]]]></description>
			<content:encoded><![CDATA[<p><em>Себе на заметку, дабы потом опять не гуглить.</em><br />
Эти 2 простых iptables-правила спасают сервер от brute force перебора пароля от SSH:<br />
<code>iptables -I INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource</code><code>iptables -I INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 5 --name DEFAULT --rsource -j DROP</code><br />
В результате те, кто делает более 5-ти попыток SSH-подключений за последние 3 минуты &#8211; блокируются на 3 минуты.<br />
Для того, чтоб эти правила запускались при старте системы делаем dump rules-файла:<br />
<code>iptables-save  > /etc/sysconfig/iptables</code></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=kXTtSqKdqGg:ijJ0Jjh1x2M:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=kXTtSqKdqGg:ijJ0Jjh1x2M:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=kXTtSqKdqGg:ijJ0Jjh1x2M:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=kXTtSqKdqGg:ijJ0Jjh1x2M:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/06/21/using-iptables-to-prevent-ssh-brute-force/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mac OS X: Few Usefull Max OS hints</title>
		<link>http://voituk.kiev.ua/2009/06/11/usefull-max-os-hints/</link>
		<comments>http://voituk.kiev.ua/2009/06/11/usefull-max-os-hints/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 07:54:44 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1016</guid>
		<description><![CDATA[За почти 2 месяца иcпользования MacBook и Mac OS X скопилось несколько полезных советиков, коими и спешу поделиться. Все tips&#38;tricks были честно найдены в глобальной сети и опробованы на себе.

Nokia E50 Не хочет коннектиться по Bluetooth (точнее коннектится, но быстро отваливается).
Удаляем файл, в котором хранятся bluetooth-профайлы устройств
rm /Library/Preferences/com.apple.Bluetooth.plist и перенастраиваем коннект с мобильным гаджетом заново.
Лично [...]]]></description>
			<content:encoded><![CDATA[<p><em>За почти 2 месяца иcпользования MacBook и Mac OS X скопилось несколько полезных советиков, коими и спешу поделиться. Все tips&amp;tricks были честно найдены в глобальной сети и опробованы на себе.</em></p>
<ol>
<li><strong>Nokia E50 Не хочет коннектиться по Bluetooth (точнее коннектится, но быстро отваливается).</strong><br />
Удаляем файл, в котором хранятся bluetooth-профайлы устройств<br />
<code>rm /Library/Preferences/com.apple.Bluetooth.plist</code> и перенастраиваем коннект с мобильным гаджетом заново.<br />
Лично у меня 2-ждый такой трюк провернуть не удалось &#8211; проблема первый раз решилаcь, а повторно -уже  не помогло.<br />
<br class="clear" /></li>
<li>Когда-то я <a href="http://voituk.kiev.ua/2009/04/03/macbook-my-first-impressions/">жаловался</a> на <strong>отсутствие hotkey-я для максимизации/оптимизации текущего окна</strong>. Так вот действие для &#8220;зеленой кнопки максимизации&#8221;  в большинстве Mac OS приложениях называется &#8220;Zoom&#8221; и находится в меню View.<br />
Чтоб назначить горячую клавишу на это действие открываем:<br />
<code>System Preferences → Keyboard and Mouse → Keyboard Shortcuts</code> Далее в разделе <code>"Application Keyboard Shortcuts → All Applications"</code> добавляем такую запись:<br />
<img class="alignnone size-full wp-image-1048" title="Zoom" src="http://voituk.kiev.ua/wp-content/uploads/2009/06/picture-54.png" alt="Zoom" width="410" height="207" /><em><br />
(в данном случае, я выбрал shortcut Command+Shift+M )</em></p>
<p><em></em></li>
<li>В Finder<strong> в &#8220;Column mode&#8221; по дефолту колонки очень узкие, а после изменения и закрытия окна &#8211; их размеры не сохраняются</strong>.<br />
Решается просто: Если изменить ширину колонки при этом зажав &#8220;Option&#8221; &#8211; новый размер станет стандартным.<br />
Как сделать ширину auto-adjustable &#8211;  я  так и не нашел.</li>
<li>Для того чтоб <strong>в заголовке окон Finder показывать полный путь к открытой директории</strong> (например &#8220;/home/vadim/Desktop&#8221; вместо простого &#8220;Desktop&#8221;), нужно в терминале выполнить:<br />
<code>defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES; killall Finder</code><br />
ну и соответственно заменить YES на NO чтоб показывать &#8220;короткий&#8221; путь.<br />
Выглядит это так:<br />
<img src="http://voituk.kiev.ua/wp-content/uploads/fullpathtitles-1.jpg" alt="" /></li>
<li><strong> При коннекте по SSH на Ubuntu/Debian линуксы, в оболочке screen не работает BackSpace</strong> (и мапинг Ctrl+H не спасает)<br />
Решение: Необходимо перед запуском установить переменную окружения TERM=screeen.<br />
В приниципе можно в .bashrc назначить alias:<br />
<code>alias screen='TERM=screen screen'</p>
<p></code></li>
<li>И еще <strong>несколько мелких советов</strong>, которые я почерпнул с твиттера <a href="http://twitter.com/okertanov">@okertanov<br />
</a></p>
<ol>
<li>Shift-Minimize button &#8211; нууууу очень медленнноооое сворачивание окна в док</li>
<li>Смена дефолтного браузера на Маке происходит через <code>Safari → Preferences → Default Web Browser</code></li>
<li> Alt-Shift-K = &#8220;символ яблочко&#8221; </li>
</ol>
</li>
<li>Чтоб <strong>сменить unix-имя пользователя Max OS X</strong> (ну и заодно имя home-директории) нужно
<ol>
<li>Включить <a href="http://support.apple.com/kb/HT1528">root-пользователя</a>, залогиниться под ним</li>
<li>Переименовать home-директорию (For ex:  $ mv /Users/admin /Users/vadim)</li>
<li>Через System Preferences → Accounts создать пользователя с желаемым именем, совпадающим с новым именем home-директории</li>
<li>Согласиться с предупреждением, что существующая home-директория будет назначена новому пользователю.</li>
<li>Залогиниться под новым пользователем, проверить все ли ок, удалить старого пользователя</li>
<li>Отключить root-а</li>
</ol>
</li>
</ol>
<p>В прицнипе пока все, по мере возможности буду пополнять список.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=JnlaYkJ9bxU:SpYs72dmztM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=JnlaYkJ9bxU:SpYs72dmztM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=JnlaYkJ9bxU:SpYs72dmztM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=JnlaYkJ9bxU:SpYs72dmztM:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/06/11/usefull-max-os-hints/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Mac OS X: Home/End/etc in Terminal.app</title>
		<link>http://voituk.kiev.ua/2009/05/07/mac-os-x-home-end-terminal/</link>
		<comments>http://voituk.kiev.ua/2009/05/07/mac-os-x-home-end-terminal/#comments</comments>
		<pubDate>Thu, 07 May 2009 20:59:52 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1028</guid>
		<description><![CDATA[Мне кажется, Mac OS X  &#8211; является популярной ОС среди разработчиков, в большинстве своем потому, что она внутри все-таки *nix.  Хоть и &#8220;облагороженный&#8221; до уровня домохозяйки, &#8211; но все-таки *nix.
А какой же *nix без терминала, aka-консоли?
Вот и у меня, знакомство с новым MacBook-ом началось именно с терминала. Но к сожалению очень быстро обнаружилось, что в [...]]]></description>
			<content:encoded><![CDATA[<p>Мне кажется, Mac OS X  &#8211; является популярной ОС среди разработчиков, в большинстве своем потому, что она внутри все-таки *nix.  Хоть и &#8220;облагороженный&#8221; до уровня домохозяйки, &#8211; но все-таки *nix.<br />
А какой же *nix без терминала, aka-консоли?<br />
Вот и у меня, знакомство с новым MacBook-ом началось именно с терминала. Но к сожалению очень быстро обнаружилось, что в bash, запущенном внутри Terminal.app  не работают клавиши Home / End (в случае MacBook &#8211; это Fn+LeftArrow / Fn+RightArrow),  а также Ctrl+LeftArrow / Ctrl+RightArrow для перемещения на слово вперед/назад.</p>
<p>Google выдает огромное количество советов, как это исправляется, но 99% тех, что я перепробовал решали проблему в локальном терминале, и не решали при удаленном подключении из него.</p>
<p>Единственное рабочее решение, которое заработало и локально и remote-но, выглядит так:</p>
<ol>
<li>Открываем Preferences приложения  Terminall.app</li>
<li>Переходим на закладку Settings =&gt; Keyboard</li>
<li>Для Home/End добавляем в список такие записи:<br />
<img class="size-full wp-image-1029 alignleft" title="picture-20" src="http://voituk.kiev.ua/wp-content/uploads/2009/05/picture-20.png" alt="picture-20" width="307" height="226" /> <img class="size-full wp-image-1034 alignright" title="picture-27" src="http://voituk.kiev.ua/wp-content/uploads/2009/05/picture-27.png" alt="picture-27" width="321" height="233" /><br class="floatnone" style="float:none;clear:both" /><br />
(для вставки <strong>\033</strong> нужно в поле ввода нажать <strong>Esc</strong>)</li>
<li>Аналогичным образом, для реализации переещения вправо-влево с шагом в одно слово используются комбинации <strong>\033b</strong> и <strong>\033f</strong></li>
</ol>
<p>Вуаля! &#8211; и жизнь вне Windows постепенно налаживается :)</p>
<p><em>Этой заметкой я постараюсь открыть в блоге серию небольших Tips&amp;Tricks, основанных на собственном опыте и относящихся к использованию MacBook и Mac OS X.</em></p>
<p><em>Следующей заметкой хочу рассказать, как в Java Swing приложение добавить немного Mac OS X специфичного внешнего вида и поведения. Это кому-то вообще интересно? Или банальщина и не стоит даже напрягаться?<br />
</em></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=lnFYRR_K-wk:P0lLL8_owRE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=lnFYRR_K-wk:P0lLL8_owRE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=lnFYRR_K-wk:P0lLL8_owRE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=lnFYRR_K-wk:P0lLL8_owRE:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/05/07/mac-os-x-home-end-terminal/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Apache Tomcat init.d script</title>
		<link>http://voituk.kiev.ua/2009/04/28/apache-tomcat-initd-script/</link>
		<comments>http://voituk.kiev.ua/2009/04/28/apache-tomcat-initd-script/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 13:33:18 +0000</pubDate>
		<dc:creator>Vadim Voituk</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://voituk.kiev.ua/?p=1022</guid>
		<description><![CDATA[Продолжая серию заметок &#8220;Из программиста в руководители админы&#8221; :), опять же себе на заметку пишем init-скрипт для корректного запуска/перезапуска Apache Tomcat под Linux.
Создаем файл /etc/init.d/tomcat такого содержания:
# Tomcat auto-start
#
# chkconfig: - 90 15
# description: Jakarta Tomcat Java Servlets and JSP server

export JAVA_HOME=/usr/java/default
export JRE_HOME=/usr/java/latest
export CATALINA_HOME=/home/vadim/tomcat

case $1 in
start)
  sh $CATALINA_HOME/bin/startup.sh
  ;;
stop)
  sh $CATALINA_HOME/bin/shutdown.sh
  [...]]]></description>
			<content:encoded><![CDATA[<p>Продолжая серию заметок &#8220;Из программиста в <span style="text-decoration: line-through;">руководители</span> админы&#8221; :), опять же себе на заметку пишем init-скрипт для корректного запуска/перезапуска Apache Tomcat под Linux.</p>
<p>Создаем файл <strong>/etc/init.d/tomcat</strong> такого содержания:</p>
<pre><code># Tomcat auto-start
#
# chkconfig: - 90 15
# description: Jakarta Tomcat Java Servlets and JSP server

export JAVA_HOME=/usr/java/default
export JRE_HOME=/usr/java/latest
export CATALINA_HOME=/home/vadim/tomcat

case $1 in
start)
  sh $CATALINA_HOME/bin/startup.sh
  ;;
stop)
  sh $CATALINA_HOME/bin/shutdown.sh
  ;;
restart)
  sh $CATALINA_HOME/bin/shutdown.sh
  sh $CATALINA_HOME/bin/startup.sh
  ;;
*)
  echo "Usage: $0  {start|stop|restart}"
  exit 1
  ;;
esac
exit 0</code></pre>
<p>После этого выполняем:<br />
<code>chmod +x /etc/init.d/tomcat<br />
 chkconfig tomcat on</code></p>
<p>Аналогичный <a href="http://voituk.kiev.ua/2009/02/09/nginx-initd-script/">init.d-скрипт для запуска nginx</a> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/researchers?a=tgng-M7IJZs:X-UfwrkSDI0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/researchers?i=tgng-M7IJZs:X-UfwrkSDI0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/researchers?a=tgng-M7IJZs:X-UfwrkSDI0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/researchers?i=tgng-M7IJZs:X-UfwrkSDI0:F7zBnMyn0Lo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://voituk.kiev.ua/2009/04/28/apache-tomcat-initd-script/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
