понедельник, 21 января 2008 г.

WayBack

Иногда возникает необходимость запустить приложение не в настоящем времени, а в прошлом или будущем. Обычно это нужно для тестирования приложения или для обхода устаревания evaluation license. Достигается это переводом системных часов, либо запуском приложения в vmware - оба этих метода имеют свои очевидные недостатки. К счастью в linux есть такая замечательная вещь как LD_PRELOAD, позволяющяя "переопределить" импортируемые функции приложения. Так, например, если подменить time, gettimeofday и clock_gettime - то программа с большой долей вероятности будет жить в том времени который нам нужен, в то время как вся остальная система будет жить в обычном временном русле. Для этих целей я написал небольшую C'ную библиотеку. Устанавливается библиотека как обычно make install.

Для примера, небольшое тестовое приложение на C:

void main () {
printf ("%lu\n", time(0));
}

Запускаем:

akshaal@...:/tmp% ./test
1200947571

akshaal@...:/tmp% WAYBACK_TODAY=1970.01.01 LD_PRELOAD=libwayback.so.0 /tmp/test
63225

akshaal@...:/tmp% WAYBACK_LOG_LEVEL=3 WAYBACK_TODAY=1970.01.01 LD_PRELOAD=libwayback.so.0 /tmp/test
Delta time: 3094082896
time modified
63257


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

Например приложение на Java и стандартная утилита date:

import java.util.Date;

public class test {
public static void main (String[] args) {
System.out.println (new Date());
}
}

akshaal@...:/tmp% java test
Mon Jan 21 22:39:26 EET 2008

akshaal@...:/tmp% WAYBACK_TODAY=2010.11.27 LD_PRELOAD=libwayback.so.0 java test
Sat Nov 27 20:40:39 EET 2010

akshaal@...:/tmp% date
Mon Jan 21 22:41:20 EET 2008

akshaal@...:/tmp% WAYBACK_TODAY=2010.11.27 LD_PRELOAD=libwayback.so.0 date
Sat Nov 27 20:41:50 EET 2010


К сожалению данный способ может быть использован для обхода устаревания лицензии :) у программ к которым есть evaluation license ограниченная на определенный срок (например JProfiler 5, YourKit Profiler 7, InteliJ Idea и еще много). Я не проверял работает ли (но уверен, что да :) ) ибо предпочитаю опенсоурс софт и вообще это плохо и я против использования библиотеки для этих целей :).

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

Библиотека написана за час и не является Абсолютным Решением. Кому надо - юзают на свой страх и риск, а с меня никакого спросу.

P.S. Больше всего напарился с одной вещью. Запускаю свинговое приложение, а оно виснет. Думаю че за нахрен. Копался-копался... оказывается java юзает pthread_condwait и ей в качестве параметра передается не относительное время (время когда ожидание прекращается), а абсолютное! Пришлось и эту функцию переопределить и вычитать дельту. Но как я искал.. strace говорит, что нить висит на futex каком-то.. и только чудом догадался, что futex может быть более нижним лаером под pthread'ом, а там уже полез смотреть как работа с X'ами идет в libawt.

четверг, 17 января 2008 г.

Scala - первое впечатление

Technology stack: java, spring framework, maven, eclipse, jboss

Все состыковалось нормально, но разочарований пока больше:
1. Поддержка Scala в eclipse'е просто никакая. Подсвечивает двумя цветами, комплишенов нет, рефакторинга нет, навигации нет. Может я что-то не правильно сделал с плагином, но для первого впечатления я бы сказал, что поддержки вообще нет.

2. Maven2 нормально собирает Scala, но нужно обязательно Maven 2.0.7 или выше. Сначало собираются все Java классы, а потом Scala. Поэтому врятли получится из Java сослаться на Scala класс. Это в пределах одного проекта. Если нужно наоборот, то надо делать два разных под модуля. А если в перемешку охото - вообще не знаю как (правда и желание левое).

3. Spring'у вобще-то пофиг инстансы какого класса делать. Главное, чтобы геттеры были. Какой-то особенной поддержки для scala в спринге нет (в отличии от BSH, Groovy и еще чего-то (jruby или jpython)).

4. Каким-то странным образом Scala делает getter'еры и setter'ы для переменных класса. То делает, то нет. Например для java.lang.Map не сделала. А для scala.collection.jcl.Map - сделала что-то типа setVar... Я сначало губу расскатал, думаю вот, наконец то не надо геттеры и сеттеры руками делать. А хрен. По умолчанию не делает само. Если в еклипсе это хотя бы для джавы двумя кликами делается, то тут это еще и руками писать вида: def getVar () = var.

5. Про override не понял. В примере override нарисован - у меня он говорит мол не ожидаю я тут override увидеть....

6. Интеграция с Java. Думаю да, клево, есть imlicit методы - значит наверное все круто и просто. Нефига. Все равно врапперы надо делать, чтобы из java Map получить scala Map. И trait scala Map не совместим с interface java Map.

7. Пишу val pending : List[(=>Unit)] = Nil; Определил. А вот pending = (println "") :: pending -- ругается, что (println "") - это Unit, а ему нужен =>Unit. lazy val v = println "" и последующий pending = v :: pending; тоже самое. v видетели Unit. Забил, сделал val pending : List[() => Unit] = Nil ... но осадок остался.

Понятно, что часть этой фигни - по моей неопытности и незнанию и наверняка решается. Но всеже.. )
Из приятного: type inference это хорошо, замыкания это хорошо, карринг это хорошо. Экономия кода не большая по сравнению с джавой, но она есть. Код чище, если на врапперы не втыкать. А если использовать приемущественно одну Scala, то вообще красота по чистоте будет.

P.S. Тут на работе постоянно бухтят о коллбэках в моем API и пытаются от них избавится... :) А буть скала, было бы это scala:
helper.runInScope (scope) {
println ("Hello world");
}


вместо:
helper.runInScope (scope, new Callback0 () {
public void run () {
println ("hello world");
}
});


Но scala там не быть :))

вторник, 8 января 2008 г.

CAL & Scala

Решил заюзать что-то отличное от Java для своего очередного домашнего хобби проекта (ну и изучить новую технологию как обычно...). Впечатление после чтения документация во время прибывания в Омске.

CAL (Quark Framework) - прикольно все-таки, что это Haskell для Java, но вот что-то интеграция с Java меня не впечатлила - чисто на урове FFI как в Haskell. Как домэйн язык оно может и удобно, но как полная замена Java не катит. Правда сильно не вчитывался - может и не прав.

Scala - весмьа красиво и многообщеюще. Почему-то постоянно слышал про этот язык несколько лет назад, когда читал рассылку O'Caml, но ни разу Scala не удосужился попробовать. А зря, весьма элегантно. Немного расстроило отсутствие поддержи Scripting for Java (не помню номер JSR).

суббота, 5 января 2008 г.

CollectD

Грубо говоря - ни дня без патчей (хотя бы так, чем ничего). Провозившись с collectd нашел ошибку. Исправил. Патч (аж из трех новых строк) отослал. Может кто-то тоже возится, пытаясь понять, почему unixsock plugin для collectd не проставляет права на socket.
diff -urN old/src/unixsock.c new/src/unixsock.c
--- old/src/unixsock.c 2007-11-10 17:15:39.000000000 +0200
+++ new/src/unixsock.c 2008-01-05 20:45:17.000000000 +0200
@@ -29,6 +29,7 @@
#include <pthread.h>

#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/un.h>

#include <grp.h>
@@ -365,6 +366,8 @@
return (-1);
}

+ chmod (sa.sun_path, sock_perms);
+
status = listen (sock_fd, 8);
if (status != 0)
{