Записки программиста, обо всем и ни о чем. Но, наверное, больше профессионального.

2012-01-31

HTML5 file upload

Небольшая подборка сцылок по теме загрузки файлов на сервер:

Загрузка картинок на сервер с использованием HTML5+jQuery+PHP (Drag&Drop)
HTML5 File Uploads with jQuery (сильно смахивает на оригинал предыдущей статьи)
HTML5 File API: множественная загрузка файлов на сервер
plupload.com (народ хвалит, а я предостерегу — память течет и контроля целостности нет).

Для CMS, решения на HTML5+jQuery — самое оно. Перетащи-и-Брось, индикатор загрузки, все это делается легко и изящно.

Кто не спрятался, я не виноват

Странные нынче времена, за товарную контрабанду мы рискуем быть наказанными по административной ответственности, а за хранение (не дай Бог использование) кряков/кейгенов - наступает уже уголовная. Любопытно, чем нанче грозит хранение огнестрельного оружия? Не удивлюсь, если с точки зрения закона это менее вредно обществу, чем хранение zip-архива с вирусней.

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

Правда, учитывая количество времени, потребное на разборы и чистку, проще все архивы (а заодно и рабочие системы) закриптовать наглухо. И вот тут начинается интересное — как это сделать удобно/оптимально.

Для Linux доступна масса средств, лично мне нравится ecryptfs. Под MS Windows все несколько грустнее. Есть практически безальтернативный Truecrypt, все остальные варианты ему уступают так или иначе. И у Трукрипта есть киллер-фича, он может закриптовать системный раздел, но только для MS Windows. В случае, если кроме винды на диске есть еще и Linux, приходится крутиться:

My solution was:
* Encrypt Windows7 system partition using truecrypt, selecting Single boot and overwriting Grub2 loader with truecrypt loader
* Boot Debian from Rescue CD and install grub2 bootloader NOT on MBR but on /dev/sda3 which is Debian / partition (so truecrypt loader was not overrided)
Now while booting truecrypt bootmenu is shown and if I'd access Win7 I'm entering password, but if I'd enter debian (via Grub2) I hit esc key and then truecrypt loader is searching all other partitions for boot loader and finding Grub2 which resides on /dev/sda3 and load system properly.

superuser.com/questions/251109/encrypt-multiple-systems-windows-7-deb
steve-oh.com/blog/index.php/ubuntu-vista-dual-boot-full-encryption-with-truecrypt
truecrypt.org/docs

Лично не проверял, но придется. К тому идет.


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

2012-01-29

История аглицкого языка за 10 минут

Превосходный ролик!
За 10 минут нам в юморной форме рассказывают о наиболее важных эпизодах развития аглицкого.


http://english.oper.ru/news/read.php?t=1051609356

Я тут недавно смотрел Black Adder, там в одной из серий обыгрывался труд составления словаря. В ролике говорится о 9-ти годах и 42000 слов. Книга 8 дюймов толщиной - «невозможно читать, но весма полезна для залезания на верхние полки».
Аткинсон (Black Adder) за одну ночь переписал этот словарь, начиная с «aarddvark» :)

2012-01-28

День выборов

Пестня из кина.

... Но нельзя отрицать, что за время его правления приостановлен развал страны, укрепилось международное положение Германии, стабилизировалась экономика, сократилась безработица, созданы новые молодежные организации, развивается спорт.
...
Я сегодня снова много думал. И пришел к выводу, что буду голосовать за Гитлера.
...
lleo.me/dnevnik/2012/01/27

Если кто срефлексировал — почитайте историю Германии 20-х, 30-х годов 20-го века.


Вспоминается такое:

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

http://www.anekdot.ru/id/308977/

2012-01-27

make it work, make it right, make it fast

Как ты это делаешь — всегда правой.

В сформулированном виде — банальность. Но не каждый может сформулировать — что есть «правильно». Правильно, это когда идет движение к цели согласно ценностям и приоритетам.

... Вот тут всё становится на свои места, особенно если вспомнить не менее известное "make it work, make it right, make it fast" (именно в такой последовательности, и каждое следующее не раньше имеющегося предыдущего). Остается только с виду незаметный, но очень важный вопрос — а что же такое правильно? Вроде всем понятное слово, но каждый под ним понимает что-то свое, обычно интуитивно понимаемое и расплывчатое. Более того, никакого абсолютного "правильно", общего для всех и всегда, нет и быть не может. Тогда что же это?

Я бы определил "правильно" как 3 компонента — цели, ценности и приоритеты. Они неразрывно связаны друг с другом.

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

При той же самой цели, делать что-то можно разными способами. Как выбирается способ? Между задачами соблюдаются какие-то более-менее постоянные ценности, принципы. Например, "деньги не пахнут" или "всё надо делать качественно". Ценности для человека — это то, что значимо, к чему он неравнодушен, на что ему не похуй. То, что можно описать словами "хорошо" и "плохо", в отличие от всех остальных вещей, к которым нет ничего, кроме равнодушия. ...

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

nuclight.livejournal.com/129234

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

UPD.
Отсюда вытекает основная функция начальника/руководителя: подобрать коллектив из людей, ценности которых совместимы; обеспечить понимание и принятие целей и приоритетов каждым участником работ.

2012-01-26

Сотни терабайт

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

Давайте посчитаем. Для начала, узнаем количество тайлов на территорию Москвы.

Исходные данные таковы.
Территория — квадрат со стороной 30 километров.
Всего есть 20 LOD-ов (масштабная линейка из 20-ти ступеней).
Каждый следующий масштаб отличается от предыдущего в два раза, т.е. тайлов на одну и ту же территорию в четыре раза больше (или меньше, если в другую сторону).
Самый крупный масштаб 1 : 1128.497176.
Плотность картинки 96 DPI (дюйм карты насчитывает 96 пикселей).
Тайл — квадрат со стороной 256 пикселов.
Средний тайл весит 0.02 мегабайт. В отличие от остальных данных, этот параметр получен экспериментально и не может быть на 100% точным. Скорее всего он весит меньше, поскольку плотность информации очень разная на разных масштабах и территориях.

Имеем 1128.5 дюймов местности в 1 дюйме карты, что дает нам 1128.5 * 25.4 / 1000 / 96 = 0.29858 метров на 1 пиксель.
Чтобы закрыть 30 километров надо 30000 / 0.29858 / 256 = 392.48 тайлов. Это по одной стороне.
Значит на Москву надо 392.48 ** 2 = 154041.12 тайлов.
Что в мегабайтах означает 0.02 * 154041.12 = 3080.82 мегабайт или 3 гигабайта.

Итак, мы выяснили, что для самого крупного масштаба гуглокарт на Москву надо 3 гигабайта тайлов. Масштаб на ступень меньше потребует 3080.82 / 4 = 770 мегабайт, следующая ступень потребует 192 мегабайта, и далее — геометрическая прогрессия на 20 шагов. Пяти гигабайт должно хватить с избытком на всю масштабную линейку.

Теперь, если хотите, можете сами посчитать, сколько надо тайлов (сотни терабайт, да?) на цилиндрическую развертку (проекция Меркатора) Земли в целом.
Длина экватора - 40076 км. Длина меридиана – 40009 км, нам нужна половина (от полюса до полюса). Короче, считать надо прямоугольник 40000 км на 20000 км в несколько округленном виде.

У меня получилось 2 738 терабайт. Три петабайта на весь глобус, и это только один масштаб, пусть и самый крупный. Я правильно посчитал? А то у меня с арифметикой часто глюки бывают.

def GooGlobeTilesSize():
 squareSide = 30.0 * 1000.0 # meters
 scale20 = 1128.497176 # meters in meter
 dpi = 96
 tileSide = 256.0 # pixel
 tileMB = 0.02 # megabyte
 inch = 2.54 / 100.0 # meter
 m2px = scale20 * inch / dpi # meters in pixel
 tilesLine = squareSide / m2px / tileSide
 squareTiles = tilesLine ** 2
 squareMegabytes = squareTiles * tileMB
 print '%s гигабайт на Москву' % (squareMegabytes / 1000.0)

2012-01-24

Remastersys

Какая интересная штука — обещают сделать live-CD/DVD из снимка с рабочей машины. Для ленивых самое оно — одной командой (если не считать установки самого ремастерсис). Типа, поставил дебианчик или убунту, настроил и, опля, сделал тираж. Пригодится при переезде станции на новую железку или при переносе сервера.

Remastersys can help you deploy multiple machines or even take a sandbox server and copy it onto production hardware.
With Remastersys, you can:
  • Make a full system backup (including personal data) to a live CD or DVD that you can use anywhere and install.
  • Make a distributable copy (without personal data) that you can use as an installation/live disk.
Once you master the ISO, you can install it on any machine that meets the original system requirements for the distribution (which varies by distribution and release).
The true beauty of Remastersys is it allows you to take a pre-existing Debian-based machine, get it set up the way you need it, and create a live distribution based on that setup.
...
You can take a look at the /etc/remastersys.conf file and make changes to suit your distribution needs (such as naming the live CD, changing the live user name, etc.). It’s “go” time. Issue the commands:
sudo su
remastersys dist
The commands will take quite some time to run, so go get some coffee and eat a scone. Once it’s done, you’ll have an .iso file that can then be burned to a CD or DVD (depending upon the size). If you want to make a full backup distribution of your system, you can run
remastersys backup
and the resulting ISO will include user data. As long as you remember the 4 GB limit, you’ll be okay.

techrepublic.com/blog/doityourself-it-guy/diy-create-a-distribution-or-backup-of-your-debian-based-desktopserver
geekconnection.org/remastersys/debian
dedoimedo.com/computers/remastersys

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

2012-01-23

ConcurrentQueue

Вот одного я не пойму — зачем дотнетные фреймворки такие разные? Например, почему в Silverlight нету такой штуки как ConcurrentQueue?. Это такая threading-safe queue, то что надо, но в сильвере нету.

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

И только после того как я решил делать свой велосипед и полез искать мьютексы, погрузился в тему потоков в сильвере, выплыло это: System.Threading.Monitor. И к нему, в качестве примера кода, безопасная очередь — то, что я искал. А пацаны то и не знают.

class SafeQueue<T>
{
   // A queue that is protected by Monitor.
   private Queue<T> m_inputQueue = new Queue<T>();
   // Lock the queue and add an element.
   public void Enqueue(T qValue)
   {
      // Request the lock, and block until it is obtained.
      Monitor.Enter(m_inputQueue);
      try
      {
         // When the lock is obtained, add an element.
         m_inputQueue.Enqueue(qValue);
      }
      finally
      {
         // Ensure that the lock is released.
         Monitor.Exit(m_inputQueue);
      }
   }

Типа, это прогрессивный метод работы с блокировками? К этому должны придти все дотнетные фреймворки?

2012-01-21

Text

Открытие месяца — текстовый редактор для программеров, плагины к которому можно (и нужно) писать на Python.

Удивительно, но я лишь пару дней назад впервые узнал о существовании редактора Sublime Text. Кроссплатформенный, портабл, расширяемый, автоматизируемый, ...
Лучше один раз увидеть, чем сто раз услышать:



sublimetext.com
sublimetext.com/dev
habrahabr.ru/blogs/python/136529

Ушел осваивать новую тулзу.

2012-01-20

Админка

Где-то тут я писал про Oracle Apex, средство публикации таблиц и табличных аппликух в вебе. Ставить и настраивать этот «арех» то еще удовольствие. Можно ли проще? Можно.

В рамках проекта Saint подготовлен инструментарий, который позволяет быстро и просто генерировать web-интерфейсы для управления данными в DataMapper ORM, путем создания каркаса на языке Ruby. Saint позволяет создавать любые HTML-поля на чистом Ruby, поддерживает любые типы ассоциирования таблиц, комплексные фильтры, встроенный файловый менеджер и другие полезные функции. Основная цель Saint - максимально упростить управление контентом определённых таблиц БД. Код проекта распространяется под лицензией BSD. Пример интерфейса, созданного на основании простого 100-строчного скрипта, можно оценить на данной странице.

opennet.ru/opennews/art 32841

Полезная штука, однозначно.

2012-01-19

Сорцы


Казалось бы, какая польза может быть от газеты «Завтра»? А она есть. Ибо автор выложил в открытый доступ исходники сайта (Python, Django, Redis, Solr):

Два месяца назад мы запустили новый сайт газеты "Завтра". Всё работает на 512-метровом рэкспейсовом vps, вместе с солром, и даже не думает ходить в своп, что интересно.
Это мой первый проект с такой посещаемостью, поэтому я несколько удивлён что с первого раза удалось нарисовать такой код. Причем ведь всё стандартное: ОРМ джанговский, шаблонный движок тоже. Разве что редис используется для хранения сессий и кеша.
Без солра вообще было занято в среднем 100 метров памяти. Но джава взяла своё и съела остававшееся :)
Исходный код выложен тут. Полно сырых моментов, однако работает и не жужжит.
Джанга рулит всё-таки.

zw0rk.blogspot.com/2012/01/blog-post_11

Автору респект и уважуха.

Когда-то я настолько любил учиться, что тянул к себе любые найденные исходники мало-мальски интересных проектов. А сейчас то ли выучился уже, то ли доступность исходников такова, что тянуть к себе смысла нет, то ли постарел...
Даже сырцы Doom III не скачал.
А помню, как разбирал код Quake.

2012-01-17

Каникулы

Поразительная штука — язык. Иногда такие фортеля получаются, ой-ёй. Вот на днях закончились зимние каникулы, да? А что такое каникулы? Для нас это многодневный перерыв в работе или учебе. А буквально?

А буквально, это производное от латинского diēs caniculārēs. Что можно перевести как «собачьи дни». Согласно отключаемой через 11 часов педивикии «... are the hottest, most sultry days of summer

То есть, при таких раскладах, зимние каникулы — это оксюморон. Чепуха. А с другой стороны, если дни собачьи, то почему бы им не быть зимой?

Отдельного расследования заслуживает вопрос: почему самые жаркие дни лета получили название «собачьи»? Да еще и на латыни? Типа, собаки упали и лежат, тяжко дыша — значит в Риме каникулы.


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

Это похоже, наверное, на то как если бы энергокомпании устроили «Час Земли», отрубив нам электричество в знак своего протеста против повышения энергопотребления (приводящего к глобальному потеплению).
Поживем, увидим. Может и так будет.

Who's on first

.. we have Who's on fist, What's on second, I-don't-know on third...
... - why you asking me who's on first? - I'm not asking, I'm telling you, Who's on first!
... - Who's on first! - I don't know. - He's on third, we don't talking about him...

Это из скетча Abbot and Costello. Все, кто хоть немного воспринимает на слух аглицкую речь, просто обязаны посмотреть скетч. Ржака невероятная!
Райкину с Авас-ом никак не сравниться.

Вчера поглядел «Человек дождя» - Rain Man, в оригинале. Раньше пару раз я видел эту фильму, но вот эпизодов с «кто на первой базе» никак не понимал. Вернее понимал так, что Рейман пытается решить некую головоломку. А теперь я осознал, послушав оригинальную звуковую дорожку. Рейман не понял юмора виденного когда-то скетча и воспринял его как загадку, которую и пытался разгадать.

Чем дальше, тем я более убежденный сторонник теории, что фильмы надо смотреть с оригинальной звуковой дорожкой.

2012-01-15

Zope & HTTP PUT

Я тут уже выступал на тему «а как Zope обрабатывает метод PUT протокола HTTP». Неясно было, Zope «из коробки» поддерживает этот метод или надо поднимать WebDAV?

Сегодня я этот вопрос разьяснил. Сделал в Zope в папочке /uploader/t/ обьект ZPT с именем test и произвольным содержимым. Это получился типа сервер.
Потом нарисова типа клиента
 import httplib2
 h = httplib2.Http(timeout=3)
 #~ h.add_credentials('guest', '1111')
 h.add_credentials('admin', '12345678')
 h.force_exception_to_status_code = True
 resp, content = h.request('http://localhost:8080/uploader/t/test', 'PUT',
  body='Test with text body', headers={'content-type':'text/plain'})
 print 'resp=[%s]\ncontent=[%s]' % (resp, content)

На выходе получил такие принты:
as guest
resp=[{'bobo-exception-line': '717', 'status': '401', 'content-length': '259', 'bobo-exception-value': 'See the server error log for details', 'content-type': 'text/html; charset=utf-8', 'bobo-exception-type': 'Unauthorized', 'server': 'Zope/(Zope 2.11.4-final, python 2.4.4, win32) ZServer/1.1', 'date': 'Sun, 15 Jan 2012 17:16:42 GMT', 'bobo-exception-file': 'HTTPResponse.py', 'www-authenticate': 'basic realm="Zope"'}]

content=[<strong>You are not authorized to access this resource.</strong> (Also, the following error occurred while attempting to render the standard error message, please see the event log for full details: You are not allowed to access 'title_or_id' in this context)]


as admin
resp=[{'date': 'Sun, 15 Jan 2012 17:30:14 GMT', 'status': '204', 'accept-ranges': 'none', 'server': 'Zope/(Zope 2.11.4-final, python 2.4.4, win32) ZServer/1.1'}]

content=[]

В переводе на понятный это звучит примерно так:
я отправляю запрос обьекту типа ZPT в Zope сначала от обычного бесправного пользователя, затем от админа. В результате обычного пользователя посылают лесом.
Админа пропускают, что приводит к замене внутренностей ZPT обьекта test засланным текстом.

Выводы.

Метод HTTP PUT обрабатывается в Zope без привлечения дополнительных серверов типа WebDAV. Что я и пытался выяснить.
Как и указано в доках Zope, HTTP PUT рассматривается в Zope как вызов метода обьекта. В моем случае, для понятности происходящего, этот вызов можно записать как такой псевдокод

obj = getObject('/uploader/t/test'); obj.PUT(requestBody)

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

Вопрос с обработкой PUT вылез из размышлений на тему «как ловчее файлы на сервер загружать», не просто так. Итак, чтобы мне сделать upload файлов через HTTP PUT, мне надо сделать такой продукт Zope, класс которого будет содержать переопределенный метод PUT. В этом методе я должен принимать чанки присылаемых файлов.

Может быть так и сделаю. Пока на очереди способ
HTTP POST multipart/form-data, Content-Transfer-Encoding : binary
Такие дела.

HTML верстка

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

требования, которые у меня были к искомому решению:
  • Простота работы
  • Наличие базового дизайна
  • Адаптивность разметки для мобильных устройств
  • Лучше, чтоб было на HTML5
  • Бесплатность
... В течении нескольких дней я собрал шаблон, создал несколько вариантов тем оформления и выложил все это на Гитхаб для скачивания.
Simpliste — название, которое пришло само. Вот что предлагает шаблон:
  • CMS не требуется, это просто HTML-код.
  • Разметка создается простыми блоками, которых не слишком много, так что не запутаешься (возможны три, две или одна колонка). Готовые классы есть для большинства ситуаций.
  • Ресет от HTML5 бойлерплейт дает стабильность внешнего вида в разных браузерах.
  • HTML5 и CSS3. Предусмотрена загрузка HTML5 Shiv c сервера Гугл (это только для IE). Больше никаких скриптов к шаблону не подключено.
  • Есть несколько тем оформления. Все темы созданы без использования файлов изображений.
  • Адаптивность к ширине браузера. На мобильных устройствах колонки превратятся в вертикальный блок статей, CSS-классы предусматривают это автоматически.
habrahabr.ru/blogs/webdev/136077
cssr.ru/simpliste
github.com/rafikov/Simpliste/zipball/master

Простой, симпатичный и аккуратный дизайн. Несколько тем, в каждой теме буквально два файла — HTML и CSS. Забиваем в HTML свой текст и выкладываем на сайт. Проще пареной свеклы.

2012-01-13

Using PostgreSQL

Кстати, сегодня ведь ч0рная пятница! 2012-01-13 friday. Какой кошмар.

Итак, продолжим. Предыдущий пост был посвящен установке и первичной настройке СУБД PostgreSQL (вместе с PostGIS, которая пока никак не задействована, потом пригодится). В том посте я обещал нарисовать пример использования свежеустановленной БД по задаче «загрузить список файлов в таблицу и найти нужные файлы».

Приступим.

В наличии файл (размер под гигабайт, более 4 000 000 строк) вида CSV.
Пример данных, первые две строки из файла:
'mode';'ino';'dev';'nlink';'uid';'gid';'size';'atime';'mtime';'ctime';'fullName'
'33206';'0';'0';'0';'0';'0';'2924';'2012-01-12 03:17:04';'2011-12-20 17:38:39';'2011-12-20 17:38:39';'c:\arcgisserver\arcgiscache\topo500\Layers\conf.xml'

Для меня интерес представляет параметр mtime, то есть время последней модификации. Мне надо найти файлы, изменение которых проходило после некоей даты, которую еще надо определить исходя из нечеткой логики типа «в последнюю неделю старого года мы немного файлов изменяли, когда точно — не помню».

Файл был получен прогоном скрипта, где ключевые строки такие:
#!/usr/bin/env python
...
csvWriter = csv.writer(fileObj,
 delimiter=';', quotechar="'", quoting=csv.QUOTE_ALL, lineterminator='\n')
...
 for (path, dirs, files) in os.walk(path):
  for fn in files:
   fullName = os.path.join(path, fn)
   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = ('', '', '', '', '', '', '', '', '', '')
   try:
    (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(fullName)
   except:
    log.error('os.stat failed', exc_info=True)
   csvWriter.writerow((mode, ino, dev, nlink, uid, gid, size,
    strFtime(atime), strFtime(mtime), strFtime(ctime), fullName))

Глядя на содержимое файла, я состряпал такую таблицу (в pgAdmin есть вполне приятный GUI создания таблиц)
CREATE TABLE flist
(
   fmode integer, 
   fino integer, 
   fdev integer, 
   fnlink integer, 
   fuid integer, 
   fgid integer, 
   fsize integer, 
   fatime character varying(20), 
   fmtime character varying(20), 
   fctime character varying(20), 
   "fullName" character varying(255), 
   CONSTRAINT flist_pk PRIMARY KEY ("fullName")
) 
WITH (
  OIDS = FALSE
);
ALTER TABLE flist OWNER TO postgres;
видно, что с именем «fullName» я погорячился — теперь придется всю дорогу использовать форму записи имени с кавычками. Еще видно, что индексы я делать пока не стал, из соображений скорости загрузки. Правда сделал первичный ключ (без него как-то неуютно даже).

Теперь надо загрузить файл CSV в эту таблицу. Есть сведения, что с этим легко справится встроенная в PostgreSQL команда COPY. Но есть закавыка — если я на клиенте, где мне расположить файл? Я попробовал по разному и в итоге, лично мне проще оказалось выполнить команду в консоли сервера, подмонтировав файл в дерево каталогов сервера.

Сначала я тупо скопировал файл на сервер
postgres@postgis:~$ rsync v@sqz2:vshare/t/topo500/current/listfiles.csv ~/
получился файл /var/lib/postgresql/listfiles.csv
что многое говорит о профиле пользователя postgres на сервере.
А потом я подумал (бывает, сначала делаешь, потом думаешь) и решил сделать лучше — подключить Samba, ибо часто нужно использовать виндовые шари.

Получилось так:
от рута:
   86  aptitude install cifs-utils
   92  mkdir -p /home/v/mnt/vshare
   94  chown -R v /home/v/mnt
   98  mount -t cifs //sqz2/vshare /home/v/mnt/vshare -o username=v,uid=postgres
postgres@postgis:~$ less /home/v/mnt/vshare/t/topo500/current/listfiles.csv
Что и требовалось - файл доступен для пользователя postgres на сервере БД.

Собственно импорт довольно прост:
postgres@postgis:~$ psql
postgres=# copy flist(fmode, fino, fdev, fnlink, fuid, fgid, fsize, fatime, fmtime, fctime, "fullName") 
from '/home/v/mnt/vshare/t/topo500/current/listfiles.csv' with DELIMITER as ';' CSV header quote as '''';
COPY 4260931
последняя строка показывает сколько строк скопировано. Число правильное. Жаль, время я тогда не засек, а тулза его не показывает. По ощущениям, данные заливаются раза в два дольше, чем если просто переписывать файл по сети. Возможно, удалив первичный ключ получилось бы быстрее.

Дальнейшая работа с таблицей целиком проходит на клиенте, pgAdmin query tool в моем случае.

Создать индекс на поле fmtime. Опять же, через GUI создания/редактирования таблиц
-- DROP INDEX flist_mod_idx;
CREATE INDEX flist_mod_idx
  ON flist
  USING btree
  (fmtime COLLATE pg_catalog."default" );
в том GUI довольно много опций, надо бы в них поподробнее разобраться. А сейчас все опции дефолтные.

Запрос на выборку
SELECT 
  flist."fullName"
--  , flist.fctime
--  , flist.fmtime
FROM 
  public.flist
WHERE 
  flist.fmtime > '2011-12-23 21:53:37'
ORDER BY
  flist.fmtime ASC
-- limit 1000
;
Total query runtime: 7962 ms.
70066 rows retrieved.
изначально я его сделал через GUI графического построителя запросов, из любопытства. Оказалось очень даже удобно. Только опции ограничения количества записей не нашел как в запрос добавить. Пришлось руками поправлять.

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

Ну и получив нужную мне выборку, в том же pgAdmin query tool я сохранил ее в файл, через меню File — Export. Очень удобно.

Задача решена, всем спасибо, все свободны.

PostgreSQL

Вчера решил совместить нужное с полезным. Получилось приятное :)

Нужно было определить список (подмножество) файлов из определенного каталога, по дате модификации. Фигня, скажете вы. А я уточню — файлов более 4-х миллионов, что дает полный список размером почти в 1 гигабайт, что дает время перестроения списка файлов в, к примеру, тотальном коммандере десятки минут. И критерий поиска точно не определен. Нужна БД и индексы, однозначно.

И я собрался под это дело создать собственный сервер БД, с блекджеком и шлюхами PostgreSQL + PostGIS. Ибо все равно назрела потребность уйти с Oracle на более открытое и, что важнее, свободное решение. Это получается полезное дело.

В итоге я получил опыт установки и первичной настройки PostgreSQL на Debian. Что приятно :)

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

Тут я и зафиксирую журнал установки PostgreSQL 9.1.2 + PostGIS на Debian testing (wheezy) «по быстрому». Установка всего из пакетов дистра, ничего «левого».

Создал виртмашину: виртбокс, 1 гиг память, 100 гиг диск, 2 ядра. Сетевой интерфейс bridge с хостовым.
Установил оп.систему, подключив в вирт.сидиром исошник сетевой установки. При установке выбрал базовые пакеты + ssh сервер.

Поднастроил под себя дебианчик (несущественные и ошибочные команды я убрал из списка):
root@postgis:~# history 
    4  uname -a
   11  cat /etc/fstab 
   16  tail -n 300 -f /var/log/syslog 
   18  nano /etc/apt/sources.list
# оставил только эти записи
deb http://mirror.yandex.ru/debian/ testing main contrib non-free
deb-src http://mirror.yandex.ru/debian/ testing main contrib non-free

deb http://security.debian.org/ testing/updates main
deb-src http://security.debian.org/ testing/updates main

deb http://mirror.yandex.ru/debian/ testing-proposed-updates contrib non-free main
deb-src http://mirror.yandex.ru/debian/ testing-proposed-updates contrib non-free main
   21  nano /etc/dhcp/dhclient.conf 
# поправил две строки
send host-name "postgis";
send dhcp-lease-time 360000;
   22  reboot
   27  aptitude install linux-headers-3.1.0-1-686-pae dkms make gcc
   29  nano .bashrc 
# добавил эти опции руту и своей основной учетке
shopt -s histappend
shopt -s cmdhist
export PROMPT_COMMAND='history -a'
export HISTFILESIZE=1000
export HISTSIZE=1000
export HISTCONTROL=ignoreboth:erasedups
   38  aptitude update; aptitude safe-upgrade; aptitude full-upgrade
   39  aptitude search postgis


Установил PostgreSQL+PostGIS
   43  aptitude install postgis
   44  aptitude install postgresql-9.1-postgis
   46  netstat -tuanp
и оказалось, что слушает он только на порту 127.0.0.1:5432 чего лично мне мало.

Дальше пошла настройка PostgreSQL

   50  passwd postgres
   51  /etc/init.d/postgresql restart

пытался найти как называется сервис, чтобы подключится с клиентской машины. Оказалось, что можно и без указания сервиса
   53  locate pg_service.conf
   55  less /usr/share/postgresql/9.1/pg_service.conf.sample

ставил админпак, чтобы pgAdmin не выступал
   56  aptitude install postgresql-contrib
   57  updatedb
   61  aptitude search postgresql-contrib
   62  aptitude install postgresql-contrib-9.1
   63  locate adminpack
   64  less /usr/share/postgresql/9.1/extension/adminpack—1.0.sql
   65  psql -U postgres < /usr/share/postgresql/9.1/extension/adminpack—1.0.sql
а так нельзя. Надо по другому, см.ниже
   66  su -l postgres
где-то тут все включилось и зашуршало
   67  watch "netstat -tuanp"
это был history рута.

Теперь, что я делал от имени пользователя postgres, глядя в stuartellis.eu/articles/postgresql-setup
root@postgis:~# su -l postgres
postgres@postgis:~$ psql
postgres=# alter role postgres with encrypted password 'guesswhat';


Вероятно, тут был обратно рут:
nano /etc/postgresql/9.1/main/postgresql.conf 
# внес строку
 listen_addresses = '*'
nano /etc/postgresql/9.1/main/pg_hba.conf
# добавил строку
 host all all 192.168.0.0/16  md5
root@postgis:~# /etc/init.d/postgresql restart

После рестарта я смог на клиентской машине законнектится pgAdmin-ом. Параметры коннекта:
host: postgis.algis.com
port: 5432
db: postgres
user: postgres
pass: guesswhat

И pgAdmin чего-то вякнул на тему adminpack (server instrumentation not installed). Я этот админпак поставил
   62  aptitude install postgresql-contrib-9.1
root@postgis:~# locate adminpack
так делать не надо:
   65  psql -U postgres < /usr/share/postgresql/9.1/extension/adminpack—1.0.sql
 err: Use "CREATE EXTENSION adminpack" to load this file.
postgresql.org/docs/9.1/static/sql-createextension
надо вот так:
postgres@postgis:~$ psql
postgres=# create extension adminpack;
CREATE EXTENSION
postgres=# /q
но результат странный — предполагалось, что у меня в pgAdmin будет доступ к файлам конфигов сервера — не вышло. В интернетах говорят, что эта функция работает только если pgAdmin запустить на хосте, где работает сервер.
А ошибка при попытке открыть конфиг такая:
ERROR: absolute path not allowed
CONTEXT: SQL function "pg_file_length" statement 1
archives.postgresql.org/pgadmin-support/2009-10/msg00001

Собственно, на этом первичная настройка сервера БД заканчивается. На этом месте я выключил виртмашину и сделал ее копию, на всякий случай. Вдруг кому понадобится сервер БД, а тут раз — уже сконфигуренная машина. Файл архива весит менее 700 мегабайт. Мелочь, а приятно.

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

2012-01-12

Install fonts using a script

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

Уже несколько лет успешно пользуюсь таким скриптом для установки шрифтов в систему:
'fonts.install.vbs
Const FONTS = &H14&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(FONTS)
objFolder.CopyHere "c:\t\fnts\*.ttf"
'~ objFolder.CopyHere objShell.Namespace("c:\t\fnts").Items

@rem fonts.install.cmd
md c:\t\fnts
copy *.ttf c:\t\fnts\
cscript.exe //Nologo //T:600 fonts.install.vbs

Уж не знаю, где был надыбан первоисточник, но Скриптинг Гай дает практически такой же рецепт:

this should help a little:
Const FONTS = &H14&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(FONTS)
objFolder.CopyHere "C:\Scripts\Myfont.ttf"

Of course, that might also get you to thinking; in fact, you might be thinking, “Hey, all I have to do is copy a font into the Fonts folder and that font will automatically be installed for me.” And that’s true, but with one very important caveat: you must copy the file using the Shell object. Admittedly, you can use WMI or the FileSystemObject to copy a file into the Fonts folder; however, when you do so the operating system will not automatically install the font for you. As far as we know, the only programmatic way to get Windows to recognize that a new font has been added to the Fonts folder, and thus get Windows to install that font for you, is to use the Shell object.

blogs.technet.com/b/heyscriptingguy/archive/2008/04/25/how-can-i-install-fonts-using-a-script

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

Есть мнение, что у MS Windows (и ее компонент) есть три состояния: работает, не работает, может быть работает. Не на пустом месте придумано.

2012-01-11

Вы звонили, не отпирайтесь

На днях опубликовали интересное известие:

На двадцать восьмой конференции Chaos Communication Congress (28c3), проходящей с 27 по 30 декабря в Берлине, исследователи безопасности продемонстрировали новую технику атаки на GSM-сети...
...
В частности, утверждается, что таким образом можно делать звонки на дорогие платные номера. По словам этого исследователя, используемая техника уже известна и применяется в различных криминальных целях. По сведениям Карстена, уже сейчас известно много странных случаев, когда абоненты получают счета для оплаты на сотню евро в счет звонков, которые они ранее якобы делали на дорогие платные номера на Карибах.
...
так называемые "скрытые" сервисные SMS, которые используются оператором в разных целях, например для определения местонахождения абонента. В уходящем 2011 году в Германии зафиксирован лавинообразный рост использования этой возможности в криминальных целях...

opennet.ru/opennews/art 32690

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

Особенно любопытны становятся, в свете таких сообщений, неутихаемые попытки совместить телефон с кошельком. Вот радость будет кому-то!

Короче, почаще проверяйте баланс и не держите больших сумм на счету. Это как минимум.

2012-01-10

Каникулы всё

Каникулы кончились, и слава Богу. Уже надоело лениться и ничего не делать.

Вот интересно, гуглил целый час, но так и не нашел четкого ответа на вопрос — чтобы использовать HTTP PUT, надо ли включать поддержку WebDAV сервера в Zope или же стандартный веб-сервер Zope включает в себя обработчик метода PUT?

Придется проверять на практике.

Архив блога

Ярлыки

linux (241) python (191) citation (186) web-develop (170) gov.ru (159) video (124) бытовуха (115) sysadm (100) GIS (97) Zope(Plone) (88) бурчалки (84) Book (83) programming (82) грабли (77) Fun (76) development (73) windsurfing (72) Microsoft (64) hiload (62) internet provider (57) opensource (57) security (57) опыт (55) movie (52) Wisdom (51) ML (47) driving (45) hardware (45) language (45) money (42) JS (41) curse (40) bigdata (39) DBMS (38) ArcGIS (34) history (31) PDA (30) howto (30) holyday (29) Google (27) Oracle (27) tourism (27) virtbox (27) health (26) vacation (24) AI (23) Autodesk (23) SQL (23) humor (23) Java (22) knowledge (22) translate (20) CSS (19) cheatsheet (19) hack (19) Apache (16) Klaipeda (15) Manager (15) web-browser (15) Никонов (15) functional programming (14) happiness (14) music (14) todo (14) PHP (13) course (13) scala (13) weapon (13) HTTP. Apache (12) SSH (12) frameworks (12) hero (12) im (12) settings (12) HTML (11) SciTE (11) USA (11) crypto (11) game (11) map (11) HTTPD (9) ODF (9) Photo (9) купи/продай (9) benchmark (8) documentation (8) 3D (7) CS (7) DNS (7) NoSQL (7) cloud (7) django (7) gun (7) matroska (7) telephony (7) Microsoft Office (6) VCS (6) bluetooth (6) pidgin (6) proxy (6) Donald Knuth (5) ETL (5) NVIDIA (5) Palanga (5) REST (5) bash (5) flash (5) keyboard (5) price (5) samba (5) CGI (4) LISP (4) RoR (4) cache (4) car (4) display (4) holywar (4) nginx (4) pistol (4) spark (4) xml (4) Лебедев (4) IDE (3) IE8 (3) J2EE (3) NTFS (3) RDP (3) holiday (3) mount (3) Гоблин (3) кухня (3) урюк (3) AMQP (2) ERP (2) IE7 (2) NAS (2) Naudoc (2) PDF (2) address (2) air (2) british (2) coffee (2) fitness (2) font (2) ftp (2) fuckup (2) messaging (2) notify (2) sharepoint (2) ssl/tls (2) stardict (2) tests (2) tunnel (2) udev (2) APT (1) Baltic (1) CRUD (1) Canyonlands (1) Cyprus (1) DVDShrink (1) Jabber (1) K9Copy (1) Matlab (1) Portugal (1) VBA (1) WD My Book (1) autoit (1) bike (1) cannabis (1) chat (1) concurrent (1) dbf (1) ext4 (1) idioten (1) join (1) krusader (1) license (1) life (1) migration (1) mindmap (1) navitel (1) pneumatic weapon (1) quiz (1) regexp (1) robot (1) science (1) seaside (1) serialization (1) shore (1) spatial (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)