Sunday, August 29, 2010

Softncoffee goes mobile

Поставил себе на кпк moBlog блоггинг-клиент. Собственно это первый пост с него. По эргономике moBlog оказался вполне приемлемым. Все что потребовалось: в настройках создать профиль, выбрать блоггинг сервис из списка, задать свои логин и пароль.

Friday, August 27, 2010

Ликбез по Linux за август

Короткое резюме за август.

1. подключение общих папок под Oracle Virtual Box:

Win32 guest: net use x:\\vboxsvr\host_shared_dir

Linux guest: sudo mount -t vboxsf host_shared_dir guest_mount_point

2. монтирование IMG-файла:

sudo mount -o loop linux-0.2.img mount_point

3. ssh: для работы потребуется openssh-client и openssh-server. Соотв. на target-машине должен быть поднят openssh-server.

ssh user@11.22.33.44 - наиболее простой вариант залогиниться в target- машину.
sftp user@11.22.33.44 - удобный ftp-client поверх ssl.

4. быстрый способ получить данные по некоторому url с помощью python:

tim@epsilon:~$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> data = urllib.urlopen("http://google.com").read()
>>> print "Read data: %s"%(data)


Отличная книга по python, к тому же бесплатная - здесь.

5. получение софтовых пакетов установленных на машину:

RHEL: rpm -qa
Ubuntu: dpkg-query -l
AIX: lslpp -L all

6. grep - очень мощный инструмент для поиска и фильтрации нужной информации:

получить все строки файла somewhere, в которых содержится aword:
grep aword somewhere.txt

пример: получить все пакеты, которые имеют в названии слово python:
dpkg-query --show | grep python


У большинства менеджеров пакетов есть всякий stuff, который позволяет получить подробную информацию об установленных пакетах. А также можно задавать каталог с базами данных или root-каталог, что позволяет сканировать установленный софт на некоторых ОС, расположенных на других разделах или дисках. Полезная, на мой взгляд, шпора для админов по unix - здесь

7. общие команды:

получение справки по команде, например для rpm: man rpm
удаление каталога рекурсивно, без подтверждения: rm -r -f your_dir
создание нового каталога: mkdir your_dir
перемещение/переименование файлов: mv source target
соединение файлов с их послед. выводом в стандартный поток: cat file1 file2 file3, можно использовать для вывода одного файла, в частности: cat file1

Friday, August 6, 2010

Знакомьтесь, антипаттерн double-checked locking

На днях размышлял, как можно было бы ускорить следующую конструкцию:
Конструкция 1. Известная всем реализация ленивого синглтона.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static synchronized Singleton getInstance()
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
return INSTANCE;
}
}

Основным недостатком является наличие synchronized, которое по-хорошему нужно
только при инициализации экземпляра объекта singleton, а не при каждом доступе к нему.
Таким образом, сразу же напрашивается мысль, а что если попробовать использовать критическую секцию только при инициализации объекта:
Конструкция 2. Первая попытка сделать короче время доступа к INSTANCE.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
return INSTANCE;
}
}

Теперь инициализация объекта будет происходить при первом доступе к объекту, но, к сожалению, данная конструкция не спасает от конкурентного доступа. Так как может получиться так, что конкурирующие процессы после проверки INSTANCE на null последовательно войдут в критическую секцию и проинициализируют Singleton несколько раз. Тут же придумал workaround: поставить проверку на null после входа в критическую секцию, сказано - сделано:
Конструкция 3. Вторая попытка или double-checked locking антиппатерн.
public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
}
return INSTANCE;
}
}

Полученная конструкция в теории должна работать, но так ли это? Довольный своим открытием, я решил посмотреть, что пишут эксперты о такой конструкции, есть ли какие-то другие, более эффективные варианты ускорения реализации паттерна singleton. Очень быстро обнаружил, что такая конструкция действительно используется и называется она double-checked locking (в некоторых источниках такую конструкцию называют даже антипаттерном [2]). Действительно она применяется для ускорения singleton, но имеет ряд неочевидных недостатков для некоторых языков.

Недостаток первый. В некоторых языках, в т.ч. и в Java значение переменной INSTANCE может быть присвоено при выполнении конструктора до его завершения. Это связано с выделением памяти, как только выделяется память, то INSTANCE получает соотв. значение (в Java это ссылка, в других языках это, возможно, указатель на некоторую выделенную для объекта область памяти). Таким образом, есть вероятность, что пока один поток будет выполняться в критической секции, другой, выполнив проверку INSTANCE на null, в критиескую секцию уже не пойдет, а сразу вернет неинициализированную (но не равную null) переменную INSTANCE.

Недостаток второй. Запись и чтение значений переменных в многопоточных программах на некоторых языках могут зависеть от реализации конкретной исполняющей среды/компилятора. Например, в JAVA используется кеширование переменных: из соображений эффективности каждый поток может хранить свою собственную приватную копию переменной. Эта копия может синхронизироватся с основной памятью в различные моменты, например, при входе в критическую секцию и при выходе из нее [3]. Как вариант, в Java можно использовать модификатор volatile для переменной INSTANCE, которое действительно гарантирует атомарный доступ к переменной. В таком случае переменная никогда не кешируется потоками и доступ к ней осуществляется, как если бы это происходило внутри критической секции (synchronize над этой переменной). Но по сути это приводит к тому же от, чего уходили - к наличию критической секции при доступе к переменной.

Таким образом, рекомендуется использовать конструкцию 1 [2], либо использовать факт о ленивой загрузке классов [1]: т.е. что сам класс Singleton будет загружен лишь при первом обращении к нему, соотв. будут проинициализированны все static-поля и секции:
Конструкция 4. Если быть проще...
public class Singleton
{
private static Singleton INSTANCE = new Singleton();

static
{
// further INSTANCE initialization
}

private Singleton()
{
// Singleton initialization
}

public static Singleton getInstance()
{
return INSTANCE;
}
}


Материалы.

[1] http://www.ibm.com/developerworks/java/library/j-dcl.html
[2] http://www.javamex.com/tutorials/double_checked_locking_fixing.shtml
[3] http://www.javamex.com/tutorials/synchronization_concurrency_synchronized1.shtml

Thursday, July 22, 2010

Переменные среды в Linux

Установка некоторых переменных среды через консоль:

export JAVA_HOME=/path/to/java/jdk1.6.0_20
export PATH=$JAVA_HOME:$PATH

export M2_HOME=/path/to/java/maven
export M2=$M2_HOME/bin
export PATH=$M2:$PATH

export используется, если задается глобальная переменная. Если переменная локальная (т.е. только для данного процесса), то export не требуется.
Посмотреть значение переменной можно, например, так:

echo $PATH

Кстати, в отличие от Windows, в PATH элементы разделяются двоеточием, а не точкой с запятой.
Для того, чтобы переменные среды устанавливались при загрузке пользовательского профайла рекомендуется использовать ~/.pam_environment для того, чтобы добавить туда скрипт с заданием переменных. Общие рекомендации по установке persistent environment variables можно узнать, набрав в консоли man pam_env, либо здесь.

Как оказалось, ~/.pam_environment не является скриптовым файлом, а представляет собой лишь список переменных среды. К тому же, у меня не получилось переопределить PATH, используя упомянутый файл. Такое переопределение приводило к тому, что в машину вообще нельзя было залогиниться. Пришлось войти в консольном режиме и с помощью vim удалять строки в ~/.pam_environment, отвечающие за переопределение PATH.

В конце концов, я взял и добавил нужные строки для определения переменных среды в ~/.profile. Сработало.

Tuesday, July 13, 2010

Использование system properties в eclipse.ini

Понадобилась небольшая кастомизация eclipse.ini.
Потребовалось уметь создавать свои параметры из eclipse.ini и уметь читать их внутри eclipse. Первый поиск практически ничего не дал конкретного по eclipse, но нашелся другой, более общий варинт: использование системных свойств (system properties) java. Системное свойство можно определить через eclipse.ini в качестве аргумента java-машины, например:

...
-vmargs
-Dfile.encoding=UTF-8
-Dosgi.requiredJavaVersion=1.5
-DMyCustomProperty=aPropertyValue
-Xms256m
...

Теперь в коде можно получить значение свойства MyCustomProperty следующим образом:

String value = System.getProperty("MyCustomProperty");

Friday, July 9, 2010

Создание архивов с помощью VBS

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


';===================================
';
'; Simple zipping routine:
';
'; source is folder path to be zipped (recursive zip)
'; dest is file path for output zip archive
';
'; the main idea comes from here:
';
'; http://www.codecomments.com/archive299-2006-2-295877.html
'; http://forum.script-coding.info/viewtopic.php?id=1020
';
';===================================
sub zip(source, dest)
'
' wait operation delay
'
const dt = 1000
Set fso = CreateObject("Scripting.FileSystemObject")
Set ShellApp = CreateObject("Shell.Application")

With fso.CreateTextFile(dest, True)
.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, Chr(0))
.Close
End With

ShellApp.NameSpace(dest).CopyHere source

WScript.Sleep dt
'
' waiting for acrhive creation
'
On Error Resume Next
Do
fso.OpenTextFile dest, 1, False
If Err.Number = 0 Then Exit Do
Err.Clear
WScript.Sleep dt
Loop
end sub

Wednesday, July 7, 2010

Некоторые скриптинговые рутины на VBS

Давно хотел выложить код на VBScript, который я использовал в скрипте для публикации проекта (под публикацией понималось выкладывание сборки в базу данных Lotus Notes и рассылка уведомлений по списку).

Работа с Lotus Notes в vbs:

sub run()
' получить сессию (COM-объект, соотв. важно,
' чтобы объект был зарегистрирован в Win-реестре)
Set nSession = CreateObject("Notes.NotesSession")
' получить базу
Set db = nSession.GetDatabase(STORAGE_DATABASE_SRV,STORAGE_DATABASE_PATH)
if not db is nothing then
' какая-то работа с базой
'...
'...
end if
' освобождеине COM-объекта
nSession = null
end sub



Сниппет с приаттачиванием файлов к документу:


const EMBED_ATTACHMENT = 1454
';================================================
';
'; Simple file attach routine
';
'; @param doc is Notes Document
'; @param itemName is RTF item name
'; @param path is path to the file to be attached
';================================================
sub attach(doc, itemName, path)
Set item = doc.getFirstItem(itemName)
if not item is nothing then
call doc.removeItem(itemName)
end if
Set rti = doc.CreateRichTextItem(ItemName)
Set object = rti.EmbedObject(EMBED_ATTACHMENT, "", path)
end sub