суббота, 27 марта 2010 г.

[life.humour] Типа крутой номер

Это авто припарковано в двух минутах ходьбы от офиса:

Владелец данного авто, может, и нервный, но крутизны ему не хватило – спереди обычный регистрационный номер.

пятница, 26 марта 2010 г.

[prog] Торчащие наружу Eclipse-овые уши

IBM очень активно спонсирует разработку Eclipse. Поскольку не менее активно использует созданные в рамках Eclipse разработки. Вот, например, при запуске IBM WebSphere MQ Explorer-а гордо заявляется о том, что он построен на базе Eclipse:

Но даже если кто-нибудь в этом усомнится, ему напомнят об этом в диалоге настроек MQ Explorer-а:

Лично мне показалось ненормальным наличие рядом со специализированными настройками MQ Explorer-а еще и настроек Ant-а, компилятора Java, дебаггера, редактора, средств работы с CVS и прочую IDE-шную лабуду. Т.е. я понимаю, что все это пошло “в нагрузку” к Eclipse-овскому ядру. Но все равно как-то несолидненько.

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

А про Eclipse, похоже, уже можно шутить как про Emacs: хорошая операционка – этот ваш Eclipse, туда бы еще текстовый редактор нормальный ;)

четверг, 25 марта 2010 г.

[prog] Berkeley DB 5 может мимикрировать под SQLite

Компания Oracle анонсировала выход Berkeley DB 5 – теперь она полностью называется Oracle Berkeley DB 11g Release 2 (eao197: ну вот, попала разработка под крыло Ынтырпрайзной компании и получила помпезное название). Вот некоторые подробности на русском языке на сайте opennet.ru.

Для меня самое интересное – это то, что Berkeley DB 11gR2 теперь поддерживает SQLite-овский SQL API. И, по заявлению Oracle, приложения, которые раньше работали с SQLite теперь смогут работать и с BDB. Имхо, очень разумный ход. Хотя я не очень представляю, как идеология key-value хранилища ложиться на SQL. Если найдется время нужно будет глянуть.

Так же заявлено, что для BDB подготовлены JDBC и ODBC драйверы. Что приятно, можно будет попробовать с BDB работать через OTL.

Disclaimer: сам я в реальных проектах BDB не применял – приглядывался несколько раз, но в конце-концов отказывался либо в пользу своих велосипедов, либо в пользу SQLite. Но по опыту работы с первыми версиями Subversion, которые в качестве хранилища репозиториев могли использовать только BDB, о бесплатной версии BDB у меня сложились негативные впечатления – слишком уж часто рапозитории падали насмерть и восстанавливались только из архивных копий.

среда, 24 марта 2010 г.

[prog.humour.vulgarity] Ща спошлю на тему зачатия языка программирования

Предупреждение: в основном тексте заметки присутствует нецензурная лексика.

На RSDN есть такой краеугольный, основополагающий, я бы сказал, персонаж – VladD2. Иногда он выдает перлы, достойные попасть под стекло и на стенку. Вот, очередной:

И вообще, я не верю в языки проектируемые в теории. Язык как ребенок. Его нужно зачать, выносить, родить и воспитать.

[prog] Еще несколько слов о TLV

Поскольку в одной из предыдущих заметок тема TLV была затронута, скажу еще пару слов.

TLV-представление можно, условно, разделить на два типа:

1. С фиксированными размерами полей Tag и Length. Например, Tag – 2 байта, Length – 4 байта. Это очень простой тип TLV. Его главная проблема – в выборе подходящего размера полей. Например, если под Length отвести 4 байта, а значения не будут превышать 100 байт длиной (а то и 20 байт, что довольно часто происходит в моих задачах), то на каждый TLV будет приходиться три лишних байта в Length. На одном-двух TLV это, может быть, еще и не заметно. А вот на 10-20 TLV полях в PDU и сотнях тысяч PDU – эти лишние байты стремительно складываются в килобайты, а потом и в мегабайты никому не нужных нулей.

2. C “плавающими” размерами полей Length и/или Tag (обычно плавает размер Length). Например (если мне не изменяет склероз, так происходит в ASN.1), если длина Value не превышает 127 байт, то под Length отводится один байт (старший бит у него нулевой). Если же длина Value > 127, то первый байт Length хранит количество байт, необходимых для двоичного представления длины Value. И в первом байте Length старший бит установлен в единицу – это и есть признак того, что Length длиннее одного байта. В таком представлении значение 128 будет представлено двумя байтами: 0x81, 0x80. А значение 256 – тремя: 0x82, 0x01, 0x00. В ряде случаев плавающим делается еще и значение Tag, хотя это усложняет, на мой взгляд, работу с TLV.

Имхо, TLV представление достаточно удобно, когда нужно сериализовать набор объектов. Но здесь, по крайней мере по моему опыту, следует применять двухпроходную схему. На первом проходе вычисляется общий размер будущего представления объектов и выделяется необходимая память. На втором проходе в выделенный буфер (поток) записываются теги, ранее вычисленные длины и значения.

Однако, если же нужно оформлять в TLV уже готовые блоки данных (т.е. есть готовый байтовый массив, который нужно обрамить TLV), то здесь могут начаться проблемы с производительностью. Если в вашем распоряжении нет средств ввода-вывода с поддержкой gather-scatter, то придется выполнять копирование уже готовых данных в новый буфер, в котором будут присутствовать Tag и Length. В некоторых случаях (когда речь будет идти о передачи больших объемов данных) такое копирование обойдется дорого.

[life] Страшное дело

Минут сорок назад раздался звонок в дверь. Жена открыла. Там соседка с этажа выше. Сразу начала орать: “Вы что сидите? У вас пожар – весь дом в дыму, а вы ничего не делаете!”

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

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

Тут подтянулись соседи, начали звонить в тамбур. Оказалось, что в одной из тех квартир хозяйка находится дома, но и она ни сном, ни духом – у нее тоже ничем не пахнет. А из-за двери второй квартиры действительно пробивается легкий дымок.

Буквально через пару минут приехали пожарные. Дверь открыли, оттуда повалил сизый дым, на площадке стало ничего не видно. Только силуэты снующих туда-сюда пожарных в масках.

Насколько сейчас известно, никто не пострадал, в квартире никого не было. Горела кровать (ее выбросили из окна – остов обгоревший, матрас, похоже, выгорел полностью).

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

Такие, мля, дела. Когда дым валит столбом из дверей соседней квартиры, а потом узнаешь, что огонь горел буквально за стеной твоей детской – это э… несколько бьет по мозгам.

вторник, 23 марта 2010 г.

[prog] Забавный баг при реализации TLV unpacker-а

Есть такой удобный формат для организации бинарных данных – TLV (Tag-Length-Value или Type-Length-Value). Его смысл в том, что каждая порция данных предваряется двумя обязательными полями – Tag и Length. Поле Tag содержит целочисленный идентификатор, который указывает, какой смысл несут данные. Поле Length содержит длину данных в байтах. Ну а дальше идут сами данные.

Удобство этого формата в том, что парсер может ничего не знать про содержимое некоторых блоков данных. Парсер считывает Tag и Length. Если значение Tag ему известно, то он обрабатывает данные. Если не известно, то следующие Length байт просто пропускаются. Благодаря этой схеме протоколы на основе TLV очень легко расширяются, сохраняя при этом совместимость с предыдущими версиями. Например, в какой-то PDU (Protocol Data Unit, элемент прикладного протокола, например, сообщение протокола) можно добавить новое поле, и старые клиенты будут его просто игнорировать.

Так же TLV удобен при передаче по потоковым коммуникационным каналам, например, по потоковым TCP/IP сокетам. Ведь в TCP, например, если отправитель отсылает 32K одной операцией write, то получатель может вычитать их не за одно обращение к read, а за два – первый раз, скажем, придет 28K, затем оставшиеся 4K. Вот с TLV-протоколами такая передача данных очень удобна – получатель всегда может определить, получил ли он весь пакет или нужно еще подождать. (С другой стороны, при отправке нужно сначала длину подсчитывать и в начало блока данных записывать Tag+Length, что может негативно сказываться на производительности, но это уже другой вопрос).

TLV-представление имеет очень широкое распространение. Так, ASN.1 BER – это TLV. Да и в Google Protobuf, AFAIK, так же используется принцип TLV.

Ну а теперь к сути повествования. Последние дни делал библиотеку для поддержки простого протокола для взаимодействия с клиентом. Упаковка сообщений выполняется в TLV. При распаковке обнаруживается интересный эффект – упаковывался объект сообщения A, а распаковывается объект сообщения B. При этом ошибок распаковки не возникает – тишь да гладь.

Ларчик, как водится, открывался просто – в парсере для нескольких Tag-ов по ошибке была зарегистрирована одна и та же фабрика (т.е. вместо фабрики объектов A регистрировалась фабрика объектов B). Ну это ладно, до этого я быстро додумался.

Озадачивало меня другое – почему при чтении объектом B полей объекта A не происходит никаких ошибок? Сообщения-то разные, и имеют только одно общее поле. Все остальные поля совершенно разные. Но объект B как-то умудряется их проглатывать, даже не поперхнувшись…

А дело как раз в расширяемости основанных на TLV протоколов :) Объект B, видя во входном потоке чужие поля (поля объекта A) просто игнорировал их, считая, что это новые опциональные поля о которых он не знает и знать не хочет.

Вот так вот – за что боролись, на то и напоролись :)

PS. А unit-тесты рулят!

понедельник, 22 марта 2010 г.

[life.humour] О романтичности фраз на иностранных языках

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

Но только в том случае, если ты не понимаешь, что там говорят. А вот если понимаешь, то может случиться как с композицией Liama из музыкального сопровождения представления La Nouba (Цирк Солнца). Шок, в который я был повергнут не описать :)

Так что слушаем сами (надеюсь, меня не посадят за нарушение авторских прав).

PS. Само представление я не смотрел, так что не знаю, насколько эти фразы там в тему. Кстати говоря, текста песни я так же не понимаю, может там все еще забористей ;)

[prog] Как не нужно писать bat-файлы под Windows

Пару недель назад поставил себе Scala 2.7.7 “чисто попробовать” – пришлось исправлять евоный scala.bat-файл. Поматюгался на Unix-овых ламеров, которые под Windows фишку не рубят, да и забыл, не до Scala стало. А надысь потребовалось Maven2 себе поставить. И, сюрпрайз, сюрпрайз, там в mvn.bat точно такие же проблемы!

Дело вот в чем: со времен Windows 95 (когда мелкомягкая корпорация заложила очередную мину пользователям – разрешила пробелы в именах файлов) имена приходится заключать в кавычки для того, чтобы защититься от пробелов. Например, если в текущем каталоге есть файл с именем “tasks and plans.txt”, то чтобы просмотреть его содержимое в командной строке нужно будет вводить:

type “tasks and plans.txt”

или

notepad “tasks and plans.txt”

но не:

type tasks and plans.txt

поскольку в последнем случае type будет получать не один аргумент, а три -- “type”, “tasks”, “plans.txt”.

Авторы bat-файлов для Scala и Maven2 решили защищаться от пробелов в именах файлов по полной программе. Например, им нужно проверять значение переменной среды JAVA_HOME. Но, поскольку внутри ее значения могут быть пробелы, то проверку, по их замыслу, обязательно нужно защитить кавычками:

@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome

Но ирония в том, что это работает только для случая, когда в JAVA_HOME пробелов нет. А вот если есть, тогда указанный if раскрывается во что-то такое:

@REM ==== START VALIDATION ====
if not ""c:\Program Files\Java\jdk_16"" == "" goto OkJHome

И при исполнении bat-файла возникает ошибка, поскольку командный процессор видит набор независимых друг от друга фрагментов – “”, c:\Program, Files\Java\jdk_16“”. А возникает эта ошибка из-за того, что в JAVA_HOME уже есть свои кавычки вокруг значения. Поэтому лишняя перестраховка и обрамление %JAVA_HOME% дополнительными кавычками приводят к проблемам.

Пришлось править чужие bat-файлы вот так:

@REM ==== START VALIDATION ====
if not %JAVA_HOME%__ == __ goto OkJHome

воскресенье, 21 марта 2010 г.

[life.photo] Натюрморты на темном фоне Владимира Репкина

Жанр натюрморта для меня один из самых загадочных. Вот как этих фотографиях Владимира Репкина (к сожалению, скончавшегося в 2008-м году) – вроде бы цветы как цветы, но почему-то завораживают.