Общее·количество·просмотров·страницы

Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи

Архив блога

среда, 22 декабря 2010 г.

Файловая система Unix

Рассмотрим подробно Filesystem Hierarchy Standard - описание файловой системы Unix-подобных систем.

Файлы можно разделить на 4 категории: разделяемые/неразделяемые (shareable/unshareable) и статические/изменяемые (static/variable).

Static shareable:
/usr
/opt

Static unshareable:
/etc
/boot

Variable shareable:
/var/mail
/var/spool/news

Variable unshareable:
/var/run
/var/lock

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

В корневой папке (/) содержатся следующие символьные ссылки или каталоги:

  • bin - необходимые исполняемые файлы для команд

  • boot - статические файлы для системного загрузчика

  • dev - файлы устройств

  • etc - специфичная для данного хоста конфигурация

  • lib - необходимые системные бибилиотеки и модули ядра

  • media - точка монтирования для сменяемых носителей

  • mnt - точка монтирования для временной файловой системы

  • opt - дополнительное ПО

  • sbin - необходимые системные исполняемые файлы

  • srv - данные для сервисов, предоставляемых системой

  • tmp - временные файлы

  • usr - важный каталог =)

  • var - изменяемые данные



Дополнительно могут быть установлены следующие каталоги (или символьные ссылки):

  • home - содержит домашние каталоги пользователей

  • root - домашний каталог пользователя root



Каталог /bin



Каталог /bin содержит необходимые исполняемые файлы для команд. Каталог должен содержать следующие файлы или символьные ссылки на команды:


  • cat - конкатенация файлов

  • chgrp - меняет группу владения

  • chmod - меняет модификаторы доступа

  • chown - меняет владельца файла и группу

  • cp - копирование файлов

  • date - печать или установка системной даты и времени

  • dd - конвертация и копирование файлов

  • df - отчет по использованию диска файловой системой

  • dmesg - вывод буфера сообщений ядра с стандартный поток вывода

  • echo - печать строки текста

  • false - ничего не делает, возвращает "неуспех"

  • hostname - просмотр или установка имени хоста

  • kill - посылает сигналы процессам

  • ln - создание ссылок на файлы

  • login - вход в сессию системы

  • ls - вывод списка файлов в каталоге

  • mkdir - создание каталогов

  • mknod - создание специальных файлов

  • more - утилита для листания текста

  • mount - монтирование файловой системы

  • mv - перенос/переименование файлов

  • ps - отчет по процессам

  • pwd - печать названия текущего рабочего каталога

  • rm - удаление файлов/каталогов

  • rmdir - удаление пустых каталогов

  • sed - работа с потоками sed

  • sh - командная оболочка

  • stty - печать и изменение настроек терминала

  • su - изменение пользовательского ID

  • sync - сброс буферов файловой системы

  • true - ничего не делает, возвращает "успех"

  • umount - отмонтирование файловой системы

  • uname - вывод информации о системе



Дополнительно в /bin могут быть установлены следующие программы:

  • csh - C-shell

  • ed - редактор

  • tar - архивационная утилита

  • cpio - еще одна архивационная утилита

  • gzip - утилита сжатия от GNU

  • gunzip - утилита разжатия от GNU

  • zcat - утилита разжатия от GNU

  • netstat - сетевая статистика

  • ping - тест сети по протоколу ICMP




Если утилиты gunzip и zcat существуют, то они должны быть символьными линками на gzip.

Каталог /boot



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

Каталог /dev



Содержит файлы устройств. Примеры:

  • /dev/null - null-устройство. Принимает любой вывод, отправленный в файл, всегда возвращает "успех" при записи в него (но реально данные никуда не записываются). Когда данные читаются из него, сразу же возвращает маркер EOF. Иногда на жаргоне его называют "черной дырой".

  • /dev/zero - файл, который возвращает нули (0x00)при чтении из него. При записи в него всегда возвращает "успех", но реально данные никуда не записываются.

  • /dev/random - файл, который служит генератором случайных чисел. Также возможно писать в него (но зачем?). Блокирующий ввод/вывод

  • /dev/urandom - то же самое, что и /dev/random, но ввод/вывод здесь неблокирующий

  • /dev/full - при записи в этот файл возвращается маркер переполнения устройства



Каталог /etc



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

  • csh.login - файл инициализации для C-shell (systemwide)

  • exports - контроль доступа для файловой системы NFS

  • fstab - статическая информация о файловых системах

  • ftpusers - список пользователей и контроль доступа для FTP-демона

  • gateways - список шлюзов

  • gettydefs - настройки терминала для getty

  • group - файл пользовательской группы

  • host.conf - конфигурационный файл хоста

  • hosts - статическая информация о хостах (локальный DNS)

  • hosts.allow - разрешенный список хостов для TCP Wrappers

  • hosts.deny - запрещенный список хостов для TCP Wrappers

  • hosts.equiv - список доверенных хостов для rlogin, rsh, rcp

  • hosts.lpd - список доверенных хостов для lpd

  • inetd.conf - файл конфигурации для inetd

  • inittab - файл конфигурации для программы init

  • issue - сообщение перд логином и файл идентификации

  • ld.so.conf - список дополнительных каталогов, где искать зашаренные бибилиотеки

  • motd - содержит сообщение, которое показывается юзеру после логина

  • mtab - динамическая информация о файловых системах

  • mtools.conf - файл настроек для mtools

  • networks - статическая информация об именах сетей

  • passwd - файл с паролями

  • printcap - база данных системы печати lpd

  • profile - файл инициализации для sh shell login

  • protocols - список IP-протоколов

  • resolv.conf - файл настроек резолвера

  • rpc - список протоколов RPC

  • securetty - контроль доступа TTY для root

  • services - имена портов для сетевых сервисов

  • shells - пути к оболочкам

  • syslog.conf - файл настроек для syslogd



Каталог /home



Содержит домашние каталоги пользователей.

Каталог /lib



Содержит необходимые системные бибилиотеки и модули ядра.

Каталог /media



Точка монтирования для сменяемых носителей. Следующие каталоги или символьные ссылки на каталоги могут содержаться в /media:

  • floppy - флоппи-дисковод

  • cdrom - CD привод


Каталог /sbin



Содержит системные исполняемые файлы.

воскресенье, 19 декабря 2010 г.

Развертывание Apache Cassandra на кластере из двух узлов

В последнее время интерес к NoSQL-решениям в мире веб-разработки только увеличивается. Одним из ярких представителей NoSQL-мира является Apache Cassandra - распределенное масштабируемое хранилище данных. Cassandra изначально была разработана внутри Facebook (где она обеспечивает поиск по сообщениям в Inbox - Cassandra – A structured storage system on a P2P Network - хранит терабайты поискового индекса), но затем передана в Apache Software Foundation. В настоящее время сайт проекта - http://cassandra.apache.org.

В данном посте мы рассмотрим установку Apache Cassandra на кластер из двух машин - одна машина под управлением Ubuntu (IP-адрес в локальной сети - 192.168.1.101), а вторая - под Windows XP (IP-адрес - 192.168.1.100). Будем использовать последнюю версию Apache Cassandra, доступную на момент написания этого поста - версия 0.7.0 RC2.

Скачиваем дистрибутив Apache Cassandra - apache-cassandra-0.7.0-rc2-bin.tar.gz. Распаковываем дистрибутив в каталог, который назовем CASSANDRA_HOME. Заводим переменную среды с таким же именем, т.е. CASSANDRA_HOME. Все эти действия проделываем, разумеется, на двух машинах, которые входят в кластер. Например, на машине с Ubuntu CASSANDRA_HOME=/usr/tools/apache-cassandra-0.7.0-rc2, на машине с Windows XP CASSANDRA_HOME=d:\dev\apache-cassandra-0.7.0-rc2.

Теперь настроим каждый инстанс Кассандры. Открываем файл CASSANDRA_HOME/conf/cassandra.yaml и редактируем следующие свойства:

  • cluster_name - имя нашего кластера. Для всех машин, входящих в кластер, это имя должно быть одинаковым. Поменяем его на что-нибудь более узнаваемое, например, 'JDevNotes Cluster' =)

  • data_file_directories - список каталогов, где хранятся данные. Пока что ограничимся одним каталогом. Этот каталог должен быть предварительно создан и должны быть права на запись в этот каталог. Значение по умолчанию: /var/lib/cassandra/data. На Windows напишем что-нибудь вроде d:\cassandra_data\data

  • commitlog_directory - каталог, куда пишется коммит-лог Кассандры. Этот каталог также должен быть предварительно создан и должны быть права на запись в этот каталог. Значение по умолчанию: /var/lib/cassandra/commitlog. На Windows напишем что-нибудь вроде d:\cassandra_data\commitlog

  • saved_caches_directory - каталог, куда пишется сохраненный кеш Кассандры. Значение по умолчанию: /var/lib/cassandra/saved_caches. На Windows: d:\cassandra_data\saved_caches


  • seeds - список IP-адресов сидов, т.е. узлов, которые распространяют информацию о кластере. Обычно сидами делают от 5% до 30% машин в кластере. На нашем кластере из двух машинок будет всего лишь один сид - это будет машина с Ubuntu. Запишем ее адрес сюда: 192.168.1.101. По-идее, список сидов должен быть одинаков для всех машин в кластере. Так что, повторюсь, на двух наших машинах мы запишем одинаковой значение - 192.168.1.101.


  • listen_address - адрес нода с Кассандрой. По умолчанию - localhost. Это ОК, если только запущен один узел с кассандрой. Но у нас два узла! Так что для каждой машинки в кластере записываем сюда ее адрес. Для Убунты - 192.168.1.101, для машины с Windows XP - 192.168.1.100. Еще важное замечание - сюда нельзя записать адрес 0.0.0.0 - чтобы Кассандра слушала все имеющиеся интерфейсы. Нельзя - потому что для общения узлов кластера используется Gossip. Подробнее см. FAQ - Why can't I make Cassandra listen on 0.0.0.0 (all my addresses)?


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

Во-первых, это порты. Apache Cassandra по-умолчанию использует для работы в кластере два порта - 7000 и 9160. Есть еще порт 8080, который используется для JMX - через JMX можно настроить каждую ноду отдельно.

Порт 7000 используется для общения узлов кластера между собой - это так называемый storage port. Он устанавливается в параметре storage_port. Через него идут на узел команды и данные.

Второй порт - 9160 - это Thrift-port. Он устанавливается в параметре rpc_port. Thrift-port используется для подключения сторонних клиентов к Кассандре.

Параметр rpc_address определяет адрес для Thrift-клиентов. По-умолчанию, используется localhost. Сюда можно записать любой адрес, в том числе и 0.0.0.0 (в отличие от listen_address).

Наконец, рассмотрим параметр auto_bootstrap. Этот параметр по-умолчанию установлен в false. Если он установлен в true, то данная нода с Кассандрой, когда подключается к кластеру, автоматически копирует часть данных к себе с уже запущенных нод. Для сидов нельзя ставить auto_bootstrap в true. Т.е. для нашего кластера на машине 192.168.1.101, которая является сидом, следует оставить auto_bootstrap: false. Для машины же с Windows XP можно (хотя и необязательно) поставить auto_bootstrap: true.

Итак, все необходимые каталоги созданы и соответствующие права на них поставлены, параметры настройки проставлены. Теперь запускаем Кассандру:

./cassandra -f

Опция -f используется, чтобы процесс был запущен не как демон, а как foreground process (не знаю, какой тут перевод подобрать!).

Сначала мы должны запустить сид, т.е. Кассандру на машине 192.168.1.101. После того, как она запущена, подсоединим к кластеру узел 192.168.1.100. Получим следующее сообщение на машине с адресом 192.168.1.101:


INFO 00:20:12,886 Binding thrift service to localhost/127.0.0.1:9160
INFO 00:20:12,888 Using TFramedTransport with a max frame size of 15728640 bytes.
INFO 00:20:12,892 Listening for thrift clients...
INFO 00:22:52,045 Node /192.168.1.100 is now part of the cluster
INFO 00:22:52,838 InetAddress /192.168.1.100 is now UP
INFO 00:22:52,838 Started hinted handoff for endpoint /192.168.1.100
INFO 00:22:52,841 Finished hinted handoff of 0 rows to endpoint /192.168.1.100


Это означает, что две наших ноды успешно сконнектились друг с другом!

Теперь загасим узел 192.168.1.100. На узле 192.168.1.101 получим следующее сообщение:

INFO 00:31:51,004 error writing to /192.168.1.100
INFO 00:31:56,005 InetAddress /192.168.1.100 is now dead.


Полезные ссылки:

Cassandra Wiki: Loading the Config
Cassandra Wiki: Frequently asked questions

четверг, 16 декабря 2010 г.

HyperGraphDB

Borislav Iordanov делает 20-минутную презентацию по архитектуре HyperGraphDB. HyperGraphDB - расширяемое распределенное хранилище для работы с гиперграфами. Гиперграфы широко используются в машинном обучении, AI, моделировании.

Проект выпущен под LGPL, хостится на Google Code. Сайт проекта - http://www.hypergraphdb.org.

вторник, 30 ноября 2010 г.

Установка драйвера MySQL для Python (MySQLdb)

Понадобилось из скрипта на Python обращаться к БД на MySQL - задача стояла распарсить огромную кучу информации и положить результаты в какое-либо хранилище.

Скрипт, который скачивает и парсит данные, я написал на Python за несколько часов. В качестве хранилища была выбрана MySQL. Теперь нужно было найти драйвер мускула для питона. Драйвер называется MySQLdb и поддерживается сторонним разработчиком, а не фирмой MySQL. Дравер лежит по адресу http://pypi.python.org/pypi/MySQL-python. Я взял было последнюю версию драйвера (версия 1.2.3, в этой версии были только исходники) - и обломался, т.к. она никак не хотела компилиться у меня ни на Windows 7, ни на Windows XP (мне пришлось поставить setuptools и MinGW, чтобы поиметь на машине компилятор gcc). Также нужно, чтобы в файлах MySQL были заголовочные файлы (каталог include).

Тогда я решил поставить яйцо - т.е. egg-файл модуля. К сожалению, версия 1.2.3 поставляется только в исходниках, поэтому мне пришлось ставить яйцо версии 1.2.2 (это версия для MySQL 5.0). Egg-Файл можно скачать отсюда - http://pypi.python.org/pypi/MySQL-python/1.2.2 (MySQL_python-1.2.2-py2.5-win32.egg). Забыл добавить, что на машине у меня стоит версия Python 2.5.

Итак, скачав egg-файл, устанавливаем его командой easy_install:

easy_install MySQL_python-1.2.2-py2.5-win32.egg


Получаем вывод:

D:\temp>easy_install MySQL_python-1.2.2-py2.5-win32.egg
Processing MySQL_python-1.2.2-py2.5-win32.egg
Copying MySQL_python-1.2.2-py2.5-win32.egg to d:\python25\lib\site-packages
Adding MySQL-python 1.2.2 to easy-install.pth file

Installed d:\python25\lib\site-packages\mysql_python-1.2.2-py2.5-win32.egg
Processing dependencies for MySQL-python==1.2.2
Finished processing dependencies for MySQL-python==1.2.2


Чтобы работала команда easy_install, необходимо добавить в PATH %PY_HOME%/Scripts

P.S. Для версии Python 2.6 бинарники модуля можно скачать отсюда: MySQL-python Windows 64bit and 32bit distributions

UPDATE:

Для Ubuntu все намного проще. Установка MySQLdb:

sudo apt-get install python-mysqldb

воскресенье, 28 ноября 2010 г.

Модель Мараско, описывающая типы людей

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






Долгие годы наблюдений и размышлений привели меня к убеждению,
что легче в этом разобраться, если упростить задачу. В моей модели есть
три базовых состояния, характеризуемых на идише словами шлеппер,
махер и менш (schlepper, macher, mensch). Сначала я опишу эти состояния
и то, как люди переходят из одного состояния в другое. Затем я объясню,
как можно застрять в одном из предшествующих состояний и как бороть-
ся с такой ситуацией. Кроме того, я поговорю о том, что в различные пе-
риоды своей жизни люди в каждый данный момент могут пребывать
в разных состояниях. Наконец, я обращусь к вопросу о том, как люди коли-
чественно распределяются по разным состояниям и как это учитывать,
живя в реальном мире.

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

Почему это важно? Мы склонны считать, что жизнь – сложное явление,
и вопросам взаимодействия общественных групп в различных контекстах:
семейном, деловом, трудовом и т. д. – посвящена масса научных исследо-
ваний. В большинстве своем они недоступны обычному человеку. Я при-
шел к убеждению, что данная очень простая модель в значительной мере
объясняет явления, наблюдаемые в реальном мире, и позволяет делать оп-
ределенные предсказания. Простая модель, которую людям легко понять
и применить, и которая оказывается действенной в 80% случаев, полезнее,
чем сложная и трудная для применения, которая действует в 95% случаев.


Шлеппер



Начнем с первого состояния. Люди на этой фазе развития в совокупно-
сти называются шлепперами. Слово происходит от глагола «schlep»,
на идише означающего «тащить». В разговорной речи он также означает
«пронести что-либо», например, «пронести вещи через аэропорт». В обиходе
слово «шлеппер» указывает на ленивого и неаккуратного человека, но
я хочу применить его с другим оттенком значения. Для меня «шлеппер» –
это человек, находящийся на первой стадии своего развития.
В буквальном смысле шлеппер – это носильщик. В старые добрые времена
идеальный пример шлеппера являл кэдди – мальчик, таскавший сумку
с клюшками для гольфа. Когда что-то тащишь, не требуется особого напряжения
мысли: ты выполняешь полезную, но преимущественно «черную»
работу, обычно обслуживая кого-то другого. Быть шлеппером не слишком
почетно, но не стоит и недооценивать важность этой работы.
Во-первых, если ты шлеппер, никто не запрещает тебе думать. На самом
деле верно как раз обратное: поскольку работа шлеппера не требует особых
раздумий, во время нее можно думать и учиться. Когда что-то
волочишь, часто рождаются творческие мысли. Например, как бы сделать, чтобы
тратить на эту работу меньше сил? В результате в каменном веке какой-то
шлеппер изобрел колесо. Нежелание рутинно совершать скучную и неинтересную
работу или тратить непомерные усилия для достижения обыденной
цели часто приводит к возникновению идей даже у самого тупого
шлеппера – нужда (ощущаемая через боль или усталость) становится матерью
прогресса. Мой опыт говорит, что люди, которым приходилось быть
шлепперами, часто обнаруживают новые и интересные способы избежать
нудной работы, даже если это касается новой для них области. У них развивается
инстинктивная способность предвидеть возникновение тягомотной
работы и предотвращать это. Из экс-шлепперов, например, получаются
замечательные инженеры.

Вообще говоря, каждому следует пройти через шлепперство. Оно воспитывает
характер, как бы банально это ни звучало. Оно учит нас смирению –
тому смирению, которое говорит: «Если я что-нибудь не придумаю,
то буду тащить лямку всю свою жизнь». У этого явления есть интересные
стороны.

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

Иногда этот хозяин может оказаться действительно глупым – настолько,
чтобы заставлять тебя ишачить больше, чем это необходимо. Иногда он
может еще сильнее отравить тебе жизнь, намеренно проявляя жестокость.
И поскольку тебе предназначено быть шлеппером, у тебя есть две возможности:
продолжать молча «шлепать» здесь или отправляться «шлепать»
в другое место. Третий вариант – поднять шум – обычно оказывается контрпродуктивным,
поскольку шлепперы взаимозаменяемы по определению,
и тем, кто много шумит, быстро находится замена.

Наблюдательный шлеппер обнаруживает некоторые поразительные
вещи. Например, у молчаливого шлеппера развивается эрозия стенки желудка,
и если он способен делать выводы, то постарается изменить свою
работу или социальное положение, чтобы уменьшить переживания. Уходить,
чтобы продолжать тянуть лямку в другом месте (вариант номер два),
обычно смысла не имеет, т. к. это не решает проблему, потому что как все
шлепперы взаимозаменяемы, так и работа для них всюду в принципе одинакова.
Чаще всего получается переход «из огня да в полымя».
Пропускать фазу шлепперства опасно, даже если такая возможность
предоставляется. Правда, кое-кому это удается, например тем, кто родился
в богатой семье. Им никогда не удастся испытать преимущества «шлепперства»,
например радость творчества, когда тянешь лямку, или гордость, испытываемую,
когда удачно что-то дотащишь. В результате им оказывается
неведомо, как живет большинство в этом мире. Слишком многое они считают
само собой разумеющимся и плохо понимают реальность. А если вы
не начали жизнь как шлеппер, то практически невозможно, чтобы вы когда-нибудь им стали.

Но что существеннее всего, вы не получите важных уроков – смирения,
цены заработанного тяжким трудом доллара, органической несправедливости
мира и напряженности жизни рядовых людей. Другой незаменимый
урок дает общение с огромным разнообразием людей, с которыми встречается
шлеппер в реальном мире – ворами, лжецами, мошенниками и теми,
кого в менее политкорректные времена называли «простым народом». А самое
главное, встречаются удивительные люди, которые разглядят в тебе нечто
и подумают: «А что тут делает этот парень? Он явно способен на большее», –
и что-то сделают для тебя. Они становятся нашими наставниками,
тренерами и защитниками, и это один из путей покинуть фазу шлеппера.

Рано или поздно каждый шлеппер должен понять, что его прогресс зависит
от способности выйти из фазы шлепперства. Но для этого требуются
усилия. Можно остаться шлеппером навсегда и винить в этом пороки классовой
системы, рыночный капитализм или что-то иное – все с одинаковой
пользой. Выйти из этой фазы можно, если принять такие меры, после которых
твой начальник скажет: «Послушай, я плачу тебе не за то, чтобы ты сам
таскал мешки! Поищи другого, кто этим займется!» Часто для этого требуется
получить образование, что-то придумать и просто сделать нечто, что покажет
тебя в положительном свете. Необходимы, говоря словами Черчилля,
кровь, пот, слезы и труд.1 Вы должны показать, что можете приносить
пользу на следующем уровне. Этот план состоит из двух частей. Во-первых,
вы должны получить образование, приобрести мастерство, добиться результата,
сделать дело. Затем кто-то, кто обладает влиянием, должен
обратить внимание, что произошли перемены и вы готовы перейти из шлепперов
в следующую фазу. Это те наставники, о которых я говорил выше.

Итак, все мы начинаем как шлепперы. В любой семье дети – это шлепперы.
Можно рассматривать шлепперство как ученичество. Дети учатся
на взрослого. Если они будут внимательны, не погибнут и иногда будут
прислушиваться, то благополучно закончат учебу и перейдут во взрослые.
Иначе они останутся детьми навсегда.

Смиритесь с тем, что в любом занятии – на каждой новой работе, в каждом
новом виде спорта, в каждой новой связи – вы начинаете как шлеппер.
Как долго вы им останетесь, зависит от вас. И помните о необходимости
соблюдать достоинство, пока вы находитесь в учениках.


Махер



Вторая фаза жизни – это фаза махера. Я полагаю, что происхождение
слова связано с глаголом, означающим «делать». Эта вторая фаза самая
длинная и в некотором смысле самая приятная фаза жизни. Махер – тот,
благодаря кому совершаются вещи и происходят события, кто добивается
результатов. Эта фаза чрезвычайно продуктивна, и большинство махеров
получает глубокое удовлетворение от того, чем занимается. Некоторым махерам
это так нравится, что они остаются в этом качестве навсегда, и это не
так уж плохо. Если бы не махеры, мы бы все оставались шлепперами.

Махеры не просто изобретатели, предприниматели, художники и гении,
хотя все эти люди обычно махеры. Махер выделяется тем, что создает
новую ценность и изменяет порядок вещей. Обычно махер ассоциируется
с высокой, не рядовой, продуктивностью. Тот, кто отрабатывает свои восемь
часов и редко задерживается, не махер; это в некотором смысле лишь
продвинутый шлеппер. Нет, махер принадлежит к той категории людей,
про которых часто говорят: «Чтобы справиться с этим, нам нужен настоящий махер!».
Во многих фирмах махеры – это «чудотворцы», те, на ком держится
бизнес. Лакмусовая бумажка для проверки: уберите махера, и организация
не просто сильно пострадает, она просто станет другой.

У махеров есть следующие интересные свойства:
• Обычно они очень сосредоточены, на грани одержимости.
• Они впечатлительны.
• Они ориентированы на результат.
• Они видят цель и могут поймать ее в прицел. Лучше не вставать на
пути между махером и результатом, к которому он стремится.
• Махеры харизматичны – в хорошем и плохом смысле. Отсутствие
у махера харизмы встречается редко, потому что эта черта очень
часто связана с лидерством. Существуют исключения, но достаточно
редко, чтобы останавливаться здесь на них.

Есть и отрицательная сторона. Махеры часто склонны думать, что цель
оправдывает средства. Они бывают совершенно безжалостны. Те, кто сам
щепетилен в отношении чувств других людей, часто прибегают к помощи
махеров, у которых не возникает угрызений совести. Махер нисколько не
заблуждается в отношении того, за что ему платят деньги: за полученный
результат. Но если говорить правду, то махер почти всегда готов работать
бесплатно: успех – это очень сильный наркотик.

Махеры умеют сдерживать себя. Самые способные из них быстро обнаруживают,
что опасно бить слишком много посуды. Настрой против себя
слишком много людей, и ты не сможешь найти себе помощников, даже
среди таких же махеров! Есть очень много противных молодых махеров,
но очень мало противных пожилых махеров. Причина очевидна: махерам
трудно продвигаться вперед, если они не могут сколачивать группы, состоящие
из других махеров. Объем проблем, которые им предлагаются для
решения, растет и достигает такой степени, что единственным вариантом
становится игра в команде. Если махер не в состоянии выработать в себе
искусство общения, необходимое для привлечения в игру других игроков,
он окажется в изоляции, и его обгонят более толковые махеры.

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

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

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

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

В других сферах жизни быть махером – значит быть компетентным,
фактически это означает высочайшую компетентность в работе. Обычно
махер рассчитывает добиться того же в любой сфере жизни. Большое разочарование
он может испытать, если окажется, что его компетентность распространяется
только на одну предметную область. Ergo, многие махеры
становятся узкими специалистами, направляя всю свою энергию в ту область
в которой они сильнее всего. Поскольку по своей природе они склонны
к соперничеству, здесь есть реальная опасность застоя. Если ты лучше
большинства своих коллег, то к чему еще можно стремиться?
Как ни высоко положение махеров, существует еще более высокое состояние.
Слово из идиша, которым оно обозначается – mensch – практически непереводимо.

Менш



Менш – это джентльмен, «утонченная натура». Но этим не вполне передается
чувство, заложенное в фразе: «это настоящий менш!» Сущность
понятия менш» в том, что это человек с всеобъемлющим видением,
склонный к интроспекции и философии и обладающий добротой. Менш
умеет выслушивать и очень хорошо понимает чужую точку зрения.
Следует отметить, что слово Mensch в немецком языке означает, во-первых,
человека и, во-вторых, мужчину. Хотя в таком смысле эта фаза становится
доступной обоим полам, он более расширителен, чем в идише.
На идише не все люди «менши».

Между «махерами» и «меншами» есть большая разница. Во-первых,
махеры обычно резче в общении; менши добродушнее, мягче и спокойнее.
У махеров есть чувство необходимости; у меншей есть чувство неизбежности.
Менш серьезно полагает, что все должно уладиться. Шлеппера часто
считают бестолковым или глупым, хотя вся его вина может заключаться
в невежестве; махера считают толковым или умным; менша всегда считают
мудрым. Вы обращаетесь к махеру, когда надо решить задачу сегодняшнего
дня; вы обращаетесь к меншу, когда требуется перспективное решение.
В каком-то смысле шлеппер не умеет делать ничего, махер – преимущественно
тактик, а менш – стратег.

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

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

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

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

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


Еще о меншах



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

Уже упомянутый психолог Михай Чиксентмихайи описал в своей книге
«Поток: психология оптимального переживания»1 некую модель. По его
теории существует конфликт знаний и навыков мастерства с решаемой
задачей. Если задача слишком проста, людям становится скучно, они
несчастны. Если задача очень сложна относительно компетентности, то люди
напрягаются, испытывая тревогу. В случае разумного компромисса –
не слишком легко и не слишком тяжело – достигается состояние «потока».
Чиксентмихайи называет достижение состояния потока каналом потока,
потому что при этом охватывается некоторый диапазон компетентности
и сложности задач. Поток – это благодатное состояние, в котором велики
достижения и испытывается чувство исключительной удовлетворенности;
спортсмены называют это «нахождением в зоне».

Интересно, что в этой модели шлепперы будут несчастливы, поскольку
постоянно будут ниже канала потока, работая над задачами, которые кажутся
им скучными. Махеры, что очевидно, окажутся в тревоге, потому что
чаще всего будут находиться выше канала потока: для них типично
«превосходить задачи». А вот менши, я думаю, будут счастливы и плодотворны,
потому что часто попадают в канал потока. Если главное – поймать поток,
то менши, похоже, это поняли.

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

Менши – счастливые люди. Их окружают счастливые люди. Они могут
справиться с самыми неприятными неожиданностями в жизни и помочь
другим сделать это. Их жизнь очень целостна и уравновешена, и душа их
в мире.


Распределение людей по группам




На каждые 100 шлепперов приходится 10 махеров и один менш.
Почему шлепперы так многочисленны? Простой ответ можно взять
у Линкольна, который сказал бы: «Бог их любит, поэтому создал так много».
И все-таки кажется, что неудовлетворенность должна была бы рано или
поздно почти всех подтолкнуть к следующей фазе. Увы, это не так.
Во-первых, большую роль играет лень: многие просто не желают делать то, что
позволило бы им подняться. Во-вторых, требуется зрелость: для перехода
в следующую фазу надо изменить отношение к жизни и взять на себя
ответственность за свою судьбу. Проще жаловаться на систему и
невозможность продвижения в ней, чем взять дело в свои собственные руки и
добиться успеха, несмотря на препятствия. Наконец, чтобы продолжить свой
рост, требуется совершить усилие. Выход из зоны шлепперов –
фундаментальная перемена, которой многие боятся, потому что новый образ жизни,
оказывается, лишен простых радостей, доступных шлепперу. Поскольку
ничто не дается без труда, многие шлепперы так и не решаются
преодолеть эмоциональный барьер, что необходимо для перехода в следующую
фазу. Полагаю, что три эти фактора – необходимость жертвовать, зрелость
и фундаментальные перемены в жизни – объясняют, почему шлепперов
так много.

Все это помещено в контекст реального и иногда жестокого внешнего
мира. Мой опыт говорит, что интеллект и талант играют значительно
меньшую роль в продвижении, чем напряженный труд и решительная
позиция. В современной глобальной экономике, как мне кажется,
открываются большие возможности и нет непреодолимых культурных,
социальных или иных барьеров. Если вы уверите себя в том, что всем управляют
внешние факторы, то будете обречены на роль шлеппера. Можно осилить
тех, кто стоит на вашем пути, но никто не перенесет вас через препятствие,
которое вы воздвигли для себя сами. На каждые 10 махеров приходится
100 шлепперов, и это представляется мне невероятной растратой человеческого
капитала. Такое положение кажется мне все более неприемлемым
по мере нашего дальнейшего движения в сторону информационной
экономики. Рабочих мест для шлепперов становится все меньше, но то
отношение к жизни, которое позволило им существовать так долго, остается.

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


Некоторые завершающие мысли по поводу модели



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

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

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

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

суббота, 20 ноября 2010 г.

Покупать будут покупки, а не клики

Покупать будут покупки, а не клики - О том, в какую сторону будет развиваться контекстная реклама и сколько времени инвестору стоит оставаться в соучредителях интернет-проекта, рассказывает Алексей Басов, основатель и генеральный директор сервиса контекстной рекламы «Бегун» и портфельный управляющий фонда «Финам — информационные технологии. Интересное интервью, которое обозначает некоторые тренды в развитии рекламной индустрии.

HighLoad проекты на платформе Google App Engine

Выступление Михаила Кашкина на PyConf Киев 2010

http://app-engine.tumblr.com/post/1611919832

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

Хранилище данных (datastore) - key-value, индексы, долгая запись, приемлемое чтение.
Мемкеш - данные там могут протухать. Данные в мемкеше должны быть слепком данных (копией) в datastore.

Места не должно быть жалко - пусть к нам приходит один и тот же объект, если нужно, мы должны его сохранить хоть в 10 разных видах (проекциях), чтобы имеь возможность быстро его отдать.

Устройство BlobStore:
разделяется на две части - загрузка блоба (объекта) и отдача блоба.
- генерация URL для загрузки объекта
- генерация URL для просмотра (получения) объекта

Google App Engine анонсировала новое API для использования server-push технологии, которое позволяет сильно разгрузить сервер от массы
так называемых poll-запросов, которые периодически проверяют, не появилось ли чего нового на сервере. Это Channel API.

Приемы работы от Михаила Кашкина:
1) Авторизация пользователей - не используются сесиии, вся инфа о пользователе хранится в куках.
2) Активные зоны (36-37-я минута выступления) - часть страницы заменяется уже на клиенте (например, вместо кнопок Авторизация появляется надпись "Привет, Вася, спасибо что залогинились")
3) Отображение аватара человека - аватар хранится в отдельном BlobStore
4) Отображение списка друзей - рендерится весь список друзей, на клиент выдается только дельта
5) Пагинация - непросто решается в БД типа key-value. Используется кнопка "Загрузить еще результаты"
6) Поиск по строке autocomplete -
7) Кеширование страниц - кешируются не только HTML-представления, но также и JSON-представления.

Гугл по письму увеличивает лимиты на CPU, память, запросы.

четверг, 21 октября 2010 г.

Коэффициент корреляции Пирсона (Pearson)

При рассмотрении одной задачки пришлось вспомнить статистику, а именно - что такое коэффициент корреляции Пирсона (Pearsons's correlation coefficient). Пользовался при этом двумя ссылками: Wikipedia: (Pearson product-moment correlation coefficient) и MachineLearning.ru: Коэффициент корреляции Пирсона.

Итак, коэффициент корреляции Пирсона - мера корреляции (линейной зависимости) между двумя выборками X и Y, принимающая значения от +1 до −1 включительно. Другими словами, коэффициент корреляции Пирсона характеризует существование линейной зависимости между двумя величинами. Равенство коэффициента "+1" указывает на строгую прямую линейную зависимость, "-1" - на обратную. Если коэффициент равен нулю, то выборки линейно независимы.

Пусть даны две выборки:

Коэффициент корреляции Пирсона рассчитывается по формуле:

где - это средние значения выборок X и Y.

Слабые стороны этой метрики:

  • неустойчивость к выбросам

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

  • Необходимо понимать различие понятий "независимость" и "некоррелированность". Из первого следует второе, но не наоборот


Ниже показаны примеры выборок и значения коэффициента Пирсона для каждой и зних. Картинка взята из Википедии:

Интерпретация величины коэффициента некоторыми исследователями:




КорреляцияОтрицательноеПоложительное
Отсутствуетот -0.09 до 0.0от 0.00 до 0.09
Малаяот -0.3 до -0.1от 0.1 до 0.3
Средняяот -0.5 до -0.3от 0.3 до 0.5
Большаяот -1.0 до -0.5от 0.5 до 1.0

среда, 20 октября 2010 г.

Паттерн Строитель (Builder)

Строитель (Builder) - порождающий шаблон проектирования, который выделяет процесс создания сложного объекта так, чтобы различные реализации строителя могли бы создавать различные реализации объекта. UML диаграмма паттерна Строитель представлена ниже (взято из Wikipedia):



Объекты на диаграмме:

  • Builder - абстрактный строитель, определяющий интерфейс

  • Concrete Builder - предоставляет конкретную реализацию строителя. Конкретный строитель создает и собирает части объекта в единое целое.

  • Director - класс Директора отвечает за задание корректной последовательности конструирования объекта. Класс получает Конкретного Строителя, как параметр, и выполняет необходимые операции с ним.

  • Product - конечный продукт. Создается Директором с помощью Коннкретного Строителя


Мотивы применения паттерна:

  • алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой

  • процесс конструирования должен обеспечивать различные представления конструируемого объекта


Плюсы применения паттерна Строитель:

  • изолирует код, реализующий конструирование и представление

  • предоставляет полный контроль над процессом создания объекта

  • позволяет независимо изменять ход процесса создания объекта



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

Для чего нужен Директор? Опишем это на примере. Пусть подрядчик (Строитель) строит дом. Подрядчик знает, как нужно делать фундамент, возводить стены, делать стропила и класть крышу. Директор (распорядитель) говорит подрядчику, в какой последовательности это делать: сначала нужно заложить фундамент, затем стены, а после этого сделать крышу. В коде это будет выглядеть так:

public class HouseBuilder {
protected House house;
 
public House getHouse() {
return house;
}
 
public void createHouse() {
house = new House();
}
 
public abstract void buildFoundation();
public abstract void buildWalls();
public abstract void buildRoof();
}
 
public class Director {
public House constructHouse(HouseBuilder builder) {
builder.createHouse();
builder.buildFoundation();
builder.buildWalls();
builder.buildRoof();
return builder.getHouse();
}
}


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

public class HouseBuilder {
protected House house;
 
public House getHouse() {
return house;
}
 
public void createHouse() {
house = new House();
buildFoundation();
buildWalls();
buildRoof();
}
 
protected abstract void buildFoundation();
protected abstract void buildWalls();
protected abstract void buildRoof();
}
 
public class Director {
public House constructHouse(HouseBuilder builder) {
builder.createHouse();
return builder.getHouse();
}
}


В заключении можно добавить, что Строитель часто используется вместе с паттерном Компоновщик (Composite).

суббота, 16 октября 2010 г.

Создание поискового плагина для Mozilla FireFox - на примере CrunchBase

Так как часто смотрю проекты на сайте CrunchBase, то мне удобно вводить свой запрос в поисковый плагин для FireFox. Я хотел было установить себе поисковый плагин для CrunchBase, но с удивлением обнаружил, что такого плагина нет.

Что ж, раз его нет, то что мешает написать его самим? Тем более, что "написание поискового плагина" - это всего лишь создание XML-файла из нескольких строчек.

Итак, создаем файл crunchbase.xml со следующим содержанием:
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/" xmlns:os="http://a9.com/-/spec/opensearch/1.1/">
<os:ShortName>CrunchBase</os:ShortName>
<os:Description>CrunchBase - free directory of technology companies, people, and investors.</os:Description>
<os:InputEncoding>UTF-8</os:InputEncoding>
<os:Url type="text/html" method="GET" template="http://crunchbase.com/search">
<os:Param name="query" value="{searchTerms}"/>
</os:Url>
</SearchPlugin>

Помещаем этот файл в каталог с остальными поисковыми плагинами. У меня на Ubuntu этот каталог находится по следующему пути: ~/.mozilla/firefox/ph10gejb.default/searchplugins, после чего перезапускаем FireFox. Вуаля - в списке поисковых систем появилась еще одна строчка с CrunchBase.

Эти ссылки могут быть полезны по теме "Разработка поискового плагина":
Build Your Own Firefox Search Engine
Learn to make a FireFox Search Plugin, and how to install it! Detailed Tutorial! - Publishing - Pixel2Life

понедельник, 11 октября 2010 г.

Паттерн Одиночка (Singleton)

Шаблон (паттерн) проектирования "Одиночка" реализует математическую концепцию синглетона. В математике, синглетон - множество с одним элементом. Например, {10} - это синглетон, т.е. множество, состоящее из одного элемента - числа 10.

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

Рассмотрим варианты реализации одиночки на Java. При этом будем обращать внимание на многопоточность и связанные с ней возможные проблемы. Изложенное ниже следует статье в англоязычной Википедии Singleton pattern. Также использовались некоторые другие источники.

Самая простая реализация:
public class Singleton {
 
private static final Singleton INSTANCE = new Singleton();
 
// Private constructor prevents instantiation from other classes
private Singleton() {
}
 
public static Singleton getInstance() {
return INSTANCE;
}
}

Эта реализация потокобезопасна. Объект INSTANCE создается тогда, когда класс инициализируется. Например, это может произойти, когда будет вызван какой-нибудь статический метод класса. Конструктор объявляется private, доступ к экземпляру класса возможен только через getInstance(). Такая реализация, однако, может не подойти, если создание экземпляра класса требует много ресурсов. В этом случае нужно подумать об отложенной инициализации синглетона.

Вариант Уильяма Пу (William Pugh)
Это вариант отложенной инициализации (или еще говорят: ленивой инициализации)
public class Singleton {
 
// Private constructor prevents instantiation from other classes
private Singleton() {
}
 
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/

private static class SingletonHolder {
public static final Singleton INSTANCE = new Singleton();
}
 
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
 
}

Эта реализация "ленива" настолько, насколько это возможно. Здесь используется идиома Initialization on demand holder idiom - т.е. отложенная инициализация с использованием объекта-холдера.

Несмотря на отсутствие synchronized в коде, эта реализация потокобезопасна. Такая реализация Одиночки работает на всех версиях Java. Здесь используются та часть спецификации Java (см. 8.3.1.1 static Fields и 12.4.2 Detailed Initialization Procedure), в которой описывается порядок инициализации класса. При инициализации класса Java-машина сама заботится о синхронизации, т.к. нет нужды подставлять использовать synchronized.

Т.к. на внутренний класс SingletonHolder нет ссылок нигде, кроме метода getInstance, то и инциализирован он будет не ранее, чем метод getInstance будет вызван. При такой инициализации Java-машина сама позаботится о синхронизации. Так что этот вариант - пример отличной потокобезопасной реализации паттерна Одиночка.

Реализация с double-checked locking (DCL)
Рассмотрим еще одну реализацию. Эта реализация использует двойную проверку блокировки. Она будет корректно работать в многопоточной среде только начиная с версии Java 5, т.к. в Java 5 была изменена модель памяти. Ранее существовавшая модель памяти не позволяла корректно выполняться такой реализации в многопоточной среде. Вот код:
public class Singleton {
 
// volatile is needed so that multiple thread can reconcile the instance
// semantics for volatile changed in Java 5.
private volatile static Singleton singleton;
 
private Singleton() {
 
}
 
// synchronized keyword has been removed from here
public static Singleton getSingleton() {
// needed because once there is singleton available no need to acquire
// monitor again & again as it is costly
if(singleton==null) {
synchronized(Singleton.class){
// this is needed if two threads are waiting at the monitor at the
// time when singleton was getting instantiated
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

Однако, лучше не использовать double-checked locking. Это старый прием, который был вызван особенностями ранних JVM. Теперь его иногда даже рассматривают как анти-паттерн.

Подводя итоги, можно рекомендовать релализацию синглетона с помощью с использованием объекта-холдера.

Разница в synchronized(this) и synchronized(SomeClass.class)

Рассмотрим, в чем разница между
synchronized(this) {
//some stuff
}
и
synchronized(SomeClass.class) {
//some stuff
}

В Java каждый объект имеет ассоциированный с ним монитор (или lock - объект блокировки). Когда мы пишем такой код:
synchronized(this) {
//some stuff
}

мы получаем блокировку, ассоциированную с объектом, на который указывает this. Когда мы используем такую блокировку, мы подразумеваем, что мы готовы ждать, пока поток, использующий этот монитор, не освободит его. Такую блокировку имеет смысл использовать, если изменяем данные объекта (переменные объекта).

Когда мы пишем такой код:
synchronized(SomeClass.class) {
//some stuff
}
мы получаем блокировку, ассоциированную с объектом SomeClass.class. Такую блокировку имеет смысл использовать, если мы изменяем данные (переменные) уровня класса, т.е. статические переменные.

суббота, 2 октября 2010 г.

Чтение всего файла в массив байтов

Нужно прочитать файл целиком в массив байтов. Например, для текстовых файлов такое нужно, чтобы затем из байтов сделать строку с нужной кодировкой: public String(byte[] bytes, String encoding).

Далее, код функции, которая позволяет считать файл целиком в массив байтов (взято отсюда: Reading a File into a Byte Array):

public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
return null;
}
 
byte[] bytes = new byte[(int)length];
 
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
 
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
 
// Close the input stream and return bytes
is.close();
return bytes;
}

пятница, 1 октября 2010 г.

Задачка: наибольшая возрастающая непрерывная подпоследовательность (longest increasing contiguous subsequence)

Требуется в заданной последовательности найти наибольшую возрастающую непрерывную подпоследовательность. Например, дана последовательность {1,2,3,-1,2,3,4,5}. В этой последовательности наибольшая возрастающая непрерывная подпоследовательность начинается с позиции 4 и имеет длину 4, т.е. это подпоследовательность {-1,2,3,4,5}.

Запишем всю последовательность в массив. Будем последовательно проходить массив. Если элемент массива больше предыдущего, то увеличим счетчик длины последовательности на 1. Если элемент массива меньше или равен предыдущему, то поставим счетчик длины в 1 (т.к. последовательность), и метку начала подпоследовательности поставим равной текущему индексу. При этом проверим, если длина только что окончившейся подпоследовательности больше предыдущей максимальной, то максимальную длину меняем.

Входные данные передаются так: на первой строчке файла стоит кол-во чисел в последовательности. На всех остальных строчках в начале стоит следующее число в последовательности. Пример входного файла:

8
1
2
3
-1
2
3
4
5

Код:

import java.io.*;
public class Problem1 {
 
static int[] a;
static int startIndex;
static int maxLength;
 
static void findMaxIncrSubseq() {
if (a.length==1) {
startIndex = 0;
maxLength = 1;
return;
}
int start = startIndex = 0;
int length = maxLength = 1;
for (int i=1; i<a.length; i++) {
if (a[i] > a[i-1]) {
length++;
} else {
if (length > maxLength) {
maxLength = length;
startIndex = start;
}
length = 1;
start = i;
}
}
}
 
public static void main(String[] args) throws Exception {
FileInputStream fstream = new FileInputStream("in.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
strLine = br.readLine();
int size = Integer.parseInt(strLine);
a = new int[size];
int i=0;
while ((strLine = br.readLine()) != null) {
a[i] = Integer.parseInt(strLine);
i++;
}
in.close();
findMaxIncrSubseq();
System.out.println("Longest increasing contiguos subsequence starts from " + startIndex + " and is of length " + maxLength);
System.out.println("Longest increasing contiguos subsequence:");
for (i=startIndex; i<startIndex+maxLength; i++) {
System.out.println(a[i]);
}
}
}


Пример файла in.txt:

12
1
2
3
-10
5
6
7
8
9
0
1
2


Пример вывода:

>java Problem1
Longest increasing contiguos subsequence starts from 3 and is of length 6
Longest increasing contiguos subsequence:
-10
5
6
7
8
9

Постоянные читатели