суббота, 17 декабря 2011 г.

Открытый софт для научных расчетов

Задачки у меня бывают разные, кратенькое описание того, что может потребоваться я приводил здесь:

Дело происходит в Linux Debian, соответственно, интересует софт, который устанавливается из стандартного репозитория (что подразумевает опенсорсность). 

Для начала я протестировал двумерное Фурье преобразование (прямое и обратное) на широко известном тестовом изображении Lenna. Заодно в процессе поиска нужных функций увидел заметки об истории этого изображения Просто Лена и Обработка изображений: кто такая Лена

Выбор софта для такой типичной задачки вполне себе наличествует:
На практике же оказалось не так радужно, как хотелось бы. Из того, что есть в дебиане, работает "из коробки" только пакет octave. Зато для него можно установить множество расширений - например, необходимый мне пакет octave-image. Если же расширения нет в дебиан, можно установить из репозитория octave. Например, если мы хотим поставить последнюю версию разширения для работы с изображениями, качаем архив image-1.0.15.tar.gz: и далее в текущей директории выполняем:

aptitude install octave3.2-headers 
sudo octave
pkg install image-1.0.15.tar.gz
exit

Как видим, впечатление octave производит самое приятное. К сожалению, не умеет задействовать несколько ядер процессора, это досадно.

Далее я занялся тем, для чего, собственно, и подбирал софт. А именно, построением 3D модели земных недр по космоснимкам высокого разрешения. Несколько ссылок из предметной области:


На 32-бит хосте обработка космоснимка порядка 60 Мб размером требует около 1 Гб ОЗУ. Если же выполнять передискретизацию (скажем, уменьшить матрицу значений в 3 или 5 раз), то и намного меньше. Для Landsat 7 панхроматический снимок будет имеет вдвое большее разрешение и примерно вчетверо больший размер, так что 60 Мб снимок видимого и ИК диапазонов  соответствует примерно 250 Мб панхроматическому. Значит,  8 Гб ОЗУ на 64 бит хосте должно хватить и на обработку панхромата без передискретизации. Интересно, удастся ли это сделать на 32 бит хосте. Скоро проверю и это, как отлажу расчет на ближнем ИК диапазоне. Update. На 32-бит хосте панхроматический снимок прочитать не удалось - octave сообщает, что невозможно выделить требуемый объем памяти.

Статьи и документация по Octave плюс еще некоторые полезные ссылки:

среда, 14 декабря 2011 г.

MS Excel XML to CSV

XSLT file excel2csv.xsl
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mso="urn:schemas-microsoft-com:office:spreadsheet" version="1.0">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
   <xsl:for-each select="mso:Workbook/mso:Worksheet/mso:Table/mso:Row">
        <xsl:for-each select="mso:Cell">
                <xsl:value-of select="mso:Data"/>
                        <xsl:if test="position()!=last()">
                        <xsl:text>      </xsl:text>
                        </xsl:if>
        </xsl:for-each>
        <xsl:text>&#10;</xsl:text>
   </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Important: you may replace 4 spaces in "<xsl:text>      </xsl:text>" to single tabulation (or any other delimiter)!

Use as
cat file.xls | xsltproc excel2csv.xsl - > file.csv

пятница, 25 ноября 2011 г.

Lossless музыка: ape+cue и flac+cue

Как мне недавно имели честь сообщить, аз есмь ретроград - не слушаю Vinil RIP :) В самом деле, по старинке обхожусь mp3. Собственно, когда-то проблемы были с воспроизведением lossless форматов, а разницы с mp3 не заметил. Но вот сегодня доступно много всякого разного именно в виде рипов виниловых пластинок, из того что я давно хотел отыскать - так что разбираемся.

1. Если у нас есть flac+cue - достаточно привести к юникодной кодировку (текстового) файла cue:
cat *.cue | iconv -f cp1251 -t utf8 > .cue
Впрочем, необходимо это только тогда, когда имя файла flac содержит не-латинские символы - в ином случае все можно прослушать и без перекодировки.

2. Когда у нас наличествует набор файлов ape + cue, ставим пакеты pacpl, flac и monkeys-audio (для установки последнего нужно подключить репозиторий http://www.debian-multimedia.org/) и далее перекодируем (здесь команда рекурсивно пройдет все подкаталоги в поисках файлов ape и создаст файлы flac):
pacpl -t flac -o ape -r .
Как и выше, перекодируем файлы cue в юникод и меняем в них имя_файла.ape на имя_файла.flac

Прослушать файлы cue умеет audacious ( в нем можно настроить определение кодировки CP1251 для файла cue и проч.) и qmmp (работает в однобитной кодировке, так что кириллические названия в нем увидеть не удастся, но прослушать трэки - можно). Из прочих популярных плееров _не справились_ с задачей amarok, rhythmbox, juk и smplayer.

Ссылки:
Работа с flac+cue и ape+cue в Debian
Converting Monkey’s Audio (ape) to flac in Ubuntu
Split lossless audio (ape, flac, wv, wav) by cue file in Ubuntu

пятница, 29 июля 2011 г.

О LevelDB и SQLite


Новость:
Компания Google открыла исходные тексты БД LevelDB

Кратко о LevelDB - хранилище ключ-значение, однопоточный доступ, нет гарантий целостности всех данных, в памяти держит копию всех данных лог-файлов.

Утилита для тестирования SQLite у них кривая, мои патчи к ней брать тут

Результаты тестирования с патчем для использования целочисленного Primary Key смотреть здесь

Как видим, LevelDB на тестах показывает местами так себе преимущество относительно реляционной транзакционной СУБД... а местами ухитряется быть еще и медленнее :) Неплохо бы сравнить с CDB от DJB с патчем, убирающем ограничение на "константность". В любом случае, по проведенным тестам нет смысла в использовании LevelDB - функционал урезан сильно, а заметного выигрыша в производительности не видно.

Равно есть куда улучшать и SQLite - некоторые результаты плохи на фоне остальных тестов. Значит, у нас многое еще впереди.

пятница, 22 июля 2011 г.

Обновление eglibc в debian

eglibc (2.13-8) unstable; urgency=low

Starting with the eglibc package version 2.13-5, the libraries are
shipped in the multiarch directory /lib/$arch instead of the more
traditional /lib.

The toolchain in Debian has been updated to cope with that, and most
build systems should be unaffected. If you are using a non-Debian
toolchain to build your software and it is not able to cope with
multiarch, you might try to pass the following options to your
compiler:

-I/usr/include/$arch --sysroot /usr/lib/$arch

-- Aurelien Jarno Sun, 26 Jun 2011 22:28:52 +0200


вторник, 19 июля 2011 г.

Семантический веб и формат RDF

В результате общения на форуме с разработчиком Virtuoso возникло желание поглядеть, что бы все это значило и не будет ли оно полезно мне. Итак, смотрим.

Немного ликбеза: Облако и куб: RDF в аналитической базе данных

Описание языка запросов: SPARQL

Набор утилит: Command Line Semantic Web With Redland

В дебиане доступны следующие пакеты: redland-utils (утилита rdfproc), rasqal-utils (утилита roqet) и raptor-utils (утилита rapper). На этих утилитах построен облачный сервис Triplr — Web Command Line

Запрос из найденных в сети примеров:
$ time roqet -e 'PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name ?website FROM    WHERE { ?person foaf:weblog ?website ; foaf:name ?name . ?website a foaf:Document}'
...
roqet: Query returned 74 results

real	0m1.929s
user	0m0.112s
sys	0m0.012s

$ openload http://planetrdf.com/bloggers.rdf -t|grep Content-Length:
URL: http://planetrdf.com:80/bloggers.rdf
Content-Length: 56645

Теперь попробуем протестировать самостоятельно. Для экспериментов я взял лог веб-сервера, сконвертировав его в файл test.ttl нижеприведенного формата:
@prefix : <http://mobigroup.ru/2011/ttl/example#> .
[] :host "localhost"; :prot "http"; :code 503; :length 12731; :url ""; :type ""; :version "" .
[] :host "localhost"; :prot "https"; :code 503; :length 12731; :url ""; :type "GET"; :version "HTTP/1.1" .
[] :host "localhost"; :prot "https"; :code 302; :length 611; :url "login"; :type "POST"; :version "HTTP/1.1" .
[] :host "localhost"; :prot "https"; :code 200; :length 8006; :url ""; :type "GET"; :version "HTTP/1.1" .
...

$ stat --format=%s test.ttl
8502820

$ wc -l test.ttl 
52593 test.ttl

Загружаем в специальное хранилище (используется BerkeleyDB) и выполняем запрос:
$ time rdfproc test.db parse test.ttl turtle -n
rdfproc: Parsing URI file:///tmp/test.ttl with turtle parser

real	1m35.248s
user	0m42.927s
sys	0m7.116s

$ stat --format="%n %s" test.db*
test.db-po2s.db 21569536
test.db-so2p.db 79216640
test.db-sp2o.db 62119936

$ time rdfproc test.db query sparql - 'PREFIX : <http://mobigroup.ru/2011/ttl/example#> SELECT  ?code ?url ?length WHERE   { ?x :code ?code . FILTER (?code=503) . ?x :url ?url . ?x :length ?length }'>log
rdfproc: Query returned bindings results:
rdfproc: Query returned 1457 results

real	0m13.773s
user	0m13.569s
sys	0m0.132s

А здесь выполняем запрос прямо к файлу:
$ cat test.sparql
PREFIX : <http://mobigroup.ru/2011/ttl/example#>
PREFIX  src: <file:>
SELECT  ?code ?url ?length
FROM    src:test.ttl
WHERE   { ?x :code ?code . FILTER (?code=503) . ?x :url ?url . ?x :length ?length }

$ time roqet -qi sparql test.sparql >/dev/null
...подождал полчаса и прервал запрос...

Увы, очень уж тормознуто. Для сравнения, обычный grep:

$ time grep ":code 503;" test.ttl>/dev/null

real	0m0.046s
user	0m0.040s
sys	0m0.008s

$ grep ":code 503;" test.ttl|wc -l
1457

Теперь попробуем виртуозу. Ставим (запрошенный при установке пароль скоро понадобится!):
$ sudo aptitude install virtuoso-opensource

Открываем в браузере ссылку http://localhost:8890/conductor/ и идем в раздел RDF -> RDF Store Upload, где и грузим наш файл test.ttl ( за 2 минуты 45 секунд). Теперь в разделе RDF->SPARQL выполняем запрос:
PREFIX : <http://mobigroup.ru/2011/ttl/example#>
SELECT  ?code ?url ?length
WHERE   { ?x :code ?code . FILTER (?code=503) . ?x :url ?url . ?x :length ?length }

Время выполнения не показывает, но результат выдает почти мгновенно.

А вот так с помощью консольной isql-vt стереть нафиг все данные и загрузить новые (см. DB.DBA.TTLP_MT):
DB.DBA.RDF_GLOBAL_RESET() ;
DB.DBA.TTLP_MT (file_to_string_output ('/tmp/test.ttl'), '', 'http://localhost:8890/DAV/offline');




И пара запросов - на подсчет всех фактов указанного вида и отчет по URL определенного вида:
PREFIX : <http://mobigroup.ru/2011/ttl/haproxy/offline#>
SELECT  count(*) as ?count
WHERE   { ?x :timestamp ?timestamp }

PREFIX : <http://mobigroup.ru/2011/ttl/haproxy/offline#>
SELECT *
WHERE   { ?x :url ?url .
        ?x :length ?length .
        ?x :backend ?backend .
        ?x :session ?session .
        FILTER regex(?url, "q=") .
        FILTER regex(?url, "/share/") .
}

Ссылки:
Semantic Web
SPARQL — язык запросов к RDF
Знакомимся с RDF и Semantic Web через N3
<> a :RoughGuide; :to :Notation3 .
Primer: Getting into RDF & Semantic Web using N3
W3C Semantic Web Tutorial
A Prototype Knowledge Base for the Life Sciences

О виртуозе:
Extending SPARQL IRI Dereferencing with Virtuoso Sponger Middleware
Sindice, its startup company and 12 billion+ live triples SPARQL endpoint

Геоданные:
OGC Seeks Comment on candidate GeoSPARQL standard

Ресурсы:
RDF-ресурсы (диаграмма кликабельна!)
Currently Alive SPARQL Endpoints

Здесь есть и про bio2rdf
Virtuoso Universal Server AMI for Amazon EC2 Instantiation Guide

What is the Bio2RDF Project?

Страница проекта bio2rdf на sf
Bio2RDF - Demo queries

PubMed : U.S. National Library of Medicine National Institutes of Health

воскресенье, 3 июля 2011 г.

Haproxy и openload: 40ms проблема

При тестировании сервисов за реверс-прокси HAProxy посредством утилиты openload обнаружилась занимательная вещь: любой запрос выполняется не быстрее, нежели за 40 мс! Даже с "monitor-uri /TESTME" (при наличии этой директивы во фронтэнде HAProxy сам обрабатывает запрос, сообщая о состоянии текущего фронтэнда).

Запросы openload через HAProxy:
$ openload http://127.0.0.1/TESTME 1
URL: http://127.0.0.1:80/TESTME
Clients: 1
MaTps 25.00, Tps 25.00, Resp Time 0.040, Err 0%, Count 25
MaTps 25.00, Tps 25.00, Resp Time 0.040, Err 0%, Count 50
MaTps 25.00, Tps 25.00, Resp Time 0.040, Err 0%, Count 75
MaTps 25.00, Tps 25.00, Resp Time 0.040, Err 0%, Count 100

Прямое подключение openload к серверу:
$ openload http://127.0.0.1/TESTME 1
URL: http://127.0.0.1:80/TESTME
Clients: 1
MaTps 2590.64, Tps 2590.64, Resp Time 0.000, Err 0%, Count 2601
MaTps 2609.15, Tps 2775.79, Resp Time 0.000, Err 0%, Count 5399
MaTps 2644.94, Tps 2967.00, Resp Time 0.000, Err 0%, Count 8366
MaTps 2649.39, Tps 2689.48, Resp Time 0.000, Err 0%, Count 11077

Как выяснилось, проблема таится в кривом сетевом коде openload: мало того, что сильно нагружается CPU и о тестировании производительных сервисов стоит забыть сразу, так еще и возникает указанный выше таймаут.

Забавно, конечно, что автор openload побайтово работает с данными - видимо, в Индии процессоры мощные, а интернет медленный :D Комментарий от Willy:

What is shown below clearly indicates that it will never be possible
to reach medium to high loads with this tool, it receives the response
one byte at a time ! Anyway, this is unrelated to what you're observing.

> recvfrom(3, 0x507340, 1, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
> select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
> select(4, [3], [], [3], {0, 200000}) = 1 (in [3], left {0, 160000})
> recvfrom(3, "H", 1, 0, NULL, NULL) = 1
> recvfrom(3, "T", 1, 0, NULL, NULL) = 1
> recvfrom(3, "T", 1, 0, NULL, NULL) = 1
> recvfrom(3, "P", 1, 0, NULL, NULL) = 1
> recvfrom(3, "/", 1, 0, NULL, NULL) = 1

Как обходной путь, для работы с openload можно добавить в конфиг фронтэндов HAProxy директиву "no option tcp-smart-accept". После тестирования лучше отключить эту директиву - для работы браузеров и т.п. она не нужна, а эффективность работы сети снижает.

Разбор проблемы от Willy:

Hehe as you can see the client's but is even more visible here,
with 40ms betweeen the two parts :

1) the connection comes in and the first half of the request is received :

10:05:38.831751 accept(4, 0x7fff071de650, [128]) = -1 EAGAIN (Resource temporarily unavailable) <0.000000>
10:05:38.831751 recvfrom(1, "GET /README HTTP/1.1\r\n", 8192, 0, NULL, NULL) = 22 <0.000000>
10:05:38.831751 recvfrom(1, 0x6a8096, 8170, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable) <0.000000>
10:05:38.831751 epoll_ctl(0, EPOLL_CTL_ADD, 1, {EPOLLIN, {u32=1, u64=1}}) = 0 <0.000000>
10:05:38.831751 epoll_wait(0, {}, 5, 0) = 0 <0.000000>
10:05:38.831751 gettimeofday({1309413938, 831751}, NULL) = 0 <0.000000>

2) the clients remains silent for 40 ms, we're waiting for it to talk :

10:05:38.831751 epoll_wait(0, {{EPOLLIN, {u32=1, u64=1}}}, 5, 1000) = 1 <0.040000>
10:05:38.871751 gettimeofday({1309413938, 871751}, NULL) = 0 <0.000000>

3) the client finally decides to send the last part 40 ms later :

10:05:38.871751 recvfrom(1, "Connection: Close\r\nHost: 127.0.0.1\r\n\r\n", 8170, 0, NULL, NULL) = 38 <0.000000>

Большое спасибо Willy Tarreau (автор HAProxy) за помощь. Выше были приведены некоторые части нашей переписки для получения ясного представления о происхождении и решении проблемы.

TclCloud is an opensource tcl interface to the Amazon AWS webservices

Свершилось :) Полное описание и исходники см. по ссылке TclCloud

TclCloud is an opensource tcl interface to the Amazon AWS webservices api that enabled cloud automation of most AWS products and operations. Example use cases include the following:
* starting and stopping EC2 instances
* attaching EBS volumes
* creating and interfacing with SimpleDB and RDS instances
* managing EC2 Autoscale and Load Balancer configurations
* sending Simple Email Service messages
* creating, submitting and monitoring Elastic Map Reduce (Hadoop) jobs
* configuring VPC networks
* and so on ...
For more information on the Amazon AWS cloud products, see: http://aws.amazon.com/products/

Для удобства собрал пакет, брать в моем репозитории или по ссылке
Tcl cloud deb package

среда, 15 июня 2011 г.

Деб-пакеты с модулями SQLite

Собрал некоторые расширения как деб-пакеты, см. репозиторий http://mobigroup.ru/debian/pool-squeeze/main/s/

В апстримовском расширении FTS3 поправлен баг, мешающий собирать его отдельным модулем. Версия из текущего trunk, умеет conflict-resolution для виртуальных таблиц (можно писать insert or replace ...). Также добавлена поддержка стеммеров Snowball.

Модуль ICU собран "как есть" апстримовский.

Добавлен модуль для подсчета хэша sha1 (используется быстрая реализация из BSD-систем).

Для перекомпиляции, в т.ч. под другие ОС, см. в архивах файлик debian/rules, где содержатся команды сборки.

Для удобства загрузку нужных расширений можно сделать с помощью файла ресурсов:
$ cat ~/.sqliterc 
.load /usr/lib/libsqlitetcl.so
.load /usr/lib/libsqliteicu.so
.load /usr/lib/libsqlitefts3.so
.load /usr/lib/libsqlitesha1.so

$ sqlite3
-- Loading resources from /home/veter/.sqliterc

суббота, 11 июня 2011 г.

Оптимизация взаимодействия веб-клиента и сервера - Практические задачи

В завершение мы немного поговорим о типовых задачах, с которых многие из нас и начинают впервые заниматься веб-проектами. Предложенные далее решения будут настолько просты, что вы их сможете реализовать сразу же в процессе чтения статьи, а далее и масштабировать, при необходимости.


Хотелось бы немного остановиться на вопросе запуска сервисов. Способов запуска сервисов в линукс немало - скрипты http://ru.wikipedia.org/wiki/Init:


init (сокращение от англ. initialization — инициализация) — программа в UNIX и Unix-подобных системах, которая запускает все остальные процессы.

утилита nohup:


nohup — UNIX-утилита, запускающая указанную команду с игнорированием сигналов потери связи (hangup); таким образом, команда будет продолжать выполняться в фоновом режиме и после того, как пользователь выйдет из системы.

и даже запуск в сеансе screen.


Для использования init нужны рутовые права или специальная настройка системы для запуска с правами пользователя посредством команды sudo. Два других способа не требуют ни настройки системы, ни каких-либо дополнительных прав, но после перезагрузки сервера придется запускать все вручную. Все названные методы имеют большой недостаток - если сервис по какой-либо причине завершился, перезапустить его потребуется вручную. Недостаток - это еще мягко сказано, скорее, это огромная концептуальная дыра (обычно администраторы пишут скрипты для проверки работающих сервисов и, при необходимости, их перезапуска; такие скрипты добавляются в cron). Если есть возможность, рекомендую установить суперсервер runit, который обеспечивает возможность с правами пользователя создавать сервисы и управлять ими, а кроме того, сам перезапустит сервис при необходимости. Подробнее смотрите или в англоязычной документации или в русскоязычной статье Использование runit для своих сервисов.


Файловый хостинг


Все необходимое для создания файлового хостинга рассмотрено в разделе Статический контент. Здесь лишь приведу пример конфигурационного файла для запуска с помощью супервизора runit:


run

#!/bin/sh

export HOST=127.0.0.1
export PORT=6100
export ROOT=~/wwwserver

cd $ROOT
exec tcpserver -c 5 -R -H $HOST $PORT env -i LANG="ru_RU.UTF-8" \
/usr/sbin/fnord-idx . 2>/dev/null 1>/dev/null

Также можно средствами runit включить логирование запросов, но об этом см. в документации. Если листинг директорий не нужен, можно заменить /usr/sbin/fnord-idx на /usr/sbin/fnord. Для поддержки CGI и листинга директорий используйте /usr/sbin/fnord-cgi-idx, а только для CGI - /usr/sbin/fnord-cgi.


Система контроля версий


Все успешные проекты пользуются системами контроля версий, и для многих разработчиков установка и настройка такой системы это именно то, с чего начинается проект. Кроме того, для создания корпоративных и вики-сайтов может оказаться вполне достаточно функционала, предоставляемого версионной вики. Как видим, затронутая тема вполне практична.


Существует множество разных продуктов для управления версиями, зачастую нелегко разобраться в их преимуществах и недостатках. При выборе подходящего решения стоит обратить внимание на не-администрируемые решения с возможностью распределенной работы и веб-доступом. Весьма желательно также наличие встроенной версионной вики, что облегчает документирование и обеспечивает соответствие версий файлов и документации. В качестве такой системы я предпочитаю использовать fossil, который удовлетворяет всем перечисленным требованиям:


Fossil представляет собой простую в использовании распределенную систему управления исходными кодами (DSCM) с поддержкой доступа и администрирования через HTTP CGI или встроенный HTTP сервер, имеет встроенную вики, встроенный браузер файлов, встроенную тикет-систему (tickets system) и другие возможности.

Кроме того, поддерживается цифровая подпись всех коммитов, эффективный протокол синхронизации и множество других нужных функций, описание которых вы найдете на официальном сайте. Здесь я отмечу лишь самую замечательную особенность - репозиторий представляет собой единственный кроссплатформенный файл, содержащий хорошо упакованные исходные коды и дельты их изменений. Простым копированием этого файла можно перенести репозиторий на любую платформу и операционную систему.


Скачать бинарную сборку для вашего дистрибутива можно по адресу http://www.fossil-scm.org/download.html В debian/ubuntu дистрибутивах пакет fossil также есть в официальном репозитории. Основы работы описаны на сайте проекта, а также доступна для скачивания книга Fossil User manual. Далее мы ограничимся лишь парой примеров для облегчения начала самостоятельной работы.


Получить список всех команд:

$ fossil help
Usage: fossil help COMMAND.
Available COMMANDs:
add            close          http           redo           sync         
all            co             info           remote-url     tag          
annotate       commit         leaves         rename         timeline     
artifact       configuration  ls             revert         ui           
branch         del            merge          rm             undo         
cgi            descendants    mv             scrub          unset        
changes        diff           new            search         update       
checkout       extras         open           server         user         
ci             finfo          pull           settings       version      
clean          gdiff          push           sha1sum        wiki         
clone          help           rebuild        status         zip          
This is fossil version [15cb835736] 2010-06-17 18:39:10 UTC

Получить описание отдельной команды:

$ fossil help add
Usage: fossil add FILE...

Make arrangements to add one or more files to the current checkout
at the next commit.

When adding files recursively, filenames that begin with "." are
excluded by default.  To include such files, add the "--dotfiles"
option to the command-line.

Как видим, программа самодокументированная и разобраться с ее возможностями несложно.


Благодаря идеологии распределенной работы все версии репозитория равноправны, так что утрата любого из репозиториев, включая репозиторий на основном сервере, проблемой не является - можно скопировать репозиторий любого разработчика на сервер и синхронизировать его с остальными разработчиками, восстановив, таким образом, всю информацию. Вы еще думаете о проблеме бэкапов и центральном сервере? Забудьте, мы живем в мире распределенной информации. Если бы я решил последовать текущей ИТ-моде, то совершенно справедливо назвал бы fossil "облачной" системой контроля версий.


Вики


Ранее мы уже рассматривали систему контроля версий со встроенной вики: Система контроля версий Рассмотрим подробнее, чем же эта система нам будет полезна в новом качестве.


Начну с примера - данная статья с помощью встроенной в fossil вики в текущий момент редактируется локально в браузере, а после будет синхронизирована с ее веб-версией на сайте http://book.mobigroup.ru. Также можно сохранить файл статьи на диск, отредактировать в любимом текстовом редакторе и загрузить новую версию в локальный или удаленный fossil-репозиторий. Все ресурсы к статье (картинки, скрипты) также управляются fossil и в любой момент можно получить нужную версию статьи с соответствующими ей картинками и прочими ресурсами. Итак, есть фоссил-репозиторий на сайте и его копия (может быть сделана любым способом, каким нам больше нравится копировать файл) или клон (выполненный через HTTP командой fossil clone) на локальной машине. Изменения можно вносить в оба репозитория, а после синхронизации они снова станут идентичными. Иначе говоря, кроме стандартного функционала веб-вики мы получаем еще и вики локальную, которой можно пользоваться при отсуствии доступа в интернет и даже при отсутствии браузера. Любой пользователь может создать свою локальную копию и вносить в нее изменения, притом, если у него есть права редактирования вики-страниц в основном репозитории, то после этот пользователь сможет выполнить синхронизацию.


Заметим, что локальная версия репозитория является также бэкапом - в любой момент ее можно скопировать на сервер и запустить веб-интерфейс. Как много говорят о том, что бэкапы делать нужно, - но эта потребность возникает лишь при работе с "глупым" программным обеспечением, которое не умеет самостоятельно обеспечивать сохранность своих данных и даже неспособно объединить несколько частичных копий. fossil решает задачу сохранности информации благодаря поддержке ее распределенного хранения, причем синхронизация выполняется одной командой, а восстановление всех данных - простым копированием единственного файла репозитория или еще одной командой.


В качестве примера рассмотрим, как же нам получить копию репозитория, в котором опубликавана эта статья, в папке /tmp/book на своем компьютере:

$ mkdir /tmp/book
$ cd /tmp/book
$ fossil clone http://book.mobigroup.ru/ book.fossil
                Bytes      Cards  Artifacts     Deltas
Send:              49          1          0          0
Received:       16969        368          0          0
Send:           10025        225          0          0
Received:      850820        255         81        119
Send:            7898        176          0          0
Received:     1344313        214         60        107
Total network traffic: 9996 bytes sent, 434133 bytes received
Rebuilding repository meta-data...
367 (100%)...
project-id: c038be6d00dcad09c6cb103418aee95fea066e28
server-id:  e817408496f556de59679d530e521e807d2f9045
admin-user: alexey (password is "d52atf")

Вот и все, теперь можно работать с локальной копией. Имя администратора alexey и пароль "d52atf", но авторизация по умолчанию требуется только для удаленного доступа, а локально на своем компьютере логин и пароль не потребуются.


Откроем полученный репозиторий:

fossil open book.fossil 
...
project-name: Статьи Mobigroup
repository:   /tmp/book/book.fossil
local-root:   /tmp/book/
project-code: c038be6d00dcad09c6cb103418aee95fea066e28
server-code:  e817408496f556de59679d530e521e807d2f9045
checkout:     e78a25c434cfbb6175f91a69ae9dd022498392b8 2010-07-29 14:22:15 UTC
parent:       942d9890eeb8c85394c509f486558d708d8c7d08 2010-07-27 07:30:22 UTC
tags:         trunk

Теперь можно из консоли работать с репозиторием или запустить веб-интерфейс в браузере:

$ fossil ui
В текущем сеансе браузера создано новое окно.

После выполнения этой команды запустится браузер или откроется новое окно в уже запущенном браузере, с адресом http://localhost:8080/ Веб-интерфейс достаточно удобный, так что не будем отсанавливаться подробнее на том, как создать или сохранить страницу вики или просмотреть и извлечь файлы из репозитория.

Оптимизация взаимодействия веб-клиента и сервера - Кэширующий прокси

Об этих "невидимках" многие разработчики забывают, ведь кэширующие прокси находятся где-то далеко от серверов проекта и нам не подчиняются. Зато с ними мы совершенно бесплатно получаем так называемую CDN (Content Delivery Network), о которой мечтают чуть ли не все веб-разработчики. Очевидно то, что для сохраненных в кэше прокси-серверов объектов запрос к веб-серверу не требуется и это может очень значительно снижать нагрузку на оборудование нашего веб-ресурса. Но это еще не все, ведь клиент получает HTTP-ответ от ближайшего к нему прокси, у которого нужный ресурс есть в кэше, таким образом, время отклика снижается многократно. Если же нужный объект закэширован непосредственно в браузере, результат окажется еще лучше. Также в любой момент можно установить кэширующий прокси на своем сервере (или серверах) и так масштабировать веб-проект. Кэширующие прокси стандартизированы и следует лишь настроить отдачу нужных HTTP-заголовков для управления кэшированием с помощью веб-сервера или реверс-прокси.


Обратите внимание на следующие HTTP-заголовки: Cache-Control, ETag, Expires, If-Modified-Since, Last-Modified. Чаще всего используются Cache-Control и Expires. Подробно рассматривать эти заголовки мы не будем, поскольку их настройка индивидуальна для разных проектов и в сети Интернет есть детальные руководства для всех популярных случаев.


Приведем пример, как добавить HTTP-заголовок с директивой кэширования на уровне реверс-прокси Haproxy:


rspadd Cache-Control:\ public,\ max-age=604800

Схожим образом можно и удалить HTTP-заголовок:


rspidel ^Cache-Control:.*

Вышеназванный метод удобен тем, что не зависит от используемого веб-сервера и позволяет централизованно управлять кэшированием в проектах с множеством веб-серверов. Впрочем, многие веб-севрверы позволяют управлять и передаваемыми заголовками, если вам это нужно.


Узнать больше об использовании директив кэширования можно в статье PHP и Web. Кэширование.

Оптимизация взаимодействия веб-клиента и сервера - Настройка операционной системы

Для нагруженного сайта необходимость настройки сервера мало у кого вызывает удивление, да и для небольших веб-проектов стоит заранее предусмотреть опции защиты от DDOS-атак. По умолчанию Linux-системы имеют сетевые настройки, более подходящие для десктопов, нежели для серверов. Какие-либо общие рекомендации дать сложно, потому предлагаю читателям набор настроек, которые достаточно хороши для "среднего" сервера.


/etc/sysctl.conf

net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

net.ipv4.conf.default.rp_filter=1
net.ipv4.tcp_syncookies=1

net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5

net.core.somaxconn = 1024
net.core.netdev_max_backlog = 4000
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_max_tw_buckets = 360000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1

net.core.rmem_default = 262144
net.core.wmem_default = 262144

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

Посмотрев описания и рекомендации для перечисленных параметров в документации, вы сможете вполне прилично настроить свой сервер. Возможно, вам потребуются далеко не все из названных настроек, постарайтесь ограничиться минимумом изменений или попробовать использовать вышеприведенный конфиг "как есть".

Оптимизация взаимодействия веб-клиента и сервера - Реверс-прокси

Реверс-прокси это все равно что дворецкий, встречающий гостей в аристократическом замке, и при плохом выборе наш проект поворачивается к посетителям отнюдь не лицом. Современные реверс-прокси также являются и балансировщиками нагрузки, позволяя распределять поступающие запросы по множеству серверов-обработчиков.


Среди "чистых" реверс-прокси, не обремененных сторонней функциональностью, стоит назвать Pound и HAProxy. Рассмотрим особенности их использования в реальных проектах. Начнем с Pound, как более простого:


Pound позволяет распределять нагрузку между множеством Web-серверов, а также имеет встроенную поддержку SSL.

Для небольших проектов Pound будет прекрасным выбором, но при росте проекта может потребоваться его замена. На процессоре уровня Pentium D примерно при 200-300 HTTPS или 600-800 HTTP-запросах в секунду Pound перестает справляться с нагрузкой. Разработчики Pound в ответ на подобные вопросы рекомендуют воспользоваться другими реверс-прокси, пригодными для больших проектов, и это же отражено в документации. Настройка Pound проста и не требует много времени, более того, достаточно прочитать главную страницу проекта, чтобы узнать о его настройке все или почти все. Для небольших и средних проектов стоит выбрать именно его. Плюсом является и встроенная поддержка HTTPS.


Для высоконагруженных проектов прекрасным выбором станет HAProxy:

HAProxy это TCP/HTTP обратный прокси, предназначеннный для высоконагруженных проектов. Поддерживаются сессии на основе HTTP куки, балансировка нагрузки, управление входящими и исходящими хидерами HTTP-запросов. Кроме того, есть возможности блокировки запросов и удобный веб-интерфейс для просмотра всей статистики и текущего состояния.


HAProxy один из самых быстрых реверс-прокси. В число проектов, где работает HAProxy, входит Amazon EC2. Настройка нетривиальна и требует внимательного изучения документации, зато настроить можно очень гибко. Начинать знакомство с этим прокси стоит с чтения официальной документации.

Оптимизация взаимодействия веб-клиента и сервера - Сервера приложений (платформы)

Многие динамические сайты для проектов с высокой нагрузкой используют специализированные веб-сервера со встроенным интерпретатором какого-либо скриптового языка и встроенными средствами оптимизации и масштабирования. Такие системы принято называть серверами приложений:


Сервер приложений (англ. application server) — сервер, исполняющий некоторые прикладные программы. Термин также относится и к программному обеспечению, установленному на таком сервере и обеспечивающему выполнение прикладного ПО.

Ниже мы предпримем небольшой экскурс в историю и познакомимся с первым или одним из первых серверов приложений, который успешно развивался все эти годы и сегодня является мощной и эффективной системой уровня предприятия. Ссылки в основном ведут на англоязычные ресурсы, потому что в рунете практически нет информации о веб-технологиях 1990-х, активно развивавшихся в США. На самом же деле ко времени появления форка довольно примитивного веб-сервера NCSA HTTPd 1.3 под именем Apache в 1995 году уже существовали мощнейшие веб-платформы. А основанная в 1995-м году Полом Грэмом и Робертом Моррисом компания Viaweb была первым SAS (Software-As-Service) провайдером! В 1998-м году эта компания была приобретена Yahoo и превратилась в Yahoo Store.


Для Tcl мощным сервером приложений является AOL Server с многопоточным интерпретатором Tcl и развитым высокоуровневым API, пулом подключений к БД, мощной системой кэширования кода и файлов, пулом процессов-обработчиков HTTP-соединений, поддержкой языка серверных сценариев AOLserver Dynamic Pages и другими возможностями. При этом конфигурационный файл AOL Server является тиклевым скриптом, так что в нем можно использовать переменные, получать параметры конфигурации из любых внешних источников и многое другое. AOL Server разрабатывался в созданной в 1993-м году компании NaviSoft, купленной в 1994 году корпорацией AOL, и в 1999 году AOLserver 3.0 выпущен под open-source лицензией AOLserver Public License, аналогичной Mozilla Public License. Подробнее можно прочитать в статье от 2002-го года Introducing AOLserver. Существует форк проекта AOL Server, который взял исходное название NaviServer, в нем добавлены некоторые интересные возможности.


Совместно с сервером приложений для разработки может использоваться и один из фрэймворков:

Каркас (англ. framework) — в информационных системах структура программной системы; программное обеспечение, облегчающее разработку и объединение разных компонентов большого программного проекта. В его состав могут входить вспомогательные программы, библиотеки кода, язык сценариев и прочее.


Задача фрэймворка заключается и в том, чтобы предоставить идеологию разработки приложений, а не просто набор необходимых функций. Библиотеки кода могут использоваться и в CGI-приложениях, как мы уже видели в разделе динамический контент, но у серверов приложений имеется огромное преимущество в том, что весь вспомогательный код может быть загружен заранее, не замедляя выполнение каждого запроса.


Для AOL Server известным фрэймворком является OpenACS, есть и другие. OpenACS является открытой системой, построенной на кодовой базе одной из первых enterprize систем управления веб-контентом ArsDigita Community System, или, сокращенно, ACS. Да-да, от легендарной ArsDigita Corporation, о которой с восхищением пишет Джоель Спольски в статье Весна в Кэмбридже. В OpenACS добавлена поддержка СУБД PostgreSQL, тогда как ACS работал только с СУБД Oracle. В 2001 году после краха доткомов ArsDigita находилась в сложном положении, и было принято решение создать Java EE версию ACS, а в 2002 году компания Red Hat купила ArsDigita и продолжила разработку платформы ACS на Java EE под именем Red Hat CCM, в то время как Tcl-версия была переименована в OpenACS и управляется OpenACS community. В настоящее время многие крупные сайты работают именно на AOL Server + OpenACS, в том числе учебный процесс и сайты многих университетов управляются известной системой для электронного образования www.dotlrn.org


Раздача статического контента с помощью сервера приложений не столь быстра, как у веб-серверов для статики - это плата за возможность реализации необходимой бизнес-логики. Если посмотреть сравнительный график веб-серверов из соответствующего раздела, то становится заметным отставание AOLServer.


Теперь подробнее рассмотрим сервер приложений AOL Server и начнем с его установки. В debian-based дистрибутивах установка выполняется с помощью пакетного менеджера apt, в других дистрибутивах есть свои менеджеры пакетов.

sudo aptitude install aolserver4

Подготовительные действия по инициализиции веб-приложения и загрузке вспомогательных библиотек теперь не требуется выполнять для каждого запроса заново - эти действия можно выполнить единожды в скрипте инициализации. В конфигурации по умолчанию в debian-системах это должен быть файл с произвольным именем и расширением tcl в директории /usr/lib/aolserver4/servers/main/modules/tcl/tcl_module/, мы назовем его init.tcl:


/usr/lib/aolserver4/servers/main/modules/tcl/tcl_module/init.tcl

package require sqlite3
Здесь мы загрузили библиотеку для работы с базами данных формата SQLite3.

Запускаем сервер с конфигурационным файлом по умолчанию (из debian-пакета):

$ sudo /etc/init.d/aolserver4 restart

При старте будет загружен созданный нами файл init.tcl и указанная в нем библиотека станет доступна всем скриптам.


Пример. Простая страница.


В динамических страницах AOL Server содержимое тэгов <% ... %> интерпретируется как Tcl код, а все прочее считается HTML разметкой. Так что от нас потребуется лишь в нужном месте HTML страницы вставить Tcl код:


/var/www/index.adp

<HTML><BODY>
<h1>Привет, мир! Сейчас <%=[clock format [clock seconds]]%></h1>
</BODY></HTML>"

Проверяем, что наша страничка корректно создается:

$ openload -t localhost/index.adp
URL: http://localhost:80/index.adp
Clients: 1
------------------------
Status: 200
---- Headers -----------
Expires: now
MIME-Version: 1.0
Date: Sat, 03 Jul 2010 05:56:16 GMT
Server: AOLserver/4.5.1
Content-Type: text/html; charset=UTF-8
Content-Length: 123
Connection: close
---- Body   123 bytes --
<HTML><BODY>
<h1>Привет, мир!</h1>
</BODY></HTML>
---- End ---------------
Можно это и в браузере посмотреть, зайдя на адрес локального сервера http://localhost

Пример. Работа с БД SQLite3.


Создадим тестовую базу:

echo "create table log(date REAL NOT NULL DEFAULT (julianday('now'))); \
CREATE INDEX log_date_idx ON log(date);" | sqlite3 /tmp/www.db
chmod a+rw /tmp/www.db 

Создадим скрипты для вставки новой записи:


/var/www/write.adp

<%
sqlite3 db /tmp/www.db
db timeout 2000
db eval {insert into log default values}
set rowid [db onecolumn {select last_insert_rowid()}]
ns_adp_puts "Inserted new record ROWID=$rowid"
db close
%>

и для чтения времени последней добавленной записи:


/var/www/read.adp

<%
sqlite3 db /tmp/www.db
db timeout 2000
set lasttime [db onecolumn {select datetime(max(date)) from log}]
ns_adp_puts $lasttime
db close
%>

Команда db timeout 2000 указывает, что в случае, когда в БД заблокирована (производится запись из другого потока), следует подождать освобождения БД, но не более 2-х секунд (т.е. 2000 миллисекунд), а не возвращать сразу же ошибку доступа к БД. В AOL Server есть пулы соединений, предоставляющие единый интерфейс доступа к разным СУБД, но здесь используем более простой способ, открывая новое соединение к БД на каждый запрос.


Как мы видим, нет ничего особенно сложного в разработке веб-проектов на основе AOL Server. Рассказать можно еще очень многое, но нам придется ограничиться лишь таким кратким обзором. Для тех, кто заинтересовался одним из мощнейших из существующих серверов приложений AOL Server, найдется множество статей, примеров и целых промышленных платформ, ссылки на некоторые из них приведены в начале этой статьи.

Оптимизация взаимодействия веб-клиента и сервера - Динамический контент

Что касается раздачи динамического контента ("динамики"), хорошо известным методом является использование CGI-технологии:


CGI (от англ. Common Gateway Interface — «общий интерфейс шлюза») — стандарт интерфейса, используемого для связи внешней программы с веб-сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» (сценарий) или «CGI-программа».

Сам интерфейс разработан таким образом, чтобы можно было использовать любой язык программирования, который может работать со стандартными устройствами ввода/вывода. Такими возможностями обладают даже скрипты для встроенных командных интерпретаторов операционных систем, поэтому в тех случаях, когда нет нужды в сложной функциональности, могут использоваться простые командные скрипты.


Промежуточным решением между CGI и серверами приложений можно назвать технологию FastCGI, позволяющую убрать часть ограничений CGI, но имеющую и свои серьезные проблемы. По моему мнению, стоит или ограничиться CGI, если хватает производительности, или работать с серверами приложений.


Часто CGI-приложения запускают с помощью веб-сервера, но на самом деле, это совсем не обязательно. Веб-сервер для CGI-программ всего лишь определяет значения переменных окружения согласно полученным заголовкам HTTP, хотя и само приложение может прочитать эти заголовки и обойтись без помощи веб-сервера. Далее я приведу примеры CGI-приложений как запускаемых напрямую, так и с помощью веб-сервера fnord-cgi (это уже знакомый нам fnord, скомпилированный с опцией поддержки CGI).


Разрабатывать веб-приложения можно на самых разных скриптовых языках, но я предпочитаю пользоваться языком Tcl, который с успехом применяется как для больших проектов (в том числе веб-проектов), так и для несложных утилит. Кроме прочих соображений, Tcl надежен и предложенные мною примеры можно запускать на общедоступном сервере. Если вы захотите переписать примеры на любом другом языке, это сделать несложно, но берегитесь уязвимостей, особенно при вызове внешних программ. В дополнение к примерам на Tcl я продемонстрирую написание CGI-программы и на unix shell.


Пример. Листинг директории (unix shell)


Для получения листинга директории можно поступить следующим образом: вывод утилиты ls с помощью unix shell отформатировать в виде, понятном для веб-клиентов. Главное достоинство этого метода в том, что он очень быстр - настолько, что зачастую не уступает встроенному в веб-сервер генератору индекса директории. Шелл-скрипт может выглядеть следующим образом:


$ tcpserver localhost 8888 echo "HTTP/1.0 200 OK
Content-type: text/plain

`ls`"

$ openload -t localhost:8888
URL: http://localhost:8888/
Clients: 1
------------------------
Status: 200
---- Headers -----------
Content-type: text/plain
---- Body    10 bytes --
hello.cgi
---- End ---------------

Приведенные команды с tcpserver и openload нужно запускать в разных консолях, так, чтобы tcpserver был запущен первым и мог ответить на запрос от openload. И в результате мы видим простой листинг директории, который несложно отформатировать в удобном для нас виде.


Пример. Вывод текущего времени (Tcl)


hello.cgi

#!/usr/bin/tclsh

 
puts "HTTP/1.0 200 OK"
puts "Content-type: text/html; charset=utf-8\n"
puts "<HTML><BODY>"
puts "<h1>Привет, мир! Сейчас [clock format [clock seconds]]</h1>"
puts "</BODY></HTML>"

Запустим почти так же, как и ранее. Утилита env здесь "прячет" от скрипта все переменные окружения - я это делаю из соображений безопасности, но это не является общепринятой практикой.


$ tcpserver localhost 8888 env -i ./hello.cgi

$ openload -t localhost:8888
URL: http://localhost:8888/
Clients: 1
------------------------
Status: 200
---- Headers -----------
Content-type: text/html; charset=utf-8
---- Body   104 bytes --
<HTML><BODY>
<h1>Привет, мир! Сейчас Tue Jul 13 23:29:13 MSD 2010</h1>
</BODY></HTML>
---- End ---------------

Откройте адрес http://localhost:8888 в своем браузере и вы увидите страничку текстом "Привет, мир!" и текущей датой.


Пример. AJAX и СУБД SQLite3 (Tcl)


Проиллюстрируем создание AJAX-сервиса на примере небольшого приложения, отображающего записи из базы данных: http://mobigroup.ru/service/jsontest/. Код доступен по ссылке jsontest. Для отображения результатов используется компактный и быстрый кроссбраузерный шаблонизатор на javascript (см. js-функцию supplant).


Пример. Конвертор трэков GPS (Tcl)


Напишем конвертор трэков со спутникового навигатора для отображения их на Google Maps и в Google Earth. Создадим страничку, отображающую форму для отправки пользователем конвертируемого файла, и скрипт для преобразования формата трэка. Само преобразование выполнит утилита gpsbabel, а от скрипта потребуется принять и сохранить файл, вызвать gpsbabel с нужными аргументами и вернуть результат пользователю.


Для интерактивного приложения, взаимодействующего с пользователем, удобно использовать модуль ncgi из библиотеки tcllib, умеющий работать с HTTP-формами, cookie и загрузкой файлов. Образцы кода для работы можно найти по адресу ncgi.test. Модуль предполагает существование переменных окружения, список которых определяется стандартом для протокола CGI. Опять же, обратимся к минималистичному веб-серверу fnord-cgi для обработки CGI-скриптов.


HTML-страница для выбора файла исходного трэка:


index.html

<html>
<head> 
<meta content='text/html; charset=utf-8' http-equiv='content-type'></meta> 
</head> 
<body>
<h3>Конвертор трэков в формат KML</h3> 
<form enctype='multipart/form-data' method='POST' action='/track2kml.cgi'>
<input name='file' id='file' type='file' size='25''/>
<input name='upload' value='Преобразовать' id='upload' type='submit'/>
</form> 
</body> 
</html>

И CGI-скрипт пробразования трэка:


track2kml.cgi

package require ncgi
::ncgi::parse

puts "Content-type: text/html; charset=utf-8\n"

array set extensions {.gdb gdb .mps mapsource .plt ozi .gpx gpx .nmea nmea .txt nmea}
set filename [clock seconds].kml
set clientname [ncgi::importFile -client file]
# anti-XSS                                                                                                                   
set clientname [string map {& &amp; < &lt; > &gt; \" &quot;} $clientname] 
puts "
<html><body>"
if {[::ncgi::exists file]==1 && $clientname ne {} && 
  [info exists extensions([file ext $clientname])]==1} {
    set filetype $extensions([file ext $clientname])
} else {
    puts "<b>Укажите файл для конвертации в одном из форматов
[array names extensions]</b>"
    puts "<br><br><a href='javascript:history.go(-1)'>Назад</a>"
    exit
}
puts "<b>Загружен файл: $clientname</b><br>"
set inname [ncgi::importFile -server file]
set tmpname ${inname}.kml
catch {exec /usr/bin/gpsbabel -t -x simplify,error=0.002k -i $filetype \
  -o kml,points=0,trackdata=0,line_width=3,line_color=990000FF $inname $tmpname}
if {[file exists $tmpname]==1} {
  catch {file rename $tmpname $filename}
} else {
  puts "<b>Ошибка: не удалось выполнить конвертацию</b>"
}

if {[file exists $filename]==1} {
    puts "<a href='$filename'>Скачать файл KML</a><br>"
}
puts "<br><br><a href='javascript:history.go(-1)'>Назад</a>"
puts "</body></html>"

Запускаем сервис так:

tcpserver localhost 8888 env -i /usr/sbin/fnord-cgi .

Загружаем трэк, к примеру, с Garmin Oregon в формате gpx, а полученный трэк в формате kml можно открыть в Google Earth. Онлайн-версия этого сервиса также предоставляет ссылку для просмотра трэка на Google Maps и доступна по адресу http://mobigroup.ru/service/track2kml/, а ее код можно увидеть здесь track2kml. Более современным решением является создание AJAX-приложения, смотрите http://mobigroup.ru/service/track2kml-ajax/, и его код track2kml-ajax. В последнем случае мы полностью разделяем серверный код на Tcl и клиентский интерфейс на html/javascript, что очень облегчает дальнейшие поддержку и модификацию приложения, притом код серверной части заметно упрощается.

Оптимизация взаимодействия веб-клиента и сервера - Статический контент


Введение

Зачастую достаточно лишь позаботиться об интенсивном кэшировании статики на стороне клиента (включая сюда кэширующие прокси-серверы интернет-провайдеров), и количество запросов на статику оказывается относительно мало, так что оптимизация этих и так "легких" запросов становится бесполезной. Но что делать, если запросов все равно очень много? Это может быть вызвано как характером контента (например, фотогалерея), так и просто высокой посещаемостью, особенно когда много уникальных посетителей.

Легковесность

Минималистичные веб-сервера для раздачи статики совсем или почти совсем не требуют настройки, обеспечивая при этом высокую производительность. Одним из действительно простых и эффективных веб-серверов для отдачи статического контента является fnord:
Программа fnord представляет собой миниатюрный HTTP сервер(15k размером), запускаемый посредством TCP суперсервера tcpsvd, tcpserver или другого. fnord хорошо оптимизированный и быстрый, поддерживает передачу методом sendfile и постоянные соединения (keep-alive), CGI, виртуальные домены, и докачку (content-ranges). Дополнительно встроена возможность подмены содержимого на лету (html - html.gz, or gif - png), и генерация индекса директории.
Особенно интересен fnord тем, что работа с TCP делегирована так называемому TCP суперсерверу. В любой UNIX/Linux системе есть встроенный TCP суперсервер, но мы обратимся к помощи более производительного tcpserver:
tcpserver ожидает входящие соединения от TCP клиентов. Для каждого соединения запускается программа, указанная аргументом командной строки, при этом дескриптор 0 принимает данные из сети и дескриптор 1 передает данные в сеть. Также tcpserver устанавливает значения нескольких переменных окружения.
Как и некоторые другие экстремально компактные программы, tcpserver и fnord следуют так называемому UNIX-way и умеют выполнять лишь одну задачу, зато делают это хорошо. Демон tcpserver слушает указанный порт, и для каждого входящего соединения (на каждый HTTP-запрос) вызывает отдельный экземпляр fnord, который читает содержимое HTTP-запроса на stdin и возвращает результат (HTTP-заголовки и тело ответа) на stdout. Запускается веб-сервер, к примеру, по адресу localhost:8888 и для текущей директории следующим образом:
tcpserver localhost 8888 /usr/sbin/fnord .
В консоль будет выводиться лог всех соединений.

Быстродействие

И в самом деле, легковесный веб-сервер может работать без какой-либо настройки и без конфигурационного файла, но что же будет с производительностью? Для ответа на интересующий нас вопрос сравним веб-сервера по количеству обрабатываемых в секунду запросов (TPS) в зависимости от размера запрошенного файла при 50-ти конкурентных клиентских подключениях. Для каждого вебсервера мы ограничимся конфигурацией по умолчанию из дистрибутива debian squeeze, для работы на одном процессорном ядре это достаточно хороший выбор. Так как размер HTTP заголовков составляет сотни байт, то и тестирование передачи файлов размером менее килобайта практического смысла не имеет.Для тестирования я выбрал несколько популярных веб-серверов. Скрипт для тестирования можно взять по ссылке dload.tcl. Вот какие результаты были получены:
File sizeAolserver/4.5.1Apache2/2.2.15Fnord/1.10Lighttpd/1.4.26Nginx/0.7.65
1000812633682853885
5000724574674843959
10000719629671840866
50000556517608766853
100000386469557665742
500000163296333321305
100000079127135156147

или на графике


Потратив лишь минуту своего времени на запуск веб-сервера fnord, мы получили результат на уровне больших и сложно настраиваемых решений. Не будем углубляться в рассмотрение среднего времени ожидания обработки запроса, замечу лишь, что для связки tcpserver + fnord этот параметр на уровне результатов Nginx и Lighttpd (подробности смотрите в файлах dload.log в прикрепленных к статье ресурсах). Думаю, для многих такой результат оказался неожиданным. Оставляя "за бортом" философские вопросы, мы приходим к следующему выводу - оправдано использование или экстремально простого веб-сервера для статики (такого, как fnord и некоторые другие), или же следует проводить комплексное тестирование и всерьез заниматься настройкой, прежде чем выбирать одно из более сложных решений, таких как Nginx, Lighttpd, etc.

Безопасность

В целях защиты нашей системы крайне желательно, чтобы веб-сервер не имел возможности записи на диск (для защиты от перегрузок при DDOS и взлома через уязвимости в коде работы с файловой системой) и мог запускаться в chroot. При необходимости сохранения лога запросов следует его получать с stdout или в syslog. Перечисленным требованиям удовлетворяет fnord, причем запуск в chroot не требует никаких дополнительных действий. "Большие" веб-сервера придется дополнительно настраивать, чтобы они не пытались писать логи самостоятельно, а поместить их в chroot зачастую непросто.

Оптимизация взаимодействия веб-клиента и сервера - Введение

Всемирная паутина (www) начиналась с полностью статичных веб-ресурсов, так что пользователи могли лишь просматривать предложенные веб-странички и скачивать файлы. Со временем появлялись все более развитые средства взаимодействия с пользователями, начали использовать кукисы (cookie) для идентификации пользователей, предложили формы обратной связи и форумы. Сегодня многие веб-сайты обзавелись базами данных и активно применяют ajax-технологию для удобства посетителей, и для нас стал привычен термин "веб-приложения". Происходящее сравнимо с революционными изменениями, порожденными открытием книгопечатания, и даже более того - ведь теперь не только информация стала как никогда раньше доступной и глобальной, но и каждый ее потребитель легко и быстро может связаться с автором, включаясь таким образом в процесс создания новой информации. Все это здорово, но техническая часть взаимодействия между веб-приложениями и их пользователями производит впечатление чрезвычайно сложного процесса, требующего сложнейших программных решений. Но так ли это на самом деле? В предлагаемой вашему вниманию статье автор постарался показать, насколько просты принципы, лежащие в основе современного веба, и как легко можно стать полноправным участником построения всемирной сети. Печатная машинка делает процесс печати доступным каждому из нас, но большая типография производит впечатление сложного и непостижимого для неспециалиста технологического процесса. Да, технологически типография сложна, но суть ее - быть высокопроизводительной печатной машинкой. Вероятно, уже спустя 10 лет мы вовсе забудем о существовании типографий, поскольку дальнейшее развитие технологий сделает их ненужной ветвью эволюции информационного общества. Ровно так же и в области информационных технологий есть свои рабочие инструменты и есть огромные монстры, причем последние являются лишь данью нашему времени. Для сравнения мы будем упоминать и монстров, названия которых знакомы многим нашим читателям, но главное, постараемся показать основные идеи и те основные инструменты, которые позволяют их воплотить в жизнь. Автор уверен, что статья окажется полезной как начинающим разработчикам, так и профессионалам, поскольку обсуждения многих затрагиваемых здесь вопросов показывают, как мало разработчиков задумываются о том, что они делают, будучи вместо этого всецело поглощены мыслью о том, как это делать.

С чего же начинается построение веб-ресурса? Для создания и отправки созданного цифрового контента клиентам служит программное обеспечение, называемое веб-сервером. Существуют разнообразные веб-серверы, от маленьких и простых до огромных и сложных, к тому же требующих дополнительных внешних программ для своей работы. Выбор веб-сервера задача непростая, и во многих проектах используются разное программное обеспечение для передачи статических, заранее подготовленных файлов, так называемой "статики" и динамически создаваемых данных, или кратко "динамики". Также в некоторых случаях выделяются задачи потоковой трансляции мультимедиа-содержимого и некоторые другие, которые мы рассматривать не будем, поскольку такие вопросы являются узкоспециализированными и выходят за рамки текущей статьи (большинство сайтов работают с таким содержимым ровно также, как с обычной статикой). Ниже будет представлен обзор некоторых популярных решений и предложен миниатюрный и не требующий настройки веб-сервер для раздачи статики, а также технология управления генерацией динамического содержимого. Как будет показано, разница в быстродействии между самыми сложными и самыми простыми решениями часто невелика, в то время как разница между затрачиваемым на их изучение и настройку временем огромна.

Выбор веб-сервера определяется решаемой задачей, или, скорее, должен определяться. На практике большинство разработчиков во всех проектах более или менее успешно работают с тем веб-сервером, к которому привыкли, что может создавать различные проблемы. Такие решения отличает избыточная сложность реализации и настройки, а также производные от этого проблемы с безопасностью, масштабированием и другие. Поскольку по системам подобного рода пишется больше всего обзоров и технических статей, создается ложное впечатление, что это именно то, к чему надо стремиться.

Во многих случаях оптимально и достаточно ограничиться одним из миниатюрных веб-серверов для отдачи статики, технологии CGI для динамики и балансировщика нагрузки, если проект достаточно большой и один веб-сервер не справляется. Далее везде предполагается, что на сервере работает именно операционная система Linux (с ядром 2.6.26 и выше) или другая UNIX-система.

Хотя веб-сервер является необходимым компонентом, зачастую его недостаточно и для оптимизации производительности и времени отклика веб-ресурса применяются еще и так называемые реверс-прокси серверы (обратные прокси), которые представляют собой "единое окно" для доступа всех пользователей к одному или более "спрятанных" веб-серверов. Для рассматриваемой архитектуры существует калька с английского названия фронтэнд (front-end) для прокси-сервера (в общем случае - компонента, непосредственно взаимодействующего с пользователями), и бэкенд (back-end) для компонентов, непосредственно выполняющих обработку запросов, но невидимых для пользователей. Реверс-прокси лишь передают запросы на обработку далее, при этом они могут модифицировать как запрос, так и полученный результат (удалить небезопасные данные или, наоборот, добавить дополнительные данные). Преимущество от работы обратного прокси достигается за счет "умного" управления очередью пользовательских запросов и распределения этих запросов по бэкендам (в том числе, осуществляется балансировка запросов по нескольким одинаковым бэкендам, передача определенных типов запросов нужным бэкендам и обеспечение минимального времени ожидания запросов пользователей в очереди, блокирование сетевых атак многих типов). Для небольших проектов реверс-прокси часто работает на том же физическом сервере, что и бэкенды, и даже в этом случае выгоды от такого дополнительного компонента весьма ощутимы. Из-за того, что пользователь не видит разницы между обращением непосредственно к веб-серверу или к реверс-прокси, во всех случаях установленное на сервере программное обеспечение зачастую называют одинаково - веб-сервер.

На пути между веб-ресурсом и компьютером клиента (которым может быть как настольный компьютер, так и смартфон или другое мобильное устройство) обычно располагаются кэширующие прокси интернет-провайдеров, корпоративных сетей и другие. Задачей кэширующих прокси является сохранение неизменяемых или редко изменяемых файлов на определенный интервал времени. При поступлении HTTP-запроса, кэширующий прокси или возвращает ранее сохраненный результат из кэша, или передает запрос далее (к следующему прокси или непосредственно веб-сервису), а результат выполнения запроса возвращает, притом сохраняет его в кэше, если это разрешается заголовками HTTP-запроса. Дополнительно возможно использование собственного кэширующего прокси. Кроме стандартных преимуществ, свой прокси дает возможность применить нестандартные настройки для более агрессивного кэширования и снижения нагрузки на обработку запросов (но не стоит злоупотреблять нестндартным поведением кэширующего прокси, лучше правильно настроить заголовки кэширования непосредственно в бэкендах).

Грамотный выбор веб-сервера или нескольких серверов, установка реверс-прокси и учет существования кэширующих прокси на пути траффика от веб-ресурса способны кардинально повысить качество работы проекта и снизить нагрузку на серверное оборудование. Минимально необходимым компонентом для своего сайта является только веб-сервер; впрочем, многие хостеры предоставляют веб-сервер и реверс-прокси даже для недорогих тарифных планов.

В качестве критериев оценки мы будем показывать скорость обработки запросов, измеряемую в транзакциях в секунду (TPS - transaction per second). Измерения будут проводиться на моем нетбуке Intel(R) Atom(TM) CPU N450 1.66GHz. Почему именно нетбук? Ну, во-первых, именно на нем я пишу статью и мне это удобно :-) Основная же причина - показанные значения будут достаточно близки к тому, что мы получаем на бюджетных хостингах. Если же вы примените описанные далее методики на хорошем железе, то будете приятно удивлены. Я мог бы провести замеры на топовом "железе" и получить высокие цифры для украшения статьи, но это бы не привело ни к чему иному, как к разочарованию большинства читателей при практическом использовании представленного материала.

Во многих примерах показаны однопоточные обработчики, и вот почему. Специализированный балансировщик запросов выполнит задачу распараллеливания запросов почти всегда лучше, нежели встроенный в веб-сервер модуль балансировки, что, вдобавок, чрезвычайно упрощает логику самого обработчика запроса, делая его однопоточным. Занять все доступные ядра просто, запустив несколько однопоточных обработчиков на разных портах и настроив балансировку входящих запросов по этим портам в реверс-прокси, а масштабирование по числу процессоров/ядер становится наилучшим - линейным.

четверг, 26 мая 2011 г.

Забыл?

Листая блог Навального, нашел вот такую замечательную памятку:


А дело в том, что пришло время спросить за обещанное. Сегодня новые серенады поет другой президент... но тот человек, кто обещал все вышеназванное - и еще намного больше, того гляди с новыми обещаниями на трон усядется.

суббота, 21 мая 2011 г.

Internet Explorer Application Compatibility VPC Image

Обновились образы для тестирования сайтов в ИЕ разных версий. Для конвертации и запуска образов потребуются deb-пакеты unrar, qemu-utils и virtualbox/virtualbox-ose

Скачиваем архивированный образ в формате .vhd (VirtualPc) и превращаем в .vdi (VirtualBox):
unrar e Windows_XP_IE6.exe
mv Windows\ XP.vhd Windows_XP.vhd
mv Windows\ XP.vmc Windows_XP.vmc
qemu-img convert -O raw Windows_XP.vhd Windows_XP.bin
vboxmanage convertdd Windows_XP.bin Windows_XP.vdi

воскресенье, 8 мая 2011 г.

О фреймворках


Нижеприведенные статьи рассказывают, почему _не нужно_ писать фреймворки. Вот зря только автор не пояснил, что лично же он понимает под этим термином, имхо фреймворком здесь называется решение, пригодное для решения задач из существенно разных областей. Но в таком случае очевидно - не стоит ожидать, что создатель фреймворка обеспечит удобное решение задач, о существовании которых он и не подозревает... Про повторное использование кода тема еще более занимательная, потому что нагромождение параметров и слоев логики это вовсе не то, что стоит создавать (работали у меня программисты, которые самозабвенно пытались сделать универсальные построители веб-форм и проч., а в итоге добавление одного поля в одну из веб-форм проекта могло у них занимать день-два). На самом деле, повторно использовать можно и нужно оформленные в функции/классы/etc. блоки кода, решающие конкретную задачу!

Миф о фреймворках


воскресенье, 1 мая 2011 г.

Кондиционер для дома


Давно не писал в блог, поскольку был занят всякими личными делами и работой. А вот в праздники есть время кое о чем рассказать.

Жаркое лето 2010 мне довелось пережить в панельной девятиэтажке. За город выбирался часто, но там оказывалось немногим лучше - дым от лесных пожаров стелился по земле, ночью не продыхнуть. В городе тем более дышать было нечем - жарко и дым, дым... Мои сиамские кошки поседели, а в нетбуке покоробился кулер и начал заунывно трещать. От задымления спасался воздухоочистителем Bork, но уже стало понятно, что без кондиционера не обойтись.

В декабре 2010 начал выбирать кондиционер - вроде бы, самое время, спрос рухнул и цены тоже. Выбор оказался делом не простым, вдобавок, неожиданно выяснилось, что и зимой обзавестись кондиционером совсем не просто, ибо их не в сезон нет в продаже. К февралю-марту начались поставки кондиционеров, но установка грозила затянуться на несколько месяцев - не я один начал заранее готовиться к лету. Что же, после решения всех означенных проблем возникли вопросы с эксплуатацией - казалось бы, установил и радуйся, но на деле для действительно комфортного использования нужно соблюсти ряд условий. Мои друзья также решили поставить себе кондиционеры, и возникла идея собрать воедино известные нам сведения о выборе, установке и эксплуатации кондиционеров. И начнем мы с рассказа о кондиционерах Panasonic, на которых остановился выбор мой и нескольких моих товарищей.

Кондиционеры Panasonic

Почему именно Панасоник? Все просто - качественные кондиционеры (у инверторных моделей компрессор японский, 5 лет гарантии) по разумной цене и с сервисом в Нижнем Новгороде. Кроме того, знакомые, занимающиеся поставкой и установкой кондиционеров, также рекомендовали Панасоник. В "знакомых" офисах, где стоят Панасоники, ими вполне довольны, хотя встречаются некоторые жалобы, которые, как выяснилось, связаны с неправильной установкой (об этом ниже). Возможности по очистке воздуха стали дополнительным аргументом в пользу выбора именно этой марки. Посмотрев на модели от производителей более высокой ценовой категории, ощутимых преимуществ не увидел, имхо они просто добавляют "плату за брэнд".

Примечание: за последние месяц-два кондиционеры подорожали примерно на треть, приведу цены на 1 мая 2011:
  • сплит-система CS/CU-YW7MKD - 19 600 руб.
  • сплит-система CS/CU-YW9MKD - 22 680 руб.
  • инвертор Deluxe CS-E7MKD/CS-E7MKD - 38 900 руб.
  • инвертор Deluxe CS-E9MKD/CS-E9MKD - 39 280 руб.
Поскольку компрессоры для инверторов делаются в Японии, то после землетрясения и цунами в Японии цены уверенно растут. Для сравнения, в феврале стоимость Deluxe CS-E7MKD/CS-E7MKD равнялась 29 490 руб. Стоимость установки тоже увеличилась с 6 000 руб. до 7 500 руб. - из-за подорожания расходных материалов, но тут цунами уже ни при чем, похоже, что это "родная" российская инфляция...

В 2011 году кондиционеры стали весьма "продвинутыми" устройствами и умеют как охлаждать, так и обогревать (так называемые модели "тепло-холод"). Когда-то в древности (несколько лет назад и ранее) производились кондиционеры, не умевшие обогревать, но сейчас они уже повывелись, и видимо, окончательно. Из университетского курса термодинамики я помню, что эффективность обогрева кондиционером намного выше, чем простым нагревателем, потому из соображений экономии электроэнергии (и существенной экономии) умение кондиционера работать в режиме обогрева весьма полезно. Инверторные кондиционеры более экономичные (обещана экономия до половины электроэнергии), позволяют поддерживать ровную температуру в помещении, и тихие (хотя и не инверторные модели 2011 года работают тихо, по крайней мере, "на слух" разницы нет), также оснащаются неплохими воздушными фильтрами и прочими опциями, плюс к тому, инверторная модель может работать даже в мороз, что при недостатке отопления бывает необходимо (вообще-то этого делать не рекомендуется, но кого это останавливает). Технически инвертор отличается тем, что может регулировать мощность охлаждения, и ему не нужно постоянно включаться-выключаться, что и является основной причиной износа компрессора "обычных" моделей. Также инверторный кондиционер способен в несколько раз быстрее установить в помещении заданную температуру. Помня к тому же о дыме от пожаров, мы с товарищами обзавелись инверторными моделями с хорошими воздухоочистителями.

Приведу пару ссылок для ознакомления с возможностями (в инструкции очень уж все кратко изложено, оказалось проще разобраться по указанным обзорам):
Инверторные кондиционеры Panasonic: легкая победа над жарой
Инверторный кондиционер Panasonic S-XE12JKDW: спасение от жары и холода

На комнату площадью до 20 кв. м. достаточно модели CS/CU-YW7MKD или Deluxe CS-E7MKD/CS-E7MKD, на 20 с небольшим кв. м. - CS/CU-YW9MKD или Deluxe CS-E9MKD/CS-E9MKD.

Моделей на самом деле много, но практически все определяется площадью помещения и возможностью/желанием покупать инвертор. Можно пригласить установщиков кондиционеров, чтобы они по месту определили, что и как ставить и порекомендовали подходящую модель.
Теперь перейдем к вопросу установки кондиционера. Это намного более важно, нежели выбор той или иной модели - производитель гарантирует качество продукции, но удобство использования определяется почти целиком тем, насколько грамотно произведена установка. Выше я упоминал про жалобы на Панасоники, расскажу подробнее про самую популярную. При выведении стока конденсата через наружную стену при неаккуратном проталкивании трубки наружу она забивается, но сразу этого не заметить - все вроде бы работает. Но если на зиму кондиционер выключить (на пару-тройку месяцев холодов), влажный мусор в отводной трубке ссыхается и образует "затычку", как результат - внутренний блок кондиционера начинает течь... Горе-установщики в таких случаях рекомендуют пролить трубку водой из бутылки... хотя на самом деле ее надо прочистить, к примеру, продуть с помощью баллона со сжатым воздухом. Впрочем, неожиданности могут подстерегать и при правильной установке, особенно, в панельных домах, о чем я еще напишу.

Покупая кондиционер, я задавался вопросом, а нельзя ли его повесить самому. Оказалось, что гарантия дается только при установке сертифицированным специалистом, так что от этой идеи я отказался. И хорошо, потому что при установщику приходится висеть из окна вниз головой с перфоратором и ключами/отвертками. Я даже предложил привязать мастера за ногу к трубе, но он почему-то отказался :) Фото я сделал, себе на память и показать друзьям, кто захочет самолично заняться установкой. Поскольку я знаю специалистов, занимающихся установкой, то мне и друзьям, разумеется, не пришлось месяцами ждать своей очереди (вот уж любят у нас очереди создавать).


Здесь будут фото установки - пока выбираю лучшие, с разгону нащелкал многовато :)


После установки изредка случается, что через некоторое время кондиционер перестает работать, и на нем мигает лампочка таймера. Это решается легко - отключаем питание (выдернуть из розетки или отключить автомат), снова включаем и запускаем в режиме нагрева до максимума ( на моей модели это 30 градусов) на часок. Потом переключаем в режим охлаждения до минимума (у меня это 16 градусов) также на час-два. После описанной процедуры все приходит в норму и работает уже беспроблемно (мне хватило одного такого цикла, а вообще говорят, что может потребоваться два-три раза проделать эту операцию). То ли калибровка датчиков происходит, то ли клапана "тренируются".

В случае установки кондиционера в панельном доме со встроенными в стены батареями может возникать гул при работе. Причем если открыть окно - тихо, внешний блок практически неслышим. Похоже, в бетонной панели есть пустоты, которые и начинают гудеть от вибрации. Явление это редкое, но мне вот так "повезло". В настоящий момент ребята, ставившие мне кондиционер, думают, что с этим делать. Разумеется, сделают резиновые прокладки на крепления, но вряд ли это полностью решит проблему - внешний блок и так не слышно. Говорят, слышали о решении аналогичной проблемы путем высверливания нескольких отверстий в стене и заполнения их монтажной пеной. Что ж, вероятно, заглушив полости, можно действительно избавиться от шума. Будем думать и пробовать, когда найдем решение, расскажу.

Вот я и рассказал, как же происходит выбор и установка кондиционеров. В дальнейшем планирую дополнять сведениями об эксплуатации и что еще покажется интересным. Для покупки и установки обращаться к Игорю по телефону +79202548256 (можно сказать, что по моей рекомендации, будет быстрее и со скидкой).

пятница, 29 апреля 2011 г.

О стартапах

Сегодня все чаще говорят о том, что стартапы - это новая "золотая лихорадка". Не хочу дискутировать на данную тему, поскольку история показывает - кто хочет тешить себя иллюзиями, будет это делать несмотря на любые факты. А вот ссылочку на веселый и поучительный доклад приведу:

Выступление Дэвида Хейнемейер Ханссона перед школой стартапов в 2008 году

Не то чтобы нашел что-то новое, но изложено хорошо и читать интересно.

воскресенье, 24 апреля 2011 г.

О медицине

Стараюсь не писать на социальные темы, но это уже выходит за всякие границы:

Медики поставили диагноз здравоохранению
О «врачах-убийцах»
Рошаль не хочет быть главой Минздрава

Известная картина - каждый чинуша, обнаглев от собственной безнаказанности, запросто позволяет себе нагадить специалисту и даже целой отрасли, которую вообще-то обязан поддерживать и развивать, за что и получает зарплату! Считаю, действия Минздравразвития должны квалифицироваться, как минимум, как саботаж с соответствующими уголовными наказаниями для сотрудников и руководства названного учреждения, а как максимум - геноцид против собственного народа. Ибо использовать данную министерству власть для направленного публичного уничтожения специалистов-медиков - это безумие и тяжкое преступление. Притом делается это ради прямой выгоды - сохранить уютное местечко и зарплату, несмотря на ужасающее состояние в той самой области, за которую данные чиновники несут непосредственную ответственность.

четверг, 7 апреля 2011 г.

Выравнивание числа в SQLite

В очередной раз получаю вопрос, как сделать выравнивание числа в SQLite. Оставляя "за кадром" необходимость это делать в эскулайт, отвечаю - это сделать несложно, вот пример:

sqlite> create table a(val integer);
sqlite> insert into a(val) values(1);
sqlite> insert into a(val) values(10);
sqlite> insert into a(val) values(100);
sqlite> insert into a(val) values(1000);
sqlite> select substr('0000000',1,7-length(val))||val from a;
0000001
0000010
0000100
0001000

четверг, 10 марта 2011 г.

Чудеса яваскрипт

Спасибо ixti за следующую ссылку:

i am myself but also not myself:

var foo = [0];
console.log(foo == !foo);
console.log(foo == foo);

Если кто не догадался, в обоих случаях результатом будет true.

И "на закуску":
all your commas are belong to Array

понедельник, 28 февраля 2011 г.

О программистах

— Знаешь, чем отличается хороший программист от программиста-профессионала?
— Чем?
— Хороший программист пишет хороший код, когда у него хорошее настроение, а профессионал пишет хороший код всегда.

Авторство, как водится, неизвестно :-)

На правах физика добавлю еще сказанное некогда Эйнштейном:
Для нашей работы необходимы два условия: неустанная выдержка и готовность всегда выбросить за борт то, на что ты потратил так много времени и труда.

суббота, 19 февраля 2011 г.

Android SDK on debian squeeze host

See common instructions here: Installing the SDK

$ sudo aptitude install eclipse libswt-gtk-3.5-java

$ ./android --verbose update sdk
No command line parameters provided, launching UI.
See 'android --help' for operations from the command line.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no swt-pi-gtk-3550 or swt-pi-gtk in swt.library.path, java.library.path or the jar file
 at org.eclipse.swt.internal.Library.loadLibrary(Unknown Source)
 at org.eclipse.swt.internal.Library.loadLibrary(Unknown Source)
 at org.eclipse.swt.internal.gtk.OS.(Unknown Source)
 at org.eclipse.swt.internal.Converter.wcsToMbcs(Unknown Source)
 at org.eclipse.swt.internal.Converter.wcsToMbcs(Unknown Source)
 at org.eclipse.swt.widgets.Display.(Unknown Source)
 at com.android.sdkmanager.Main.showMainWindow(Main.java:297)
 at com.android.sdkmanager.Main.doAction(Main.java:265)
 at com.android.sdkmanager.Main.run(Main.java:99)
 at com.android.sdkmanager.Main.main(Main.java:88)

$ sudo ln -s /usr/lib/jni/libswt-gtk-3555.so /usr/lib/jni/libswt-gtk-3550.so
$ sudo ln -s /usr/lib/jni/libswt-pi-gtk-3555.so /usr/lib/jni/libswt-pi-gtk-3550.so
$ ./android --verbose update sdk
No command line parameters provided, launching UI.
See 'android --help' for operations from the command line.

See Android Debug Bridge and Developing on a Device
$ ./adb devices
List of devices attached 
???????????? no permissions

$ lsusb|grep LG
Bus 001 Device 027: ID 1004:618e LG Electronics, Inc. Ally/Optimus One/Vortex (debug mode)

# add new UDEV rule as
$ cat /etc/udev/rules.d/51-android.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="618e", MODE="0666", OWNER="username"
sudo chmod a+r /etc/udev/rules.d/51-android.rules

$ sudo /etc/init.d/udev restart

$ ./adb devices
List of devices attached 
80A354043043696220 device

$ ./adb -s 80A354043043696220 install test.apk 
630 KB/s (196460 bytes in 0.304s)
 pkg: /data/local/tmp/test.apk
Success

Device list in DDMS is empty now. See debian bug #560044 here: sun-java6-jre: net.ipv6.bindv6only=1 breaks java networking. Well, we may force ipv4 usage for java to fix the problem:
$ cat /etc/sysctl.d/bindv6only.conf
net.ipv6.bindv6only = 0

$ sudo invoke-rc.d procps restart

воскресенье, 6 февраля 2011 г.

Что хорошего в jQuery 1.5

Анонс: Состоялся релиз jQuery 1.5

То, чего мы так долго ждали, свершилось:
jQuery Deferred Object (подробное описание) и Использование Deferred объектов в jQuery 1.5 Заметим, что теперь обработчики можно назначать цепочками, это радует.

Также стоит глянуть официальную документацию, грепнув по номеру версии 1.5:
jQuery.ajax()

Из фильтров, конверторов и транспортов меня лично заинтересовали конверторы, а подробное описание всего перечисленного есть здесь:
Extending Ajax

На тестовом проекте уже обкатал новые возможности - кода стало меньше, и читается он легче, профит. Что касается скорости работы - визуально разницы не заметил, поскольку и предыдущая версия jQuery быстро работает, тем не менее, приятно, что добавлены различные оптимизации.

пятница, 4 февраля 2011 г.

Looking Ahead to Tcl 8.6 Jeff Hobbs

Про тикль 8.6, немного о бизнесе:
Looking Ahead to Tcl 8.6 Jeff Hobbs

Похоже, 8.7 все-таки будет, прежде чем появится версия 9.

воскресенье, 23 января 2011 г.

Об увлечениях

Из книги Алдо Леопольда "Календарь Песчаного графства":

По-моему, нет ошибки опасней, чем проповедовать свои увлечения людям, у которых их нет. Это значит навязывать их, а навязанное увлечение бессмысленно и бесполезно по самой своей идее. Не вы ищете для себя увлечения, оно находит вас. Рекомендовать увлечение столь же рискованно, как рекомендовать жену,— вероятность счастливого исхода в обоих случаях примерно равна.

четверг, 20 января 2011 г.

FTS3 Snowball Stemmer

Итак, поддержка стеммеров snowball для SQLite:

http://sqlite.mobigroup.ru/wiki?name=FTS3+Snowball+Stemmer

Пример использования:

CREATE VIRTUAL TABLE fts USING fts4(text,TOKENIZE icu russian);
insert into fts (text) values ('Нафига');
insert into fts (text) values ('попу');
insert into fts (text) values ('наган');
insert into fts (text) values ('если');
insert into fts (text) values ('поп');
insert into fts (text) values ('не');
insert into fts (text) values ('хулиган');

select * from fts where fts match 'поп';
попу
поп
sqlite> select * from fts where fts match 'нафиг';
Нафига

Примечание: аналогично можно использовать и fts3 виртуальные таблицы, но рекомендуется переходить на fts4.

вторник, 11 января 2011 г.

Определение byteorder

int main(int argc, char *argv[])
{
 int test = 1;

    if ( (((char *)(&test))[0]) == 1)
    {
         printf("NDR (little_endian)\n");
        return 0; //NDR (little_endian)
    }
    else
    {
         printf("XDR (big_endian)\n");
        return 1; //XDR (big_endian)
    }

}

Пересчет координат с некоторых судовых навигаторов

int main(int argc, char *argv[])
{
 double xpos = 4784270;
 double ypos = 7803506;

 double RadToDeg = 57.2957795132;
 double DegToRad = 0.0174532925199;
 double b = 6356752.3142;
 double PI = 3.141592654;
 double HALF_PI = 1.570796327;

 double MerToGeoLong = xpos * RadToDeg / b;
 printf("GeoLong = %f\n",MerToGeoLong);

 double MerToGeoLat = RadToDeg * (2 * atan(exp(ypos / b)) - HALF_PI);
 printf("GeoLat = %f\n",MerToGeoLat);
}

(C) Alexey Pechnikov aka MBG, mobigroup.ru