Криволапые разработчики Яндекс карт под Андроид
f1
egoroff
Персональное фэ разрабочикам мобильных Яндекс карт для андроида. Суть проблемы в том, что для самсунгов (проверял только на них) есть закладка, что внешняя карта SD будет смонтирована в папку external_sd находящуюся в корне внутренней SD карты (/mnt/sdcard) т.е. /mnt/sdcard/external_sd. Для адроида 2.3 это верно, но никак не для андроида 4.0, где внешняя карточка монтируется как /mnt/emmc и /emmc.

К чему приводит эта закладка (хардкод)? А к тому, что даже если вы в настройках яндекс карт выбираете место для хранения кэша на внешней карте, то один хрен, он будет ВСЕГДА храниться на внутренней карте, просто по другому пути. Таким образом загаживая ценное место.

Все это верно для кастомной прошивки Android 4.0 (Я использую CyanogenMod 9) и возможно в родной стоковой от самсунг, они сделали монтирование в старое место. Для решения проблемы может быть использована как командная строка, с помощью которой можно сделать дополнительный биндинг внешней карты по пути /mnt/sdcard/external_sd, но я использовал ICS SD Binder (требует рута)
Метки: , ,

Яндекс
f1
egoroff
В прошлом посте высказал свое персональное фэ яндексу за низкую скорость обновления индекса. Сегодня, опытным путем выяснилось (за вчерашний день резкий взлет посетителей с яндекса), что индекс обновляется раз в 2 недели. Небыстро однако. Да.

Персональное фэ Яндексу
f1
egoroff
У меня сайт не работал месяц (денег не было заплатить), и естественно он повылетал из всех индексов поисковых систем, но я не об этом сейчас. После восстановления работы сайта, через несколько дней, поток посетителей с гугла восстановился, т.е. сайт нормально восстановился в индексе, а вот у яндекса пока нет и соответственно посетителей оттуда кот наплакал :) Не, с гуглом, с таким тормозным роботом, им конкурировать нельзя.

Оказывается!
f1
egoroff
Вчера tomash подсказал что на непрогретом двигателе обороты холостого хода повышенные, - а я и не знал :) У меня на непрогретом 1000, а на прогретом в районе 700. Буду теперь знать :)

Прошлый год
f1
egoroff
Один из самых переменчивых годов у меня получился

  • Отошел от неудачной любви

  • Съездил в Китай

  • Сменил работу

  • Сменил квартиру

  • Сдал на права

  • Купил машину

  • Познакомился с Ниной

Интересно что будет в этом :)

Стив Джобс
f1
egoroff

  1. Бросил беременную подругу и так и не признает отцовства своей дочери Лизы

  2. До последнего отказывался помогать подруге и ребенку материально. Сделал это только под давлением суда

  3. Людей которых помогали ей в трудную минуту кидал потом

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

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

  6. Обманывал своих самых близких друзей и коллег - Стива Возняка например, сказав что продал плату или какой-то другой девайс за 500 долларов и отдав ему 300, сам продал её за 1000 и в карман положил себе 700 баксов. Подобные трюки он проделывал постоянно.

  7. При создании Macintosh постоянно занимался микроменеджментом, буквально приходя на место инженера и вмешивался в работу раздавая ему нужные, с его точки зрения, ЦУ, при этом он уже был одним из владельцев Apple с многомилионным состоянием.


Я теперь не удивляюсь почему он не раз терял все и почему его посылали партнеры. Интересно другое, - почему ему до сих пор доверяют люди и почему он выплывает? Изучаю дальше

Бага или фича R#
f1
egoroff
Наткнулся сегодня на забавное поведение R# при встрече с реальным кодом. Имеем следующий класс:

using System;

namespace tst
{
    public class A<T> where T : IDisposable, new()
    {
        private readonly T _obj;

        public A()
        {
            _obj = new T();
        }

        public void Foo()
        {
            lock (_obj)
            {
                Console.WriteLine(_obj.ToString());
            }
        }
    }

    public struct B : IDisposable
    {
        public void Dispose()
        {
            // implementation
        }
    }
    
    public class C : IDisposable
    {
        public void Dispose()
        {
            // implementation
        }
    }

    internal class Program
    {
        private static void Main()
        {
            A<B> a1 = new A<B>();
            A<C> a2 = new A<C>();
            a1.Foo();
            a2.Foo();
            Console.ReadLine();
        }
    }
}

R# правильно ругается на строчке с lock — действительно экземпляр типа T вполне может оказаться и структурой, а не только классом и таким образом будет нарушено условие для конструкции lock (а точнее для монитора, который эта штука скрывает), т.е. туда передается не ссылочный тип, а размерный. Но код прекрасно компилируется и работает, что не согласуется с теорией. Тут скорее всего идет работа с упакованным в куче объектом структуры, но как это будет работать не очень понятно. Вот и думаю, — бага где, — в R# или C# компиляторе?

Кстати если добавить ещё одно ограничение class, то код перестает компилироваться и правильно:

using System;

namespace tst
{
    public class A<T> where T : class, IDisposable, new()
    {
        private readonly T _obj;

        public A()
        {
            _obj = new T();
        }

        public void Foo()
        {
            lock (_obj)
            {
                Console.WriteLine(_obj.ToString());
            }
        }
    }

    public struct B : IDisposable
    {
        public void Dispose()
        {
            // implementation
        }
    }
    
    public class C : IDisposable
    {
        public void Dispose()
        {
            // implementation
        }
    }

    internal class Program
    {
        private static void Main()
        {
            A<B> a1 = new A<B>();
            A<C> a2 = new A<C>();
            a1.Foo();
            a2.Foo();
            Console.ReadLine();
        }
    }
}

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

Как улучшить отложенный коммит в TeamCity
f1
egoroff
В предыдущем посте про отложенный коммит в JetBrains TeamCity, я сказал, что у этого механизма (впрочем, как и у любого другого), есть ограничения, а именно время сборки проекта, при котором этой фичей можно нормально пользоваться. Мне ответили (очевидно, сотрудник JetBrains) что можно пользоваться даже если время сборки большое, нужно просто продолжать работать над другой фичей. Все клево если вы в процессе работы модифицируете другие файлы, ну и если сборка успешная тоже все клево. А если нет? Если вы, работая над другой фичей работаете с теми же самыми файлами, хуже того, правите те же самые строки и до кучи сборка ещё свалилась? Попробуй потом разбери, что к чему относится.

Все это верно в случае использования централизованных систем контроля версий вроде Subversion, где репозиторий централизованный и делая коммит, вы меняете этот репозиторий и все изменения немедленно вступают в силу. Но есть и хорошие новости, — это ограничение можно обойти при использовании распределенной системы контроля версий, вроде Mercurial, Git и пр. Жаль что пока это не поддерживается этой полезной фичей (поддержка отложенного комита сделана только для Subversion и Perforce). Кстати отличный feature request!

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

После того как вы все сделали, проверили, закоммитили локально, вы делаете push (проталкивание) в репозиторий (назовем его централизованным), из которого проводится сборка продукта и который служит для синхронизации исходников между членами команды. И вот тут то, функция отложенного push была бы очень кстати! Т.е. делается персональная сборка, и если она успешна, то push проходит. Т.к. push делается по определению редко, то можно спокойно ждать пока он завершится работая над другой фичей или багой. Ждем реализации от JetBrains :)

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

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

Модифицированная версияСвернуть )

Спасибо chemodax!
Метки:

Ограничения отложенного коммита в TeamCity
f1
egoroff
Есть такая система сборки или постоянной интеграции (кому что нравится), — JetBrains TeamCity. Реально добротно сделанная и идеологически правильная система. Кстати, для маленьких команд версия бесплатна, разумеется с некоторыми ограничениями, которые возможно вам никогда и не понадобятся. Но я не об этом :) Есть в этом продукте одна очень полезная вещь, называемая отложенный коммит (фиксация изменений в системе контроля версий), работающий правда не для всех систем контроля версий и IDE (хотя там есть консольная утиль для этого, но я ей ни разу не пользовался). Что это такое?

Это механизм позволяющий радикально уменьшить количество неудачных сборок из-за несогласованных изменений вносимых в систему контроля версий, из которой потом берутся исходники для сборки продуктов. Как это работает? Очень просто. Разработчик внес изменения в исходный код, собрал, проверил что все работает, но делает фиксацию не сразу, а через специальный штепсель (плугин) для IDE, который берет все локальные изменения, которые он хочет зафиксировать, отправляет их на сервер сборки, сервер сборки соединяет их с кодом из системы контроля версий и начинает сборку. Если сборка (включая Unit тесты, анализ кода, сборку инсталляторов и пр.) проходит успешно, сервер фиксирует в системе контроля версий все изменения, с которыми проводилась эта сборка.

Красиво да? Разумеется, но есть одно существенное ограничение — размер продукта, напрямую влияющий на время сборки. Мы, на моем последнем месте работы (если кто не в курсе, — я ушел из InfoWatch), опытным путем выяснили, что реально пользоваться этим можно только если время сборки не превышает 15-20 минут. Дальше возникает раздражение, желание сделать коммит так, не прибегая к этой функции, т.к. на все время сборки вы выключаетесь из процесса кодирования.

До тех пор пока у нас не было поддержки x64 систем, все укладывалось в эти 20 минут и все было шоколадно. После появления таковой, время сборки выросло до получаса и это стало реально напрягать, поэтому пришлось отключить по умолчанию сборку x64 версии продукта (включается опционально через установку специального свойства при создании задания на сборку). Кстати, с появлением x64 версии, пришлось начать пользоваться precompiled headers (до этого не было, т.к. разработчики считали что эта штука глючит), — тут ещё выиграли минуты 2-3.

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

Обход каталогов
f1
egoroff
А все таки, в языке Си есть свое очарование. Да, пускай это высокоуровневый ассемблер, да на нем приходится писать много кода для простых вещей, да это не оружие массового поражения, вроде C++, но в его простоте и заключается красота. Это как меч, - им достаточно сложно научиться пользоваться, в отличие например от пистолета или автомата, но если научился, то испытываешь ни с чем несравнимое удовольствие от обращения с ним.

На досуге ковыряюсь с проектом небольших консольных приложений, хэш калькуляторов (есть MD4, MD5, SHA1, SHA256, SHA384, SHA512 и Whirlpool), и там есть функция обхода каталогов с фильтрацией (исключающей и включающей). Код достаточно независимый от контекста, может кому и пригодится. Да, замечание - там используется Apache Portable Runtime. Это отличная и легковесная библиотека, написанная целиком на Си. Есть конечно в ней ряд странностей, например методика управления памятью только через собственные пулы, но это не самое страшное . Впрочем, такой дизайн наверняка был оправдан в самом начале проектирования библиотеки. Также, стоит учесть её специфику - создавалась для проекта веб сервера.

Функционал простой. TraverseDirectory обходит каталоги, с возможностью рекурсивного обхода и фильтрации. Для каждого файла может вызывается обработчик, указатель на который задается в структуре TraverseContext. Можно задавать несколько шаблонов фильтрации разделяя их точкой с запятой. Обратите внимание сколько много кода, на каком-нибудь C# кода будет раз в пять меньше, для того же самого :). Итак сам код:

Читать дальше...Свернуть )
Метки:

Нормализация размера файла - 2
f1
egoroff
В комментариях к предыдущему посту про нормализацию размера файла мне указали на некоторые проблемы, вызывающие ругань компилятора (и правильно в общем то), а это не есть хорошо. Поэтому исправленный вариант выглядит так:

#include <math.h> 
 
#define BINARY_THOUSAND 1024 
#define INT64_BITS_COUNT 64 
 
typedef enum { 
    SizeUnitBytes = 0, 
    SizeUnitKBytes = 1, 
    SizeUnitMBytes = 2, 
    SizeUnitGBytes = 3, 
    SizeUnitTBytes = 4, 
    SizeUnitPBytes = 5, 
    SizeUnitEBytes = 6, 
    SizeUnitZBytes = 7, 
    SizeUnitYBytes = 8 
} SizeUnit; 
 
typedef struct FileSize { 
    SizeUnit unit; 
    // Union of either size in bytes or size it KBytes, MBytes etc.  
    union { 
        double size; 
        long long sizeInBytes; 
    } value; 
} FileSize; 
 
unsigned long long ilog(unsigned long long x) 
{ 
    unsigned long long y = 0; 
    unsigned long long n = INT64_BITS_COUNT; 
    int c = INT64_BITS_COUNT / 2; 
 
    do { 
        y = x >> c; 
        if (y != 0) { 
            n -= c; 
            x = y; 
        } 
        c >>= 1; 
    } while (c != 0); 
    n -= x >> (INT64_BITS_COUNT - 1); 
    return (INT64_BITS_COUNT - 1) - (n - x); 
} 
 
FileSize NormalizeSize(unsigned long long size) 
{ 
    FileSize result = { 0 }; 
    result.unit = size == 0 ? SizeUnitBytes : ilog(size) / ilog(BINARY_THOUSAND); 
    if (result.unit == SizeUnitBytes) { 
        result.value.sizeInBytes = size; 
    } else { 
        result.value.size = size / pow(BINARY_THOUSAND, result.unit); 
    } 
    return result; 
}
Метки:

Отношение к неудачам
f1
egoroff
Однажды величайший баскетболист мира Майкл Джордан сказал: «Я не попал в корзину более 9000 раз за свою карьеру. Я проиграл почти 300 матчей. 26 раз мне было доверено сделать решающий бросок – и я промазал. Я очень часто терпел неудачи в своей жизни. Именно поэтому я преуспел».

Вот только недавно я понял всю соль этих слов.

Boston Celtics, 5 — Kevin Garnett
f1
egoroff

Метки:

Алгоритм brute force
f1
egoroff
В последнее время мне стало интересно делать разные мелкие программисткие штучки на C. На этот раз тема поста - алгорим взлома пароля методом грубой силы (перебор всех возможных вариантов из словаря). Ниже приведена концепция, т.е. там нет передачи хэша пароля, вычисления хэша варианта и сравнения хэшей, в концепции тупо сравниваются строки (искомый пароль, с вариантом перебора). Алгоритм, вместе с примером использования:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

static char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

int MakeAttempt(int pos, int length, const char *dict, int *indexes, char *pass, const char *desired,
                unsigned long long *attempts, int maxIndex)
{
    int i = 0;
    int j = 0;

    for (; i <= maxIndex; ++i) {
        indexes[pos] = i;

        if (pos == length - 1) {
            for (j = 0; j < length; ++j) {
                pass[j] = dict[indexes[j]];
            }
            ++*attempts;
            /* you may replace this function with the encryption function
               and return in same manner if the encryption string matches
               the one we are cracking */
            if (strcmp(desired, pass) == 0) {
                return 1;
            }
        } else {
            if (MakeAttempt(pos + 1, length, dict, indexes, pass, desired, attempts, maxIndex)) {
                return 1;
            }
        }
    }
    return 0;
}

/*!
* Caller must free memory allocated for the result in case of any
*/
char *BruteForce(int passmin, int passmax, const char *dict, const char *desired, unsigned long long *attempts)
{
    char *pass = (char *)malloc(passmax + 1);
    int *indexes = (int *)malloc(passmax * sizeof(int));
    int passLength = passmin;
    int maxIndex = strlen(dict) - 1;

    memset(pass, 0, passmax + 1);   // IMPORTANT

    for (; passLength <= passmax; ++passLength) {
        if (MakeAttempt(0, passLength, dict, indexes, pass, desired, attempts, maxIndex)) {
            goto cleanup;
        }
    }
    // Nothing found
    free(pass);
    pass = NULL;
cleanup:
    free(indexes);
    return pass;
}

int main(int argc, char *argv[])
{
    char *pass = NULL;
    char *desired = NULL;   // it must be hash but it's plain string to demonstrate concept
    clock_t start = 0;
    clock_t end = 0;
    double elapsed = 0.0;
    unsigned long long count = 0;

    if (argc != 2) {
        printf("\nProof of concept brute force\nby Alexander Egorov\n");
        printf("\nUsage: %s <pass to crack>\n\n", argv[0]);
        return 0;
    }

    start = clock();
    desired = argv[1];
    printf("\nAttempting to brute force \"%s\"\n", desired);
    printf("Should take approximatelly around %.0f trys\n\n", pow(strlen(alphabet), strlen(desired)));

    if (pass = BruteForce(1, strlen(desired), alphabet, desired, &count)) {
        printf("The correct password is \"%s\"", pass);
        free(pass);
    } else {
        printf("Nothing found\n");
    }

    printf("\nNo of trys was %llu\n", count);
    end = clock();
    elapsed = ((double)(end - start)) / CLOCKS_PER_SEC;
    printf("Time elapsed = %.3f seconds\n", elapsed);

    if (elapsed >= 1) {
        printf("Trys per second was %.3f\n", count / elapsed);
    }
    printf("\n");
    return 0;
}

Нормализация времени
f1
egoroff
А точнее говоря, перевод секунд в количество минут, часов. Просто конечно, задача кстати для собеседования по C/С++, но если лень думать, то очень будет кстати.
#define SECONDS_PER_HOUR 3600
#define SECONDS_PER_MINUTE 60

typedef struct Time {
    unsigned long hours;
    unsigned int minutes;
    double seconds;
} Time;

Time NormalizeTime(double seconds)
{
    Time result = { 0 };
    result.hours = seconds / SECONDS_PER_HOUR;
    result.minutes = ((unsigned long long)seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
    result.seconds = ((unsigned long long)seconds % SECONDS_PER_HOUR) % SECONDS_PER_MINUTE;
    result.seconds +=
        seconds - (result.hours * SECONDS_PER_HOUR + result.minutes * SECONDS_PER_MINUTE + result.seconds);
    return result;
}
Метки:

Нормализация размера файла
f1
egoroff
А точнее говоря, перевод размера в байтов в human readable величину в килобайтах, мегабайтах и т.д. Я понимаю что это очень просто но может кому пригодится :)

Основной код:
#include <math.h> 
 
#define BINARY_THOUSAND 1024 
 
typedef enum { 
    SizeUnitBytes = 0, 
    SizeUnitKBytes = 1, 
    SizeUnitMBytes = 2, 
    SizeUnitGBytes = 3, 
    SizeUnitTBytes = 4, 
    SizeUnitPBytes = 5, 
    SizeUnitEBytes = 6, 
    SizeUnitZBytes = 7, 
    SizeUnitYBytes = 8 
} SizeUnit; 
 
typedef struct FileSize { 
    SizeUnit unit; 
    // Union of either size in bytes or size it KBytes, MBytes etc. 
    union { 
        double size; 
        long long sizeInBytes; 
    } value; 
} FileSize; 
 
FileSize NormalizeSize(long long size) 
{ 
    FileSize result = {0}; 
    result.unit = size == 0 ? SizeUnitBytes : floor(log(size) / log(BINARY_THOUSAND)); 
    if (result.unit == SizeUnitBytes) { 
        result.value.sizeInBytes = size; 
    } else { 
        result.value.size = size / pow(BINARY_THOUSAND, floor(result.unit)); 
    } 
    return result; 
}

Использовать можно так:
#include <stdio.h> 
 
static char *sizes[] = { 
    "bytes", 
    "Kb", 
    "Mb", 
    "Gb", 
    "Tb", 
    "Pb", 
    "Eb", 
    "Zb", 
    "Yb" 
}; 
 
void PrintSize(long long size size) 
{ 
    FileSize normalized = NormalizeSize(size); 
    printf(normalized.unit ? "%.2f %s (%lld %s)" : "%lld %s", 
        normalized.value, sizes[normalized.unit], size, sizes[SizeUnitBytes]); 
}

Если размер меньше 1024 байт, будет выведен размер в байтах, если больше, то в килобайтах, мегабайтах и т.д. при этом в скобках будет выведен размер в байтах
Метки:

WTF
f1
egoroff
:) Нашел вчера такое:
try
{
    // A lot of code
}
catch (Exception &exception)
{
    Application->ShowException(&exception);
}
catch (...)
{
    try
    {
       throw Exception("");
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
}

New Year Just Arrived
f1
egoroff

New Year Just Arrived, originally uploaded by egoroff.

Метки:

Рожа
f1
egoroff

Certificate, originally uploaded by egoroff.

Метки: ,

?

Log in

No account? Create an account