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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

[Из песочницы] Почему стоит полностью переходить на Ceylon или Kotlin (часть 1)

Среда, 07 Июня 2017 г. 12:25 + в цитатник

В последнее время активную популярность набирает Kotlin. А что если попробовать выбрать более экзотические языки, и применить к ним те же аргументы? Статья написана по мотивам этой, практически повторяя все аргументы за Kotlin. Основная задача: показать, что Ceylon может практически тоже самое, что и Kotlin, применительно к Java. Но кроме этого у Ceylon есть кое-что еще, что будет описано в следующей статье.


Хочу рассказать о новом языке программирования, который называется Ceylon, и объяснить, почему вам стоит использовать его в своём следующем проекте. Раньше я писал на Java (много и долго, более 10 лет, начиная с Java 1.4 и заканчивая Java 8), и Java мне нравилась. Затем на меня большое впечатление произвела Scala, в результате чего Java как язык стал любить несколько меньше. Но судьба свела меня с языком Сeylon, и в последние полтора года мы пишем на Ceylon везде, где только можно. В реальных коммерческих проектах, правда внутренних. И в данный момент я не представляю себе ситуации, в которой лучше было бы выбрать Java, я не рассматриваю Java как язык, на котором стоит начинать новые проекты.


Ceylon разработан в Red Hat, автор языка — Gavin King, известный по такому фреймворку как Hibernate. Он создавался людьми, которые хорошо понимают недостатки Java, основная цель заключалась в решении сугубо прикладных задач, обеспечение максимально легкой читаемости кода, избегание любых неоднозначностей и подводных камней, во главу всего стала предсказуемость и структурная красота языка. Также большое внимание уделялось приемлемому времени компиляции. В настоящее время версия языка 1.3.2, непосредственно я познакомился с языком, когда вышла версия 1.2.0.


Хотя Ceylon компилируется в JavaScript, я сконцентрируюсь на его первичной среде — JVM.


Итак, несколько причин, почему вам следует полностью переходить на Ceylon (порядок совпадает с одноименными пунктами соответствующей Kotlin статьи):


0# Совместимость с Java


Также, как и Kotlin, как и Scala, Ceylon на 100 % совместим с Java. Вы можете в буквальном смысле продолжать работать над своим старым Java-проектом, но уже используя Ceylon. Все Java-фреймворки также будут доступны, и, в каком бы фреймворке вы ни писали, Ceylon будет легко принят упрямым любителем Java. Можно без проблем вызывать из Java Ceylon код, также без проблем вызывается Java код.


1# Знакомый синтаксис


Одна из основных особенностей языка Ceylon — максимально удобно читаемый для существующих разработчиков синтаксис. Если взять существующего Java разработчика, то с пониманием Ceylon синтаксиса у него не будет ни малейших проблем. Даже такие языки, как Scala и Kotlin будут менее похожи на Java. Ниже приведен код, показывающий значительное количество конструкций языка, аналогичный примеру на Kotlin:


class Foo(String a) {

    String b= "b";           //  unmodifiable
    variable Integer i = 0;  // variable means modifiable

    void hello() {
        value str = "Hello";
        print("``str`` World");
    }

    Integer sum(Integer x, Integer y) {
        return x + y;
    }

    Float maxOf(Float a, Float b) => if (a > b) then a else b
}

Соответственно можно без проблем продолжать писать в Java стиле на Ceylon.


2# Интерполяция строк


Это как бы более умная и читабельная версия String.format() из Java, встроенная в язык:


value x = 4;
value y = 7;
print("sum of ``x`` and ``y`` is ``x + y``") ; // sum of 4 and 7 is 11

ИМХО синтаксис здесь будет поприятнее, чем в Kotlin, с Java даже не хочется сравнивать.


3# Выведение типа


Ceylon будет выводить ваши типы, если вы посчитаете, что это улучшит читабельность:


value a = "abc";                         // type inferred to String
value b = 4;                             // type inferred to Integer

Float c = 0.7;                   // type declared explicitly
List d = ArrayList();     // type declared explicitly

4# Умные приведения типов (Smart Casts)


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


if (is String obj) {
    print(obj.uppercased)     // obj is now known to be a String
}

5# Интуитивные равенства (Intuitive Equals)


Можно больше не вызывать явно equals(), потому что оператор == теперь проверяет структурное равенство:


value john1 = Person("John"); //we override equals in Person
value john2 = Person("John");
print(john1 == john2);    // true  (structural equality)
print(john1 === john2);    // false  (referential equality)

6# Аргументы по умолчанию


Больше не нужно определять несколько одинаковых методов с разными аргументами:


void build(String title, Integer width = 800, Integer height = 600) {
    return Frame(title, width, height);
}

7# Именованные аргументы


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


build("PacMan", 400, 300)                           // equivalent
build {title = "PacMan"; width = 400; height = 300;}  // equivalent
build {title = "PacMan"; height = 300;}  // equivalent with default width

8# Выражение switch


Оператор ветвления заменён гораздо более читабельным и гибким в применении выражением switch:


switch (obj)
case(1)                              { print("x is 1"); }
case(2)                              { print("x is 2"); }
case(3 | 4)                          { print("x is 3 or 4"); }
case(is String)                      { print ("x is String"); }
case([Integer a, Float b, String c]) {print ("x is tuple with Integer ``a``, Float ``b`` and String ``c``");}
else                                 { print("x is out of range");}

switch может работать как выражение, также результат switch может быть присвоен переменной:


Boolean|IllegalStateException res = 
    switch(obj)
    case(null) false
    case(is String) true
    else IllegalStateException();

Это не полноценный pattern matching, но для большинства случаев хватает и текущего функционала.


В отличие от Kotlin у Ceylon требуется, чтобы к switch все условия были disjoint, то есть не пересекались, что для switch гораздо более логично. Если требуется сопоставление по диапазону или условия могут пересекаться, то нужно использовать обычный if.


9# Свойства


Можно добавить публичным полям кастомное поведение set & get, т. е. перестать набивать код безумными геттерами и сеттерами.


class Frame() {
    variable Integer width = 800;
    variable Integer height = 600;

    Integer pixels => width * height;
}

10# Data Class


К сожалению данного функционала пока нет. Очень хотелось бы иметь иммутабельные классы, у которых автоматом переопределен toString(), equals(), hashCode() и copy(), но, в отличие от Java, не занимали 100 строк кода.


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


class Person(shared String name, 
             shared String email,
             shared Integer age) extends DataObject() {}

value john = Person("John", "john@gmail.com", 112);
value johnAfterBirhstday = john.copy({`Person.age`->113;});
assertEquals(john, john.copy());
assertEquals(john.hash, john.copy().hash);

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


11# Перегрузка оператора (Operator Overloading)


Заранее определённый набор операторов, которые можно перегружать для улучшения читабельности:


class Vec(shared Float x, shared Float y) satisfies Summable {
    shared actual Vec plus(Vec v)  => Vec(x + v.x, y + v.y);
}

value v = Vec(2.0, 3.0) + Vec(4.0, 1.0);

12# Деструктурирующие объявления (Destructuring Declarations)


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


for ([key -> [val1, val2, val3]] in map) {
    print("Key: ``key``");
    print("Value: ``val1``, ``val2``, ``val3``");
}

13# Диапазоны (Ranges)


Для улучшения читабельности:


for (i in 1..100) { ... } 
for (i in 0 : 100) { ... }
for (i in (2..10).by(2)) { ... } 
for (i in 10..2) { ... }  
if (x in 1..10) { ... }

В отличие от Kotlin обошлось без ключевого слова downTo.


14# Функции-расширения (Extension Functions)


Их нет. Возможно появится, в ранних спецификациях языка такая возможность рассматривалась. Но вместо функций расширений в принципе работают top level функции. Если мы, допустим, хотим добавить к классу String метод sayHello, то "world".sayHello() выглядит не намного лучше чем sayHello("world"). В будущем они могут появиться.


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


15# Безопасность Null


Java следует называть почти статично типизированным языком. Внутри него переменная типа String не гарантированно ссылается на String — она может ссылаться на null. И хотя мы к этому привыкли, это снижает безопасность проверки на статичное типизирование, и в результате Java-разработчики вынуждены жить в постоянном страхе перед NPE.


В Ceylon эта проблема решена посредством разделения на типы, допускающие и не допускающие значение null. По умолчанию типы не допускают null, но их можно преобразовать в допускающие, если добавить ?:


variable String a = "abc";
a = null;                // compile error

variable String? b = "xyz";
b = null;                // no problem

За счет функционала union types String? это просто синтаксический сахар для String|Null. Соответственно можно написать:


variable String|Null с = "xyz";
с = null;                // no problem

Ceylon заставляет вас бороться с NPE, когда вы обращаетесь к типу, допускающему null:


value x = b.length        // compile error: b might be null

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


if (!exists b) { return; }
value x = b.length        // no problem

Также можно использовать безопасный вызов ?., он возвращает значение null вместо бросания NPE:


value x = b?.length;       // type of x is nullable Int

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


value name = ship?.captain?.name else "unknown";

Если всё это вам не подходит и вам совершенно точно нужны NPE, то скажите об этом явно:


value x = b?.length else NullPointerException()  // same as below
assert(!NullPointerException x);

16# Улучшенные лямбды


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


value sum = (Integer x, Integer y) => x + y;  // type: Integer(Integer, Integer)
value res = sum(4,7)                      // res == 11

Соответственно синтаксис может быть:


numbers.filter( (x) => x.isPrime() );
numbers.filter(isPrime)

Это позволяет нам писать лаконичный функциональный код:


    persons
        .filter ( (it) => it.age >= 18)
        .sort(byIncreasing(Person.name))
        .map ( Person.email )
        .each ( print );

Система лямбд плюс синтаксические особенности языка, делает Ceylon неплохим инструментом для создания DSL. Пример DSL, похожего на Anko, в синтаксисе Ceylon:


 VerticalLayout {
    padding = dip(30);  {
    editText {
        hint = "Name";
        textSize = 24.0;
    },
    editText {
        hint = "Password";
        textSize = 24.0;
    },
    button {
        "Login";
        textSize = 45.0;
    } }
};

17# Поддержка IDE


Между прочим, она достаточно неплохая. Есть eclipse плагин, есть IDEA плагин. Да, по части фич и багов все несколько хуже, чем в Scala или Kotlin. Но в принципе работать можно и достаточно комфортно, проблемы IDE на скорости разработки практически не сказываются.


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


Ну и так же, как и на Kotlin, на Ceylon можно писать для Android.


Прочитав вышесказанное, может сложиться впечатление — а зачем нам это? Тоже самое есть и в Kotlin, практически 1 в 1.


А то, что в Ceylon есть вещи, которых нет ни в Kotlin, ни в Scala, и за счет этих вещей сам язык во многом гораздо лучше, чем другие языки. Например union types, intersection types, enumerated types, более мощные generics, модульность, herd, аннотации и метамодель, кортежи, for comprehensions. Что реально меняет подход к программированию, позволяет писать гораздо более надежный, понятный и универсальный код. Но об этом в следующей части.


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

https://habrahabr.ru/post/330412/


Метки:  

Rapid STP

Среда, 07 Июня 2017 г. 12:22 + в цитатник

Протоколы семейства STP обычно несильно будоражат умы инженеров. И в большинстве своём на просторах интернета чаще всего сталкиваешься с деталями работы максимум протокола STP. Но время не стоит на месте и классический STP всё реже встречается в работе и в различных материалах вендоров. Возникла идея сделать небольшой обзор ключевых моментов RSTP в виде FAQ. Всем, кому интересен данный вопрос, прошу под кат.

Что настраивать STP, RSTP или MST?

В современных стандартах протокол STP уже нигде не фигурирует. Известный всем 802.1d в последней редакции (802.1d-2004) описывает протокол RSTP. При этом MST перекочевал в 802.1q (802.1q-2014). Как мы помним, ранее RSTP описывался стандартом 802.1w, а MST — 802.1s.

RSTP и MST имеют существенно меньшее время сходимости. Они намного быстрее перестраивают топологию сети в случае отказа оборудования или каналов связи. Время сходимости для ряда отказов этих протоколов меньше 1 секунды против 30+ секунд в случае STP. Поэтому классический STP рекомендуется использовать только там, где задействуется старое оборудование, не поддерживающее более современные протоколы.

MST в своей работе использует алгоритмы RSTP. Но в отличие от RSTP, MST позволяет создавать отдельную топологию (instance) STP для группы VLANов. В случае обычного RSTP у нас на все VLANы одна общая топология. Это не очень удобно, так как не позволяет даже в ручном режиме балансировать трафик по разным каналам. А значит, мы теряем, как минимум половину пропускной способности в случае наличия избыточных путей.

Некоторые вендоры (в частности Cisco) предлагают ещё одну разновидность быстрого протокола STP – Rapid Per-VLAN Spanning Tree (PVRST+). В этом случае для каждой виртуальной сети строится своя топология, что позволяет более эффективно утилизировать каналы. Основной минус такого подхода – это ограничение на максимальное количество таких топологий. Для обеспечения работы каждой топологии устройство тратит аппаратные ресурсы. А они не безграничны. Например, в коммутаторах Cisco 2960 поддерживается максимум 128 «инстансов» STP.

Таким образом, MST является хорошей альтернативой между стандартным RSTP и проприетарным PVRST+. Особенно если наша сеть построена на базе коммутаторов разных производителей. Стоит заметить, что все три вариации быстрого STP совместимы друг с другом.

В дальнейшем, упоминая RSTP, мы будем подразумевать в том числе и его расширения MST/PVRST+.

Какие технологии обеспечивают быстроту реакции в работе RSTP?

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

  1. Генерация BPDU сообщений каждым устройством независимо от корневого коммутатора.

    В классическом варианте BPDU «генерит» в сети только корневой коммутатор. Все остальные устройства лишь ретранслируют его. Таким образом, отсутствие BPDU от вышестоящего устройства значит, что проблема может быть в любом месте между данным устройством и корневым коммутатором. Поэтому приходилось ждать достаточно долго (MaxAge=20 сек) прежде чем, смириться с тем, что что-то пошло не так и нужно перестраивать топологию.

    В случае RSTP сообщения BPDU стали выполнять роль Hello-пакетов. Теперь потеря трёх таких пакетов (а это 2*3=6 сек) означает, что пора задуматься об изменениях в топологии.

  2. Механизм Proposal/Agreement при активации соединения точка-точка на не Edge-портах для быстрого перехода в состояние передачи (Forwarding).

    Примечание
    RSTP предусматривает два типа соединения:
    • точка-точка (point-to-point) – к такому порту подключен только один RSTP коммутатор;
    • общий (shared) — к такому порту подключено несколько RSTP коммутаторов (через хаб, что в наше время является большой экзотикой).

    Обычно коммутаторы определяют тип соединения автоматически, опираясь на режим передачи full-duplex (точка-точка) или half-duplex (общий). В случае соединения shared «фишечки» RSTP перестают работать.

    В классическом STP порт, который должен стать корневым, проходит все стадии по переходу в режим передачи (Listening -> Learning -> Forwarding), что занимает более 30 секунд.

    Прежде чем коснуться механизма Proposal/Agreement, нужно отметить два разных типа портов в RSTP: пограничный порт (Edge port) и не пограничный (non-Edge port). В Edge порт подключаются оконечные устройства (ПК, серверы, в ряде случаев маршрутизаторы и пр.). В не Edge-порт подключаются другие коммутаторы, участвующие в топологии STP.

    Примечание
    Тип порта Edge задаётся вручную. Коммутатор не может быстро определить, кто к нему подключен: обычный хост или коммутатор. Конечно, он мог бы ориентироваться на наличие BPDU на этом порту. Но по стандарту коммутатор должен обязательно подождать минимум 15 секунд (Forward delay) прежде, чем решить, что на его порт так и не пришло ни одно сообщение. А это слишком долго. Поэтому право определить, что подключено к порту, доверили человеку.

    На коммутаторах Cisco тип порта Edge задаётся командой spanning-tree portfast.

    RSTP использует механизм Proposal/Agreement для быстрого переходя портов из состояния Discarding в состояние Forwarding. Этот механизм запускается, когда у коммутатора меняется Root Port (как минимум при включении в сеть). В этом случае он выключает все порты, не являющиеся Edge-портами. Об этом оповещает вышестоящий коммутатор (куда как раз смотрит Root port), после чего включает в режим Forwarding только Root port. Остальные порты (не Edge) находятся в заблокированном состоянии, пока не произойдёт одно из двух:

    • коммутатор обменяется сообщениями Proposal/Agreement с нижестоящим коммутатором,
    • истекут таймеры перехода из стояния Discarding в Learning (15 сек) и из Learning в Forwarding (15 сек), если подключённое оборудование не поддерживает RSTP.

    Сообщение Proposal отправляется портом, который хочет стать назначенным (Designated) для данного сегмента сети. И фактически запускает механизм Proposal/Agreement. Сообщение Agreement отправляется портом, который становиться корневым (Root). Оно необходимо для оповещения вышестоящего устройства о возможности немедленно перевести порт в состояние Forwarding.

  3. Механизм альтернативного порта при потере связи через корневой порт.

    RSTP отличается от STP тем, что состояние порта отвязали от его роли. Это позволило описать роль порта в топологии сети без оглядки на его состояние. А значить обладать лучшим видение топологии сети и возможностью оперативно реагировать на изменения в ней. Так появились альтернативный (alternative) и резервный (backup) порты. Альтернативный порт – замена корневому. Через него может быть достигнут корневой коммутатор, но при этом данный порт не имеет роли корневого (т.е. получает BPDU c худшей метрикой) и не является назначенным (т.е. не является лучшим в данном сегменте сети для достижимости корневого устройства).

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


  4. Механизм немедленной реакции на получение BPDU с информацией о «худшем» корневом коммутаторе от соседа, имеющего назначенный (designated) порт для данного сегмента сети.

    В такой ситуации, если у устройства есть другой маршрут к корневому коммутатору, в классическом STP порт, который ранее был заблокирован, пройдёт все стадии и переключится в режим передачи только через 50 секунд (MaxAge + 2x Forward Delay).

    В случае RSTP коммутатор немедленно оценит полученный BPDU (в RSTP нет MaxAge таймера) и начнёт передавать свои, выставив флаг Proposal. Получив такое BPDU, коммутатор, потерявший связь с «рутом», примет участие в механизме Proposal/Agreement, так как у него сменился корневой порт. А дальше достаточно оперативно порты на обоих коммутаторах перейдут в состояние передачи.

  5. Улучшенная схема рассылки и обработки сообщений TCN BPDU об изменениях в сети.

    Классический STP считает, что топология изменилась, если порт перешёл из состояния заблокированный в состояние передачи или наоборот. Так как изменение топологии может привести к тому, что MAC адреса станут доступны через другие порты (а значит, коммутатор будет слать пакеты не туда), запускается процедура оповещения всех устройств о таком событии. Для этого рассылается сообщение Topology Change Notification (TCN). Получив которое, коммутатор меняет время старения MAC адресов со значения по умолчанию (300 сек) на 15 сек (Forward Delay). Сообщение TCN рассылается в два этапа. Сначала коммутатор, обнаруживший изменения в топологии, отправляет его в сторону корневого коммутатора. Далее корневой коммутатор, получив такое сообщение, узнаёт об изменении в сети и рассылает TCN сообщение (BPDU с соответствующим флагом) уже всем остальным. Двухуровневая схема необходима, так как BPDU в классическом варианте отправляется только корневым коммутатором.

    В случае RSTP изменением в топологии считается только переход порта в режим передачи. Причём учитываются порты, которые не являются пограничным (non-edge port). Это и логично, так как переход порта в заблокированное состояние автоматически делает MAC адреса за ним больше не доступными. Как только обнаружено изменение топологии, коммутатор рассылает через все порты (корневой и назначенные) BPDU c флагом TC. Такое сообщение быстро распространяется по сети. Получив его, коммутаторы удаляют из таблицы все MAC адреса доступные через не edge порты, за исключением того, где был получен BPDU c флагом TC.

    Edge порт никогда не вызывает изменений в топологии, а также для такого порта не сбрасываются MAC адреса в случае получения BPDU c флагом TC.

Почему RSTP иногда «тормозит» и переводит порт в режим передачи трафика только через несколько десятков секунд?

RSTP в своей работе использует обычные таймеры в следующих случаях:

  • К порту подключается устройство, поддерживающее только классический STP. В этом случае порт коммутатора из режима работы RSTP переходит в режим STP. А значит проходит все стандартные для STP стадии: Blocking, Listening, Learning, Forwarding (в зависимости от того, с какими значениями корневого коммутатора и стоимости будет получен BPDU).

  • Коммутатор определил соединение как shared. В этом случае используются стандартные таймеры RSTP. Так как к такому порту подключено два и более коммутатора, задействовать механизм Proposal/Agreement невозможно.

  • Подключено устройство, не участвующее в STP, и на порту не задан тип edge. В этом случае порт пройдёт следующие стадии RSTP: Discarding (15 секунд), Learning (15 секунд), Forwarding. Таким образом, он перейдёт в режим передачи только через 30 секунд.

Почему задание типа порта Edge более важно для RSTP, чем для STP?

Деление на порты Edge и non-Edge характерно не только для RSTP, но и для STP. Но в случае STP – это вендорная доработка протокола, нежели требования стандарта.

Основные «ЗА» включения на порту режима Edge (для оборудования Cisco – это portfast) в случае использования протокола STP:

  • Быстрое переключение порта в режим передачи (Forwarding). Порт в этом случае не проходит стандартные стадии на базе таймеров. Это важно, если к такому порту подключено обычное оборудование. Например, сервер или ПК.
  • Не происходит уменьшение времени старения MAC адресов за таким портом при получении сообщения TCN. А значит меньше вероятность фладинга пакетов для хостов, которые больше слушают, чем что-то сами отправляют.

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

  • При срабатывании механизма Proposal/Agreement блокируются все не Edge-порты. А это значит, что если мы не настроим обычный порт, куда подключено оконечное оборудование, в режим Edge, коммутатор будет выключать его на 30 секунд (работа RSTP по таймерам) каждый раз, когда меняется root port. В простых сетях это происходит не часто. Но в относительно большой легко. Это как раз тот случай, когда кажется, что перестроения произойдут в сети достаточно быстро, и никто этого даже не заметит. А по факту устройства «отваливаются» от сети на полминуты.

Таким образом, можно сделать вывод: для RSTP отсутствие настройки Edge-порта более критично, чем для классического STP.

Примечание
С настройкой порта в режиме Edge нужно быть аккуратными.

Давайте посмотрим на поведение коммутатора Cisco с портом в режиме portfast (Edge). Порт сразу переходит в режим передачи. Но он продолжает участвовать в передаче BPDU и главное продолжает слушать сеть на наличие BPDU от других устройств, на случай если по ошибке к нему подключили другой коммутатор. Если вдруг приходит BPDU, порт теряет свое состояние portfast и проходит стандартные фазы RSTP. Так в чём же может быть проблема?

BPDU отправляются в диапазоне от 0 до 2 секунд после включения порта. Плюс можно добавить к этому время распространения BPDU по сети (актуально для STP). Поэтому в течение нескольких секунд в сети может быть петля. Если трафика будет очень много, этих секунд может оказаться достаточно, чтобы широковещательный шторм, порождённый петлёй, «убил» control-plane нашего коммутатора. Чтобы этого не допустить рекомендуется portfast настраивать в связке с дополнительными технологиями, например: BPDU Guard и storm-control.

Если сеть многовендорная, причём часть оборудования вообще не поддерживает STP ни в каком виде, всё будет плохо?

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

Если коммутатор не поддерживает STP ни в каком виде, что же он будет делать с BPDU пакетами? Ответ прост – передавать такие пакеты через все порты. В качестве MAC адреса назначения PBDU пакета STP и RSTP устанавливают адрес 0180.C200.0000, который является multicast адресом. Такой BPDU пакет передаётся в рамках VLAN 1.

Примечание
Протокол MST данные обо всех топологиях упаковывает в один PBDU (кстати, именно поэтому максимальное количество инстансов для MST — 64). В качестве адреса назначения используется стандартный MAC-адрес 0180.C200.0000.

Протоколы PVST+ и PVRST+ в своей работе используют два типа BPDU:

  • IEEE-formatted BPDU для совместимости с другими версиями STP, содержит данные топологии STP для VLAN 1. В качестве адреса назначения используется стандартный MAC-адрес 0180.C200.0000.
  • PVST+ BPDU, которые содержат данные топологии STP для разных VLANов. В качестве адреса назначения используется MAC-адрес 0100.0CCC.CCCD.

Ещё один занятный монет связан с тем, что даже если мы исключим VLAN 1 из транка между коммутаторами, BPDU для первого VLAN всё равно будут передаваться.

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


А что произойдёт, если соединить два порта между собой на коммутаторе SW1 (т.е. сделать кольцо). Наша сеть погибнет? Есть большой шанс, что нет. В этом случае Root SW получит собственный BPDU на тот же порт, с которого его отправил. После этого он сразу же его заблокирует. И петля останется «жить» только в пределах коммутатора SW1. Но положительный исход возможет, только если Root SW раньше времени не «захлебнётся» от широковещательного шторма, появившегося вследствие петли на SW1. Поэтому лучше не использовать в сети коммутаторы, не поддерживающие STP.

Нужен ли STP/RSTP/MST/… в сети, если там нет петель?

Безусловно. Если петли нет сейчас, не факт, что она не появится в будущем. Например, из-за простой человеческой ошибки, когда один access-порт коммутатора подключается к другому access-порту того же устройства.

Данный FAQ не претендует на полноту. Он носит скорее ознакомительный характер и задаёт некий вектор дальнейших изысканий по тому или иному вопросу, связанному с работой современных протоколов семейства STP.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330358/


Метки:  

Huginn: простая интеграционная платформа

Среда, 07 Июня 2017 г. 12:17 + в цитатник
В мире API, сервисных архитектур и облачных решений многое доступно вообще без программирования. Однако, компании все еще тратят драгоценное время разработчиков на рутинные задачи по интеграции. Мы хотим рассказать об одной из платформ, которая позволяет нам подключить новомодный маркетинговый сервис или проверить гипотезу максимально быстро и без участия разработки.


Всем привет! Меня зовут Юра Буйлов, и я отвечаю за разработку в CarPrice. Компания развивается динамично, поэтому скорость проведения экспериментов для нас играет важную роль. Сегодня хочу рассказать о простом инструменте, который избавляет разработчиков от бесконечного потока простых однотипных задач по интеграции с внешними сервисами.

Мотивация. Почему Huginn


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

  1. поступила жалоба от клиента
  2. зафиксировать факт в журнале
  3. отправить сообщение в Telegram



Мы уже активно использовали Zapier для подобных задач, но нам важны self-hosting, масштабируемость и отсутствие ограничений по количеству обрабатываемых задач. Так мы стали искать инструмент для простых и быстрых интеграций, который был бы полезен и менеджерам, и разработчикам. Сам подход не нов и напоминает упрощенную реализацию EIPs (Enterprise Integration Patterns). Естественно, мы попробовали несколько решений из мира “кровавого энтерпрайза” (Mulesoft, Jboss Fuse, WSO2, Servicemix, Corezoid). Вели переговоры с вендорами проприетарного ПО. Все не то: долго, дорого, сложно или неудобно.

Так мы пришли к Huginn.

  • OpenSource – более 16k звёзд на github.
  • Написан на RoR – можно дорабатывать и писать свои компоненты.
  • Легко разворачивается и масштабируется.
  • Имеет низкий порог вхождения.

Где использовать Huginn


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

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


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

  • публикация аукционов во внутренний Telegram-канал,
  • триггерные уведомления: жалобы, нарушения, пики и просадки в метриках,
  • пуш данных во внешние системы, такие как exponea, expertsender или piwik.

Что такое Huginn


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

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

  • Webhook Agent – принимает POST запросы от внешних источников.
  • Post Agent, Website Agent – отправляет запросы на указанный урл, парсит JSON, HTML или XML.
  • DeDuplication Agent – не пропускает дубли событий по уникальному ключу.
  • Event Formatting Agent – позволяет перемапить поля в сообщении.
  • JavaScript Agent – выполняет произвольный JS код (V8, therubyracer).

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

Как оказалось, большинство кейсов мы покрываем тремя агентами:

  • Mysql2Agent – поллим базу на наличие изменений. Для каждой строки выборки будет сгенерировано событие и передано дальше по цепочке.
  • EventFormatting – форматируем входящее сообщение с использованием liquid шаблонов.
  • JsonAPIAgent – вызвать внешнее или внутреннее API для получения/отправки данных.

Примеры использования


Публикация новых аукционов в Telegram-канал


Ниже представлена одна из первых реализованных цепочек. Агент ежеминутно проверяет новые аукционы в БД по created_at, далее по внутреннему API получает всю информацию по авто и отправляет сообщение в Telegram.



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

Персональные рекомендации по sms


Ниже пример реализации эксперимента по доставке персональных рекомендаций дилерам по sms. Для каждого нового аукциона получаем по API внутренней рекомендательной системы (LSTM RNN) список дилеров, из БД получаем номер телефона, сокращаем ссылку на аукцион с помощью urlshortener и отправляем sms через внешний сервис рассылки.



Интеграция с маркетинговыми инструментами


Далее представлена часть схемы интеграции с маркетинговыми инструментами – сервисом exponea. В ходе ее реализации ни один разработчик не пострадал – реализация и поддержка силами одного менеджера.



Развернуть и попробовать


Самый простой способ попробовать Huginn – развернуть его в docker.

docker run -it --name huginn \
    -p 3000:3000 \
    -e ADDITIONAL_GEMS="huginn_mysql2_agent(git: https://github.com/yubuylov/huginn_mysql2_agent.git),huginn_jsonapi_agent(git: https://github.com/yubuylov/huginn_jsonapi_agent.git)" \
    huginn/huginn

http://localhost:3000/
Логин: admin, Пароль: password

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

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

Полезные ссылки


-> Оф.репозиторий
-> Установка в docker
-> Production environment
-> Список агентов
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330382/


Метки:  

Задай вопрос разработчикам облачных сервисов Mail.Ru Group

Среда, 07 Июня 2017 г. 11:57 + в цитатник


Благодаря Reddit становится популярен формат Ask Me Anything (AMA) — когда команда специалистов, ответственных за какой-то большой, популярный проект, предлагает всем желающим задавать им любые вопросы об их работе и о том, что у сервиса «под капотом», как всё устроено. Первыми формат AMA на Хабре использовали разработчики Badoo. Мы тоже решили попробовать. Надеемся, что другие компании последуют нашему примеру и начнут впускать читателей на свои внутренние кухни.


Стартовать AMA мы решили с командой Облака Mail.Ru. Это молодой, активно развивающийся проект, о котором нам всегда задают много вопросов. К тому же с момента запуска (с августа 2013 года) Облако разрослось в большую семью проектов.


Исторически Облако начиналось как B2C-продукт с веб-, десктопной и мобильными версиями. Однако B2B — это тоже очень перспективный рынок. Поэтому у нас появилась платформа Mail.Ru для бизнеса, объединяющая все B2B-сервисы компании Mail.Ru Group, в том числе Облако для архивов (Icebox), Облако для рабочих групп (Teambox) и Горячее хранилище (Hotbox).


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


Для начала немного истории


Когда мы начинали писать Облако, то взяли за основу единую кодовую базу, которая использовалась и в Почте, и в Моём Мире, и в контентных проектах. Эту кодовую базу мы называем Mpop. Она представляет собой кучу библиотек, написанных на Perl. И несколько лет назад на ней жили все портальные проекты Mail.Ru Group. Когда в каком-то из проектов что-то рефакторили в Mpop, это влияло и на остальные. Постепенно каждый проект переехал на свою версию Mpop, а затем мы начали от неё уходить. Почта, например, частично перешла на Go. Мы тоже изначально жили на Mpop, но потихонечку всё переписали на свой супербыстрый Perl-сервер. У нас полностью асинхронная архитектура, мы используем AnyEvent. И если вы знаете Perl, то приходите к нам, у нас очень весело и интересно!


Как всё устроено


Структурно Облако Mail.Ru состоит из нескольких команд:


  • Команда, которая пишет серверную часть и выстраивает её взаимодействие с хранилищами и мобильными клиентами.
  • Команда разработки API, прослойки между серверами и вебом. API пользуются и Icebox, и Teambox.
  • Команда разработки Hotbox. Она разрабатывает как административный интерфейс для работы с бакетами и ключами в Hotbox, так и само S3 API.
  • Команда разработки UI (пользовательского интерфейса) и вёрстки. Отвечает за красоту интерфейса, его стабильность, скорость и функциональность.
  • Команда разработки десктопного клиента, которая делает облачный клиент под платформы Windows, Linux, macOS. Также эта команда работает над Скриншотером и разнообразными фичами под него.
  • Две команды мобильной разработки, которые пишут клиентские приложения для iOS и Android, напрямую взаимодействующие с серверной частью.
  • Команда админов, которая всё это поддерживает, не смыкая глаз днями и ночами.
  • Также у нас есть команда тестирования и команда автотестирования, которая пишет автотесты для API.

Под капотом веб- и десктопной версий Облака


Бэкенд Облака Mail.Ru написан на ANSI C, Perl, Lua и немного С++. На Perl решаются задачи, связанные с API. Например, редактирование документов. К слову, мы когда-то рассказывали на Хабре о том, как показываем видео в Облаке, серверная часть там написана на Perl + Lua.


С самого начала, когда ставилась задача создать Облако, одним из главных требований было отсутствие долгих поисков по БД, никаких seek по диску и хранения по принципу append only. На момент старта мы не нашли подходящей БД под древовидные данные, поэтому создали собственную для представления файловой системы.


Приведём немного чисел:


  • В день наши юзеры загружают порядка 100 терабайт данных.
  • У нас есть более тысячи серверов дисковых хранилищ — это более 100 петабайт данных, в них находится более 9 миллиардов файлов. Нужно оптимально обходить и верифицировать их и быть уверенными в том, что пользовательский контент хранится надёжно и без изменений.
  • Число активных пользователей ежемесячно — более 18 миллионов. Каждый день на веб заходит много сотен тысяч уников.
  • Мы меняем в среднем десять дисков в неделю, на них заново накатываем данные.
  • Пропускная способность сети — до 200 Гбит/c (при необходимости мы можем увеличить её в несколько раз). На закачку к нам сейчас идёт около 25 Гбит/с.

Изначально Облако писалось с фокусом на десктопные и мобильные клиенты. Затем стало ясно, что веб-то жжот, нужно переделывать. Облако полностью переписали асинхронно (вообще у нас вся кодовая база асинхронная, от ANSI C до AnyEvent в Perl), стало намного лучше и быстрее. Например, сейчас веб-версия Облака живёт на том же десятке серверов, что и три года назад, при том, что число пользователей существенно выросло. Только тогда они лежали в полке по ресурсам без какого-либо запаса. Другие наши новые продукты, например Hotbox, мы тоже пишем на Perl. Такие дела.


Под капотом мобильного Облака


Для написания iOS-приложения Облака мы продолжаем использовать Objective-C. Swift пока не трогаем по ряду причин:


  1. Мы всё ещё поддерживаем iOS 7. Да, Swift уже поддерживается на этой версии операционки, но работать со Swift’овыми зависимостями весьма затруднительно.
  2. Swift всё ещё нестабилен, и нам не хочется повторять героические подвиги по адаптации новых версий языка, хорошо описанные командой разработчиков Firefox.
  3. Использование Swift в данный момент существенно увеличивает размер приложения, а мы гордимся тем, что весим всего около 20 Мб.
  4. Мы активно используем динамические свойства языка Objective-C, а в Swift аналогов нет.

В качестве примеров применения динамизма Objective-C приведём следующие:


  1. Написание юнит-тестов на утечки памяти. Это возможно благодаря нашей библиотеке POSAllocationTracker. Возможность использования в юнит-тестах выгодно отличает её от фейсбучного аналога в лице FBAllocationTracker.
  2. Автоматическое обнаружение доступа к объекту из неправильного потока. Имплементировано в объекте POSSchedulableObject из библиотеки POSRx. Кстати, в ней вы можете посмотреть на боевые примеры юнит-тестов на утечки памяти.

Другие архитектурные особенности iOS-приложения:


  • Использование POSInputStreamLibrary для загрузки видеофайлов в Облако. На графике ниже отображаются два вида загрузок видеофайлов. Оранжевые столбы — загрузки, содержимое которых получено с помощью API Photos.framework. Синие столбы — содержимое получено с помощью ALAssetsLibrary и завёрнуто в POSInputStreamLibrary. Это делает загрузку тяжёлых видеофайлов экстремально быстрой, как было описано в нашей давней статье.


  • Использование disaster recovery тестов. В нашу сетевую библиотеку встроен механизм генерации случайных сетевых ошибок. Таким образом, в отладочной сборке приложению обязательно прилетят от сервиса пятисотки и четырёхсотки. Благодаря этому практически невозможно не протестировать каждую новую фичу на данные краевые случаи. Имплементация доступна в наглядном виде в объекте POSHTTPGateway из библиотеки POSRx.

Главная архитектурная задача для iOS приложения на сегодняшний день — избавление от подвисаний приложения при работе с большими облаками. В качестве инструмента для решения данной проблемы мы видим паттерн Schedulable Architecture, о котором мы не так давно писали на Хабре. Чтобы по мере его внедрения немедленно видеть результаты и быть уверенными, что движемся в правильном направлении, мы сделали мониторинг подвисаний. Сейчас у нас уже есть график самых проблемных мест в виде списка классов, в которых чаще всего происходят зависания. Выглядит он так:



Благодаря плагину для HockeyApp у нас есть полная информация о каждом зависании — стек вызовов и логи.


Android-клиент Облака полностью разработан на Java (мы пока не нашли для себя выгоды в Kotlin’e). В принципе, в архитектуре нет ничего супермодного: MVP, весь сетевой слой в сервисе, для сети используем okhttp, данные храним в SQLite, за исключением галереи. Там может быть очень много данных, и их надо быстро поднимать из кеша. Поэтому для галереи мы применяем самописную сериализацию. Для коммуникации внутри приложения есть eventbus от green robot. Для эффективной работы в фоне на новых версиях андроида используем JobScheduler’ы, а для не очень новых — GcmNetworkManager.


Для выкатки фич на процент, A/B тестирования и части аналитики используем Firebase. Для отладки взаимодействия с сервером юзаем в дебажных сборках Stetho от Facebook. В последней версии почти перешли на векторную графику в приложении. Думаю, через пару версий полностью перейдём на неё. Тесты пишем на junit, uiautomator и espresso.


Под капотом B2B-Облака


B2B-Облако — это три разных продукта:


  • Teambox — облако для рабочих групп, аналог B2C-Облака, в котором можно выделить личное пространство для каждого аккаунта в домене, создавать общие папки для отделов и групп сотрудников и настраивать доступ к файлам.
  • Hotbox — хранилище с быстрым доступом для распространения медиа- и любого другого часто скачиваемого контента с S3-совместимым протоколом доступа, распределённым хранением с множественным копированием и гарантированным SLA 99,99 %.
  • Icebox — объектное облачное хранилище для архивации и длительного хранения данных и простым веб-интерфейсом. Оно создано для хранения и доступа к редко используемым данным с поддержкой протокола S3, к которым при необходимости можно получить быстрый доступ.

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


Платформа для бизнеса biz.mail.ru обеспечивает доступ к управлению всех B2B-Облаков. Сама платформа — это общая административная панель для B2B-сервисов Mail.Ru: Почты для сайта, корпоративного Календаря, Агента, службы DNS и B2B-Облаков. Платформа предоставляет личный кабинет администраторов и реализована по принципу плагинов — есть общие элементы (авторизация, управление проектами и доменами, списком пользователей), есть отдельные разделы для подключаемых сервисов — Почты, Teambox, Hotbox, Icebox и других. У Платформы есть своё API и механизм проксирования запросов из бэкенда Платформы в бэкенды подключенных сервисов. Таким образом, у нас имеется общая инфраструктура, функционал которой разрабатывают разные команды программистов, а для пользователей всё управление собрано в одной административной панели.


Итак, спрашивайте!


По традиции надо обозначить время, когда мы будем отвечать на вопросы. И пусть это будут два дня, а не один: сегодня и завтра с 12.00 до 19.00 (по московскому времени). Но в случае особо ожесточённых дискуссий мы, конечно, не ограничимся этим интервалом. Задавайте вопросы про наш софт, про наши серверы, про наши команды, про наше API и так далее. Погнали!

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

https://habrahabr.ru/post/330348/


Метки:  

Особенности –webkit-box или как «подружить» flexbox со старыми Safari

Среда, 07 Июня 2017 г. 11:53 + в цитатник
Уверен, многие Front End Developer-ы постоянно сталкиваются с проблемой поддержки flexbox в старых версиях популярных браузеров.
Среди них выделяются два явных фаворита – Internet Explorer (IE) и Safari.
С IE всё проще, т.к. flex поддерживается в версиях 10.0+. Версии ниже уже не актуальны, поэтому их часто игнорируют.
В Safari же ситуация иная, поскольку поддержка современной спецификации flexbox (по мнению Caniuse.com) начинается с версии IOS Safari 9.2+.

image

Проблема именно в этом! Ведь по статистике Apple, только 47% обладателей iPhone имеют возможность использовать Safari 9.2+.

image

А что делать остальным?



Если мы делаем красивый, качественный и суперадаптивный сайт, построенный на flexbox — так же красиво и качественно он будет отображаться только на устройствах, которые его грамотно интерпретируют.
На помощь в этом приходит так называемый старый синтаксис flexbox – display: box;
Это аналог свойства display: flex; только он поддерживается всеми Safari, начиная с версии 5.0+.
Однако, всё не так просто:
  1. Display: box работает только с префиксами, в данном случае с -webkit- (display: -webk2) it-box;).
  2. Странно работает с float.
  3. Аналогов некоторым современным свойствам нет.

Это те ошибки, которые отловил лично я. В будущем список будет пополняться.

Как же решить уже найденные проблемы?



Прописываем вендорные префиксы для box и связанным свойствам.
Обтекания внутри box прячут элементы
imageimage

Эту ошибку пофиксить легко. Достаточно элементам, имеющим float, добавить свойство position: relative.
image
Почему бы просто не убрать float? – А вот почему:
image

Я приведу список всех рабочих аналогов flex-свойств и box-свойств:

-webkit-box-orient (flex-direction) – направление оси элементов.
Бывает нескольких видов в случае нового синтаксиса:
— column – колонка;
— row (по умолчанию) – строка;
— row-reverse – реверсия строки;
— column-reverse – реверсия колонки.
В случае старого синтаксиса я использую всего два свойства:
— vertical – колонка;
— horizontal – строка.
Есть еще два свойства, но они не работают как аналоги реверсивных свойств нового синтаксиса, поэтому я не использую их в своей практике.

Для реверса есть свойство -webkit-box-direction, которое имеет 2 значения – normal и reverse.

-webkit-box-pack (justify-content) – задает выравнивание по горизонтали.

Новый синтаксис:
— flex-start, flex-end – элементы прижаты к началу/концу родителя;
— space-between – распределяет элементы равномерно внутри родителя, не оставляя при этом боковых отступов;
— center – центрирует элементы.

Старый синтаксис:
— start, end – аналог flex-start, flex-end;
— justify – аналог space-between;
— center – то же, что и center в новом.
У space-around НЕТ аналога!

-webkit-box-align (align-items) – выравнивание по вертикали. По праву могу назвать это одним из главных достоинств flexbox.

Новый синтаксис:
— flex-start, flex-end – элементы прижаты к верху/низу родителя;
— baseline – дефолтное значение, выравнивание по базовой линии шрифта без учета свисаний;
— center – центрирует элементы;
— stretch – растягивает дочерние блоки по высоте.

Старый синтаксис:
— start, end – аналог flex-start, flex-end.
Остальные свойства идентичны

-webkit-box-ordinal-group (order) – определяет порядковый номер элемента в группе.
В обоих случаях задается цифрой.


Других вариантов либо нет, либо они не работают. Например:
-webkit-box-lines – это, по идее, аналог свойства flex-wrap, но у меня он почему-то не работает.

И напоследок.

Если вам нужно применить любое CSS-свойство только для -webkit-, можете использовать рабочий CSS-хак. Он проверен и он РАБОТАЕТ:

@media all and (-webkit-min-device-pixel-ratio:0) {
/*Всё, что вы сюда напишете, будет работать только с -webkit-*/
}

Делитесь своим опытом и удачи!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330410/


Метки:  

[Перевод] Must-Have 3: игровые интерфейсы и ассеты для дизайнера и художника

Среда, 07 Июня 2017 г. 11:25 + в цитатник
Эти наборы интерфейсов будут незаменимыми для тех, кто хочет придать игре окончательный вид или добавить в нее графический интерфейс, способный объединить остальные ассеты.



Предыдущие статьи из серии:

Must-Have 2: 20 игровых ассетов для дизайнера и художника
Must-Have 1: 15 игровых спрайтов для дизайнера и художника

RPG User Interface
Этот простой и элегантный интерфейс в стиле RPG станет достойным дополнением для любой hack and slash или MMORPG-игры. Мне хочется играть от одного взгляда на него, и неважно, что это будет за игра.



Cartoon Games GUI Pack 3
Этот набор с элементами интерфейса станет отличным дополнением к некоторым ранее упомянутым тайлсетам, а также наборам спрайтов и фонов. Он забавный и аккуратный, а потому подойдет многим играм самых разнообразных жанров.



Match-3 Candy Game GUI
Меня просто покорил этот яркий дизайн с удивительной четкими деталями. Если вы впервые создаете игру в духе Candy Crush или просто хотите добавить в интерфейс крутых элементов, вы не сможете пройти мимо этого варианта.



Cartoon Games GUI Pack 9
Веселые фоны и заголовки, представленные здесь, создадут у игроков особое настроение. Приятная цветовая палитра и светлый дизайн – вот что нужно большинству приложений.



Cartoon Games GUI Pack 11
Нужен интерфейс, который идеально подходил бы приключенческой игре с местом действия в лесу? Он перед вами!



Mobile Game GUI Pack 02
Хорошая 2D игра требует хорошего UI-набора. Этот содержит удивительные векторные элементы и вполне достойно смотрится на фоне остальных наборов из списка.



Mobile Game GUI Pack 04
Тем, кто предпочитает мобильный формат, однозначно понравится этот потрясающий UI-набор. Отличный вариант для пазл-игры с возможностью отслеживать прогресс по уровням.



Cartoon Games GUI Pack 14
Я не смогла устоять перед стилем этих кнопок. Их яркая цветовая палитра будет здорово смотреться с большинством ассетов. Вот почему этот набор должен быть у каждого дизайнера.



DingDong: Game GUI Pack
Если вашему интерфейсу как раз не хватало чего-то веселого и красочного, обратите внимание на этот набор. С ним вы получаете в распоряжение множество значков, баннеров, иконок, слайдеров и многого другого.



Space Game GUI Pack
Разработчики игр в космическом сеттинге, не упустите шанс получить набор из более чем 350 уникальных элементов в шести разных форматах! Теперь вам не придется тратить время на создание ассетов и вы сможете уделить больше внимания разработке самой игры.



Наборы для игр


Эти наборы пригодятся тем, кто ищет всех ресурсов понемногу или целый пакет готовых ассетов.

Wirawiri: Game Level Map Builder
Проявите все ваши творческие способности, создавая карты с этим восхитительным набором! Он включает несколько типов поверхностей, текстур и дорожек, а также кнопок и иконок, способных в сумме произвести практически неограниченное количество разных уровней.



Top Down Racing Game Creation Kit
Здесь вы найдете машины, здания, поверхности и всё необходимое для настоящей гоночной игры с видом сверху.



2d Pixel Art Game Assets
Создайте игру в лучших традициях пиксельного 2D платформера. В вашем распоряжении более 150 ассетов – загружайте и приступайте к работе!



Casino Card Game GUI
Трудно не войти в азарт, имея в арсенале такой набор для казино-игры. Он включает полную колоду карт, фишки, столы, потрясающий золотой текст и многое другое.



Cannon Ball Shooter Game Assets
Йо-хо-хо! Давно хотели создать бабл-шутер в пиратском стиле? Тогда вам сюда. В набор входят спрайты, дополнительные элементы и анимация – и всё это в файлах трех форматов.



Flying Adventure Dark Style Game Kit
Набор сочетает в себе уникальную атмосферу и качественные ассеты, которые идеально подойдут для приключенческой игры. Сюда входят: спрайты персонажей, фоны, наборы дополнительных элементов и т. д.



Spooky Places Game Assets
Этот набор выполнен в духе мультипликационной хоррор-игры и включает всё, что нужно для приключенческого платформера – от спрайтов до кнопок интерфейса.



Game Assets for Tank Wars
Создайте мультипликационную танковую игру, от которой будет трудно оторваться. В набор входят спрайты, тайлы, элементы интерфейса и многое другое.



Golden Slots Game Kit
Лучшая находка для вашей слот-игры. Набор включает свыше 500 различных элементов в шести разных форматах.



Space Game GUI Set
Космически красивый дизайн меню, кнопок, спрайтов, фонов и других элементов набора определенно произведет на ваших игроков приятное первое впечатление.



Разное


Здесь приведены дополнительные иконки и ассеты, которые выгодно дополнят дизайн вашей игры.

Common Game Icon Asset
Сюда входят 100 иконок в четырех размерах. Набора с головой хватит на несколько игр разных жанров.



RPG Item Bundle 1
В этом наборе представлено 296 предметов в трех размерах – то, что нужно, для настоящей RPG с большим и разнообразным инвентарем.



Magic Bottles Icons
Добавьте в свою игру красивые флаконы. Они отлично подойдут для обозначения предметов, свойств, зелий, заклинаний и так далее. Доступно 28 иконок в трех форматах.



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



2D Cartoon Forest Trees & Plants
Набор растений и деревьев позволяет создавать множество красочных фонов и окружений.



Donut Game Icons Set
Набор ярких пончиков не только дополнит вашу текущую пазл-игру, но и вдохновит на создание новой!



85 RPG Fantasy Spells Icons
Если вашей фэнтези-игре нужны иконки для заклинаний, обратите внимание на это предложение. Набор включает 85 иконок в трех размерах.



Asteroids Game Pack
Небольшие наборы вроде этого отлично дополнят веселую космическую игру новыми элементами, а иногда уровнями, скинами или даже новыми версиями.



Isometric Map Icons Vol.01
Набор пригодится разработчикам изометрических игр. Теперь у вас появится еще больше интересных зданий. Создавайте города вручную или загружайте эти здания в генератор карт.



Common Game Icon Pack HD
Вашей игре не хватает нескольких иконок? Взгляните на этот набор с потрясающе красивыми векторными ассетами, доступными в трех форматах.

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

https://habrahabr.ru/post/330252/


Метки:  

Что такое Nimses? Интсаграм где вместо лайков деньги

Среда, 07 Июня 2017 г. 11:03 + в цитатник
Nimses это новая социальная сеть, своим видом очень похожая на Инстаграм, вот только от обычной ленты фотографий её отличает социальный капитал внутри сервиса.

Nimses находится на первом месте среди бесплатных приложений в российском и украинском App Store. Ещё 1 июня его не было в чарте, а 4 июня он уже закрепился на лидерской позиции.



Ним — это социальная валюта в Nimses, она постоянно увеличивается, каждую минуту на 1. Чтобы опубликовать пост вам придется заплатить 100 нимов, а чтобы лайкнуть другой пост от 10 до 100, в зависимости от того какую цену на него установил автор.

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

Лента в Nimses привязана к вашей геолокации. При создании поста высвечивается цифра с количеством пользователей, которые увидят ее. Посты в Nimses очень напоминают контент в инстаграм, по сути своей они прямые конкуренты.

Уже в этом месяце Nimses обещают запустить встроенный магазин где нимы можно будет обменять на товары или услуги, также с 2018 года их можно будет обналичивать (для пользователей с количеством нимов 43 000 и более). На сегодняшний день 1$ = 1028 ним.



В мае о Nimses знала только узкая киевская тусовка, но уже в начале июня компания начала масштабную PR кампанию, что привело к падению SMS-шлюза для регистрации новых пользователей 05.05. PR кампания основана на промо-кодах всего за неделю сделала Nimses самым вирусным приложением в российском и украинском App Store.

Создатели сервиса


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



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




Чтобы получить стартовый капитал в приложении нужно ввести промокод приглашения при регистрации (чуть больше тысячи нимов), и владелец промо-кода тоже получит бонус. Мой промокод: mcwwe0pkqp.

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

https://habrahabr.ru/post/330404/


Метки:  

[Из песочницы] Списки инициализации в C++: хороший, плохой, злой

Среда, 07 Июня 2017 г. 10:58 + в цитатник

В этой статье я бы хотел рассказать о том, как работают списки инициализации (braced initializer lists) в C++, какие проблемы они были призваны решать, какие проблемы, в свою очередь, вызвали и как не попасть в просак.


Первым делом предлагаю почувствовать себя компилятором (или language lawyer-ом) и понять, компилируются ли следующие примеры, почему, и что они делают:


Классика:


std::vector v1{5};
std::vector v2(5);
std::vector v3({5});
std::vector v4{5};
std::vector v5 = 5;

Современный C++ — безопасный язык, я никогда не выстрелю себе в ногу:


std::vector x( {"a", "b"} );
std::vector y{ {"a", "b"} };

Больше скобочек богу скобочек!


// Почему их тут пять, скомпилируется ли программа и почему?
std::vector> v1{{{{{}}}}}; 

Если один конструктор не подходит, мы берем второй, правильно?


struct T{};
struct S {
    S(std::initializer_list);
    S(double, double);
    S(T, T);
};

int main() {
    S{T{}, T{}}; // Работает ли вот так?
    S{1., 2.}; // а так?
}

Almost Always Auto, говорили они. Это повышает читабельность, говорили они:


auto x = {0}; // какой тут тип у x?
auto y{0}; // а у y?
// вы уверены? попробуйте другую версию вашего компилятора

Привет из древних времен:


struct S {
    std::vector a, b;
};

struct T {
    std::array a, b;
};

int main() {
    T t1{{1, 2}, {3, 4}};
    T t2{1, 2, 3, 4};
    T t3{1, 2};
    S s1{{1, 2}, {3, 4}};
    S s2{1, 2, 3, 4};
    S s3{1, 2};
}

Все понятно? Или ничего не ясно? Добро пожаловать под кат.


Disclaimers


  1. Эта статья ознакомительная, не претендует на полноту и часто будет жертвовать корректностью в угоду понятности. С другой стороны, у читателя предполагается базовое знание C++.
  2. Я пытался придумывать разумные переводы на русский для англоязычных терминов, но с некоторыми я потерпел полное фиаско. Синтаксические конструкции вида {...} я буду называть braced-init-lists, тип из стандартной библиотеки — std::initializer_list, а вид инициализации, когда мы пишем как-то так: int x{5} — это list-init, также известная как uniform initialization syntax, или универсальный синтаксис инициализации.

Attention!


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


Итак, braced-init-lists (штуки с фигурными скобками, {1, 2, 3}, uniform initialization syntax) и std::initializer_list — разные вещи! Они сильно связаны, между ними происходят всякие тонкие взаимодействия, но любое из них вполне может существовать без другого.


Но сначала — немного предыстории.


Unicorn initialization syntax



В C++98 (и его bugfix-update, C++03) существовало достаточно проблем и непоследовательностей, связанных с инициализацией. Вот некоторые из них:


  • Из C пришел синтаксис инициализации переменных (в том числе, массивов и структур) с использованием фигурных скобок, но он не очень хорошо взаимодействовал с возможностями C++ (например, инициализация структур не была доступна для C++-классов)
  • Часто хочется соорудить какой-нибудь контейнер (например, std::vector) из заранее известных элементов — в языке не было встроенной возможности для этого, а библиотечные решения (Boost.Assign) не отличались изящностью синтаксиса, были не бесплатны с точки зрения скорости работы и не слишком хорошо влияли на время компиляции
  • При инициализации примитивных типов легко случайно потерять информацию при сужающем преобразовании (narrowing conversion) — например, случайно присвоить double в int
  • Most vexing parse, которым любят пугать начинающих C++-ников.

Поэтому во время разработки C++11 родилась такая идея: давайте мы дадим возможность проинициализировать что угодно с помощью фигурных скобок:


  • Для случаев, где это применимо в C, новый синтаксис будет работать так же, только лучше
  • Сужающие преобразования при этом мы запретим
  • А если мы пытаемся проинициализировать класс с конструкторами, то мы и конструктор сможем вызывать, с переданными параметрами

Pitfalls


Казалось бы, на этом можно и закончить: инициализация контейнеров должна получиться сама собой, ведь в C++11 появились еще и шаблоны с переменным числом параметров, так что если мы напишем variadic-конструктор… на самом деле, нет, так не получится:


  • Такой конструктор должен быть шаблоном, что часто нежелательно
  • Придется инстанцировать конструкторы со всевозможным числом параметров, что приведет к раздуванию кода и замедлению компиляции
  • Эффективность инициализации, например, для std::vector-а будет все равно не идеальная

Для решения этих проблем придумали std::initializer_list — "магический класс", который представляет собой очень легкую обертку для массива элементов известного размера, а так же умеет конструироваться от braced-init-list-а.


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


Зачем же он нужен? Главным образом, чтобы пользовательские классы могли сказать: "я хочу конструироваться от braced-init-list-а элементов такого-то типа", и им не требовался бы для этого шаблонный конструктор.


(Кстати, к этому моменту должно стать понятно, что std::initializer_list и braced-init-list это разные понятия)


Теперь-то все хорошо? Мы просто добавим в наш контейнер конструктор вида vector(std::initializer_list) и все заработает? Почти.


Рассмотрим такую запись:


std::vector v{5};

Что имелось в виду, v(5) или v({5})? Другими словами, хотим ли мы сконструировать вектор из 5 элементов, или из одного элемента со значением 5?


Для решения этого конфликта разрешение перегрузок (overload resolution, выбор нужной функции по переданным аргументам) в случае list-initialization происходит в два этапа:


  1. Сначала рассматриваются только конструкторы с единственным параметром типа std::initializer_list (это один из главных моментов, когда компилятор таки генерирует std::initializer_list по содержимому фигурных скобочек). Разрешение перегрузок происходит между ними.
  2. Если ни один конструктор не подходит, то дальше все как обычно — разворачиваем braced-init-list в список аргументов и проводим разрешение перегрузок среди всех доступных конструкторов.

Отметим, что конструктор, который проиграл на первом этапе, вполне может подойти на втором. Это объясняет пример с избытком скобочек для инициализации вектора из начала статьи. Для понятности удалим один из вложенных шаблонов, а также заменим std::vector на свой класс:


template struct vec {
    vec(std::initializer_list);
};

int main() {
    vec v1{{{}}};
}

Под пункт 1 наш конструктор не подходит — {{{}}} не похож на std::initializer_list, потому что int нельзя проинициализировать с помощью {{}}. Однако {} — вполне себе zero-initialization, поэтому конструктор принимается на втором шаге.


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


struct S {
    S(std::initializer_list);
    S(double, double);
};

int main() {
    S{1., 2.};
}

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


Классы-агрегаты


Ну теперь-то все? Не совсем. Старый синтаксис инициализации структур, доставшийся нам от C, никуда не делся, и можно делать так:


struct A { int i, j; };
struct B { A a1, a2; };
int main() {
    B b1 = {{1, 2}, {3, 4}};
    B b2 = {1, 2, 3, 4}; // brace elision
    B b3 = {{1, 2}}; // clause omission
}

Как видим, при иницализации агрегатов (грубо говоря, C-подобных структур, не путать с POD, POD — это про другое) можно и пропускать вложенные скобочки, и выкидывать часть инициализаторов. Все это поведение было аккуратно перенесено в C++.


Казалось бы, какой бред, зачем это в современном языке? Давайте хотя бы предупреждения компилятора будем на это выводить, подумали разработчики GCC и clang, и были бы правы, не будь std::array классом-агрегатом, содержащим внутри себя массив. Таким образом, предупреждение про выкидывание вложенных скобок по понятным причинам срабатывает на вот таком невинном коде:


int main() {
    std::array a = {1,2,3};
}

Проблему эту GCC "решил" выключением соответствующего предупреждения в режиме -Wall, в clang-е же уже три года все по-прежнему.


Кстати, тот факт, что std::array — агрегат, не прихоть безумных авторов стандарта или ленивых разработчиков стандартных библиотек: достичь требуемой семантики этого класса просто невозможно средствами языка, не теряя в эффективности. Еще один привет от C и его странных массивов.


Возможно, большая проблема с классами-агрегатами — это не самое удачное взаимодействие с обобщенными функциями (в том числе) из стандартной библиотеки. На данный момент функции, которые конструируют объект из переданных параметров (например, vector::emplace_back или make_unique), вызывают обычную инициализацию, не "универсальную". Вызвано это тем, что использование list-initialization не позволяет никаким нормальным способом вызвать "обычный" контруктор вместо принимающего std::initializer_list (примерно та же проблема, что и с инициализацией в не-шаблонном коде, только тут пользователь не может обойти ее вызовом другого конструктора). Работа в этом направлении ведется, но пока мы имеем то, что имеем.


Almost Always Auto


Как же braced-init-list-ы ведут себя в сочетании с выводом типов? Что будет, если я напишу auto x = {0}; auto y = {1, 2};? Можно придумать несколько разумных стратегий:


  1. Запретить такую инициализацию вообще (в самом деле, что программист хочет этим сказать?)
  2. Вывести тип первой переменной как int, а второй вариант запретить
  3. Сделать так, чтобы и x, и y имели тип std::initializer_lits

Последний вариант нравится мне меньше всего (мало кому в реальной жизни заводить локальные переменные типа std::initializer_list), но в стандарт С++11 попал именно он. Постепенно стало выясняться, что это вызывает проблемы у программистов (кто бы мог подумать), поэтому в стандарт добавили патч http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html, который реализует поведение №2… только в случае copy-list-initialization (auto x = {5}), а в случае direct-list-initialization (auto x{5}) оставляет все по-старому.


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


Промежуточные итоги


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



В качестве примера возьмем, например, историю с [over.best.ics]/4.5, который сначала добавили в стандарт, потом, не подумав, удалили, как избыточный, а потом добавили обратно в измененном виде — как описание крайнего случая с пятью (!) условиями.


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


  1. Потратьте некоторое время на то, чтобы ознакомиться с тем, что на самом деле происходит (я рекомендую прочитать параграф стандарта — на удивление понятный и не слишком зависимый от остальных)
  2. Не используйте std::initializer_list, кроме как в параметре конструктора
  3. Да и в параметре конструктора используйте, только если вы понимаете, что происходит (если не уверены — сконструируйтесь лучше от вектора, пары итераторов или range-а)
  4. Не используйте классы-агрегаты без крайней необходимости, напишите лучше конструктор, инициализирующий все поля
  5. Не используйте braced-init-list в сочетании с auto
  6. Прочитайте эту статью про то, что делать с пустыми списками инициализации (у меня руки чешутся ее перевести и запостить, может быть, вскоре займусь)
  7. И, как я уже писал в самом начале, имейте в виду, что braced-init-list и std::initializer_list — это разные концепции, весьма хитро взаимодействующие друг с другом

Давайте помечтаем


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


Мне кажется, что переиспользовать фигурные скобки для создания std::initializer_list во время инициализации — ошибка дизайна языка. Я был бы очень рад, если бы вместо этого мы получили бы более явный и отдельный синтаксис (пусть и более уродливый, например, какие-нибудь странные скобки типа <$...$> или встроенный интринзик вроде std::of(...)). То есть инициализируем вектор как-то так: std::vector> x = std::of(std::of(1, 2), std::of(3, 4));


Что бы это дало? Новый способ инициализации (с защитой от most vexing parse и сужающих преобразований) оказался бы отвязан от std::initializer_list, не потребовалось бы вводить отдельный шаг для разрешения перегрузок, ушла бы проблема с конструктором vector или vector, новый синтаксис инициализации можно было бы использовать в обобщенном коде безо всяких проблем.


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


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


struct S {
   int a, b;
   S(...) = aggregate;
};

Заключение


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

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

https://habrahabr.ru/post/330402/


Метки:  

[Из песочницы] Типизированные компоненты в Vue.js, или как подружить Vue, TypeScript и Webpack

Среда, 07 Июня 2017 г. 10:39 + в цитатник

Речь в данной статье пойдет о довольно необычном сочетании технологий: Vue.js + TypeScript + Webpack, в разрезе single-file компонентов. Решение данной задачи отняло у меня приличное количество времени с первого захода, поскольку исчерпывающее объяснение того, как использовать все это вместе, да и еще с рядом ограничений (NPM предоставляет нам runtime-only build Vue.js), найти в цельном виде практически невозможно. Если вас заинтересовала данная тема, то приглашаю к дальнейшему чтению.

Думаю причины, по которым вы можете захотеть использовать данное сочетание с Vue.js, довольно-таки очевидны:

  • Типизацию для JS сейчас хотят почти на всех, крупных и не очень, проектах;
  • Webpack — крайне простое, в использовании, и популярное, средство сборки
    проектов (да еще и import/export может)

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

Начнем мы, как водится, с демонстрации конфигураций package.json и webpack.config, и дальнейшего разбора последнего.

package.json
{
  "name": "vuejs-webpack-ts",
  "version": "1.0.0",
  "description": "Sample project of Webpack+TS+Vue.js ",
  "main": "webpack.config.js",
  "scripts": {
    "start": "webpack-dev-server --hot --inline --history-api-fallback"
  },
  "repository": "https://github.com/StepanZharychev/vue-ts-webpack.git",
  "author": "Stepan Zharychev",
  "license": "ISC",
  "dependencies": {
    "babel-core": "^6.24.0",
    "babel-loader": "^6.4.1",
    "css-loader": "^0.27.3",
    "style-loader": "^0.16.0",
    "ts-loader": "^2.0.3",
    "typescript": "^2.2.1",
    "webpack": "^2.3.2",
    "vue": "^2.3.3",
    "vue-class-component": "^5.0.1",
    "vue-loader": "^12.1.0",
    "vue-property-decorator": "^5.0.1",
    "vue-template-compiler": "^2.3.3",
    "webpack-dev-server": "^2.4.2"
  }
}

webpack.config.js
module.exports = {
    entry: './app/init.ts',
    output: {
        filename: 'dist/bundle.js',
        path: __dirname,
        publicPath: '/static/'
    },
    module: {
        loaders: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                options: {
                    configFileName: 'tsconfig.json',
                    appendTsSuffixTo: [/\.vue$/]
                }
            },
            {
                test: /\.js/,
                loaders: ['babel-loader']
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        ts: 'ts-loader'
                    },
                    esModule: true
                }
            },
            {
                test: /\.css/,
                loaders: ['style-loader', 'css-loader']
            }
        ]
    },
    devServer: {
        compress: true,
        port: 8001
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js']
    },
    devtool: 'source-map'
}

Момент, который интересует нас больше остальных, — это использование vue-loader. Как можно заметить в параметрах options, мы указываем еще одну коллекцию лоадеров, и понадобится она нам как раз для того, чтобы при парсинге vue темплейта webpack смог правильно обработать зависимости с отличным от стандартного типом. Теперь я предлагаю вспомнить (или изучить) базовую структуру vue компонента.


Компонент имеет абсолютно типичную для компонентного подхода структуру: темплейтскрипт(ts в нашем случае) — CSS. И как раз скрипт и представляет для нас наибольшую проблему в данном случае: т.к. должен быть обработан предварительно. На стороне Webpack проблему мы решили, теперь ее осталось решить внутри компонента, делается добавлением атрибута lang с соответствующим расширением.

main.vue(рутовый компонент)



main.ts
import Vue from 'vue'
import Component from 'vue-class-component'
import HelloComponent from '../hello/hello.vue'

@Component({
    components: {
        hello: HelloComponent
    }
})
export default class MainComponent extends Vue {
    public message = 'Hello there, Vue works!'
}

Пара слов о @Component
Как можно заметить перед классом нашего компонента находится декоратор, который занимается тем, что «переводит» код компонента в более привычный (в форме объекта) для Vue.js формат, использование данного декоратора не является обязательным, но позволяет писать более читаемый код. (так же хорошим дополнением являются «property decorators»)

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

import MainComponent from './components/main/main.vue'

… поскольку TS ничего не знает о наших vue темплейтах, но это вообщем-то не проблема, все требуется сделать в данном случае — это задекларировать в d.ts файл модуль следующего вида:

declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
}

Эта пара строчек кода «объяснит» TS-у как именно обрабатывать импорт *.vue файлов да и работает все по довольно очевидной причине: все наши компоненты наследовались от Vue.

Теперь можно закончить написание нашего index.ts:


import Vue from 'vue'
import MainComponent from './components/main/main.vue'

class AppCore {
    private instance: Vue;

    private init() {
        this.instance = new Vue({
            el: '#appContainer',
            render: h => h(MainComponent),
        })
    }

    constructor() {
        this.init();
    }
}

new AppCore();

Здесь происходит довольно типичный для инициализации Vue-приложения вызов конструктора, но может возникнуть вопрос зачем нужно указывать render, почему нельзя просто указать темплейт и использовать там рутовый компонент? Дело тут вот в чем, дефолтная версия vue.js из npm (она же по совместительству — лучшая по производительности) является runtime-only build версией, что обозначает невозможность парсинга наших темплейтов налету, и из-за этого мы должны указать render функцию с рутовым компонентом, как точку входа.

Немного о билде
Тут может возникнуть еще более резонный вопрос: почему компонент внутри компонента рендерится нормально? Дело тут вот в чем, внутри vue-loader живет специальный компонент, который занимается тем, что переводит наши темплейты в рендер-функции на стадии билда, и в дальнейшем vue.js пользуется уже собранными функциями без необходимости выполнять парсинг самостоятельно (очевидный + к производительности). Резюмируя: все вложенные компоненты будут использованы уже в виде рендер-функций, а вот для инициализации рутового придется прописать ее самостоятельно по понятным причинам.

Надеюсь, что после данного разбора, вам стало более понятно, как нужно собирать vue компоненты c TS и Webpack. За полным примером можете пройти сюда.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330400/


Метки:  

Awless — мощная альтернативная CLI-утилита для работы с сервисами AWS

Среда, 07 Июня 2017 г. 10:34 + в цитатник


Все пользователи облачных сервисов Amazon давно знают про родной консольный инструмент для работы с ними — aws-cli. Но оказалось, что далеко не всем его достаточно: по этой причине компания WALLIX выпустила альтернативное и более функциональное решение под названием awless.

Исходный код awless написан на языке Go (использует AWS Go SDK) и опубликован на GitHub под свободной лицензией (Apache License 2.0). Текущая версия awless — 0.1.0. Поддерживаются операционные системы GNU/Linux, Mac OS X и Windows. Что же позволяет эта утилита?

Возможности


Awless поддерживает работу со следующими сервисами/возможностями AWS:
  • EC2;
  • IAM;
  • S3;
  • RDS;
  • Auto Scaling;
  • SNS;
  • SQS;
  • Route53;
  • CloudWatch;
  • CloudFormation;
  • Lambda.

Одной из главных особенностей утилиты является вывод в разные форматы: как в human-readable (таблицы, совместимые с разметкой Markdown), так и в машинные (CSV, TSV, JSON), что обеспечит удобство работы с данными в скриптах, использующих awless. Если же вы будете взаимодействовать с инструментом вручную, другая приятная опция — автодополнение команд (поддерживаются оболочки Bash и Zsh — как активировать, см. в выводе awless completion).

Ещё одна интересная возможность awless — движок шаблонов для команд, позволяющий создавать целые наборы операций, выполняемых в AWS (и запускаемых однострочной командой). Примером может служить уже встроенный в awless шаблон для создания нового экземпляра EC2:
$ awless create instance subnet=subnet-356d517f image=ami-70edb016 type=t2.micro

Особенностью такой команды является передача параметров в виде ключа-значения, которые используются для выполнения дополнительных операций (в данном случае — подсеть и образ AMI для запуска в новом экземпляре).

Среди прочих фич awless:
  • фильтрация списков ресурсов по их свойствам и тегам;
  • возможность использования произвольных алиасов для названий ресурсов;
  • поддержка AWS userdata для provisioning (исполнения произвольных удалённых или локальных скриптов) на новых создаваемых экземплярах;
  • логирование выполняемых операций (awless log);
  • отмена ресурсов, созданных с помощью шаблонов (awless revert с идентификатором операции из журнала);
  • простой SSH-доступ к экземплярам (awless ssh);
  • просмотр данных о ресурсах в offline (требует предварительного запуска awless sync для локального хранения данных).

Установка


Установка awless сводится к выполнению команды:
$ curl https://raw.githubusercontent.com/wallix/awless/master/getawless.sh | bash

… или (при наличии установленного Go):
$ go get -u github.com/wallix/awless

Кроме того, готовые архивы с awless для разных платформ доступны для скачивания на странице с релизами.

Примеры использования awless


Разработчики подготовили классное видео, демонстрирующее работу с утилитой. Однако… в нём используется формат анимированного PNG — APNG, поэтому для просмотра в Chrome понадобится последняя версия 59 или специальное дополнение, а поскольку очередной его просмотр в Firefox привёл к неадекватному потреблению памяти, оставлю это видео ссылкой вместо встраивания в пост.

Примеры конкретных операций (взяты из документации и встроенной справки):
  • Список экземпляров с сортировкой по времени их работы:
    $ awless list instances --sort uptime
  • Вывод пользователя по его имени или ID:
    $ awless show jsmith
  • Создание экземпляра и provision в него из Gist:
    $ awless create instance name=my_machine image=ami-3f1bd150 keypair={keypair.name} \
    subnet={main.subnet} securitygroup={securitygroup} \
    userdata=https://gist.github.com/simcap/360dffae4c6d76ab0e89621dd824a244
  • Определение политики для пользователя:
    $ awless attach policy user=jsmith arn=arn:aws:iam::aws:policy/AmazonEC2FullAccess
  • Загрузка локального файла в S3:
    $ awless create s3object bucket=my-existing-bucket file=./todolist.txt
  • Создание экземпляра и вход в него по SSH (по локальному ключу):
    $ awless run repo:instance_ssh
    Please specify (Ctrl+C to quit):
    instance.name ? my-new-instance-name
    instance.subnet ? @my-existing-subnet
    instance.vpc ? @my-existing-vpc
    keypair.name ? my-new-keyname
    $ awless ssh my-new-instance-name

Заключение


Количество звёзд awless на GitHub приближается к 3 тысячам, а это явный индикатор того, что подобного инструмента ждали. У проекта есть wiki, в которой можно получить больше информации по его установке и использованию. Кроме того, у всех команд есть достаточно подробная встроенная справка — флаг -h (например, awless create instance -h).
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330398/


Метки:  

Интеграция телефонии с CRM: на что опираться при самостоятельной настройке

Среда, 07 Июня 2017 г. 10:11 + в цитатник
image

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


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


  1. Покажу, как мы сами реализовали готовую интеграцию виртуальной АТС с retailCRM на основе новой версии API. Эта же логика может быть легко перенесена в любую нужную интеграцию с вашей системой (оговорюсь, что это не инструкция, а именно фундамент для реализации интеграций других АТС с retailCRM или других CRM с телефонией UIS).
  2. Расскажу о ключевых функциях по управлению данными, которые мы зашиваем в обновленный API и на которые вы можете опираться.

Пример базовой интеграции телефонии с CRM


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


  • Всплывающую карточку контакта
  • Фиксацию потерянных звонков в CRM
  • Исходящие звонки из CRM
  • Прослушивание записей разговора в CRM-системе

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


Используемые инструменты



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


Общая схема работы интеграции


image


Кликайте на схему, чтобы посмотреть в полном размере.



Активация телефонии в retailCRM


Телефония в retailCRM активируется запросом к /api/v4/telephony/setting/{code}/edit. Cреди прочих, в запросе указываются следующие параметры:


  • makeCallUrl — URL, на который retailCRM будет отправлять запросы для генерации исходящих звонков.
  • changeUserStatusUrl — URL, на который retailCRM будет отправлять оповещения об изменении статуса сотрудника.

Обработка звонка


Всплывающая карточка контакта


Всплывающая карточка контакта в retailCRM осуществляется простым запросом к API /api/v4/telephony/call/event, триггером будет сработавшее уведомление на событие «Ожидание ответа», когда у сотрудника уже звонит телефон.


Пропущенные звонки


Пропущен звонок или успешен, можно определить по параметру is_lost в уведомлении о завершении звонка. И если звонок пропущен, то статус звонка будет загружен запросом API /api/v4/telephony/calls/upload, поля которого можно заполнить параметрами из уведомления.


Успешные звонки и сохранение их записей в CRM


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


Немного о компоновке запроса:


  • В поле params можно указать интересующие параметры, чтобы в ответе пришли только они
  • В поле filter можно указать наименование тех полей, которые вас интересуют

Как это выглядит
{
  "jsonrpc": "2.0",
  "id": 1122,
  "method": "get.call_legs_report",
  "date_from": "2017-06-01 14:34:00",
  "date_till": "2017-06-01 14:36:52",
  "params": {
    "access_token": "N2dw2Rf33fn23fknkmdfeJmcP",
    "filter": {
        "filters": [
            {
                "field": "call_session_id",
                "operator": "=",
                "value": 31451224
            },
{
                "field": "is_talked",
                "operator": "=",
                "value": true
            }
        ],
        "condition": "and"
    },
    "fields": [
      "id",
    "call_seesion_id",
    "call_records",
    "release_cause_code",
    "direction",
    "start_time",
    "employee_id",
    "called_phone_number",
    "contact_phone_number",
    "total_duration",
    "duration"
    ]
  }
}

Полученную информацию необходимо загрузить в retailCRM запросом API /api/v4/telephony/calls/upload. Если требуется расширить набор загружаемых параметров, их можно взять из параметров уведомления «Завершение звонка».


Исходящий звонок из retailCRM по клику


При попытке сотрудника позвонить по клику на номер контакта из интерфейса CRM, retailCRM будет присылать вам запрос на URL, указанный при активации телефонии. Теперь необходимо этот запрос перенаправить в сервис телефонии для совершения звонка. Для этого можно использовать наш Call API.


Как это выглядит
{
  "jsonrpc": "2.0",
  "method": "start.employee_call",
  "id": "number",
  "params": {
    "access_token": "N2dw2Rf33fn23fknkmdfeJmcP",
    "first_call": "employee",
    "early_switching": true,
    "switch_at_once": true,
    "show_virtual_phone_number": false,
    "virtual_phone_number": "88002000600",
    "direction": "out",
    "contact": "72131231111",
    "employee": {
      "id": 13421
    }
  }
}

Cинхронизация статусов сотрудников в retailCRM и UIS


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


Как это выглядит
{
  "jsonrpc": "2.0",
  "id": "number",
  "method": "update.employees",
  "params": {
    "access_token": "N2dw2Rf33fn23fknkmdfeJmcP",
    "id": 13421,
    "calls_available": false
  }
}

Нюансы управления данными через API UIS


А сейчас, как обещал, расскажу о ключевых функциях по контролю передаваемых между телефонией и CRM данных, которые мы предусмотрели в обновленном API UIS.


  • Контролируемая защита данных. Запросы к API осуществляются по ключам с разграниченными правами доступа. Ключи API создаются под конкретного пользователя и обладают набором прав, аналогичным полномочиям пользователя в Личном кабинете UIS. Например, если у него есть только доступ на просмотр сотрудников, и редактировать их профили в интерфейсе UIS он не может, то не сможет сделать это и через API.
  • Журнал-лог запросов в личном кабинете. Еще один важный шаг к повышению прозрачности всего процесса по работе с API.
  • Гибкие условия фильтрации для получения данных. Задавать условия можно самостоятельно.
  • Передача массивов в запросах для получения списка конкретных сущностей (сотрудников, звонков и пр.). Раньше, чтобы получить, например, профили сотрудников Коли, Васи и Пети, нужно было делать три запроса к API, а теперь это один запрос, в котором указаны ID нужных сотрудников.
  • Частичное обновление данных. Отправлять всю простыню свойств обновляемой сущности в запросе на обновление не нужно — достаточно отправить только те поля, которые реально изменились.
  • Индивидуальное определение получаемых полей. В запросе на получение данных задаются только интересующие вас параметры. Профит — фильтрация хлама в виде ненужной информации.
  • Продуманная система ошибок. Это для того, чтобы упростить диагностику проблем.

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


P.S. Кстати говоря, если вы представитель CRM-системы, которой не хватает интеграции с телефонией, то тоже буду рад сотрудничать. Вы поможете нам проработать схему готовых партнерских интеграций в один клик из Личного кабинета UIS, а мы вам — сделать интеграцию наших сервисов для ваших пользователей.

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

https://habrahabr.ru/post/330396/


[Перевод] Нативные EcmaScript модули: новые возможности и отличия перед webpack

Среда, 07 Июня 2017 г. 10:06 + в цитатник

image


В предыдущей статье Нативные ECMAScript модули — первый обзор я рассказал историю JavaScript модулей и текущее состояние дел реализации нативных EcmaScript модулей.


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


Основные мысли:


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

https://habrahabr.ru/post/329918/


Метки:  

Notepad++: проверка кода пять лет спустя

Среда, 07 Июня 2017 г. 09:04 + в цитатник
Picture 1

В этом году статическому анализатору PVS-Studio исполнилось 10 лет. Правда, стоит уточнить, что 10 лет назад он назывался Viva64. И есть ещё одна интересная дата: прошло 5 лет с момента предыдущей проверки кода проекта Notepad++. С тех пор PVS-Studio был очень сильно доработан: добавлено около 190 новых диагностик, усовершенствованы старые. Впрочем, ожидать огромного количества ошибок в Notepad++ не стоит. Это небольшой проект, состоящий всего из 123 файлов с исходным кодом. Тем не менее, в коде найдены ошибки, которые будет полезно исправить.

Введение


Notepad++ — свободный текстовый редактор с открытым исходным кодом для Windows, с подсветкой синтаксиса большого количества языков программирования и разметки. Базируется на компоненте Scintilla, написан на C++ с использованием STL, а также Windows API и распространяется под лицензией GNU General Public License.

На мой взгляд, Notepad++ отличный текстовой редактор. Я сам его использую для всего, кроме написания кода. Для анализа исходников я воспользовался статическим анализатором PVS-Studio 6.15. Проект Notepad++ уже проверялся в 2010 и 2012 годах. Сейчас нашлось 84 предупреждения уровня High, 124 предупреждения уровня Medium и 548 предупреждений уровня Low. Уровни предупреждений указывают на достоверность найденных ошибок. Так, из 84-х наиболее достоверных предупреждений (High), 81, на мой взгляд, указывают на настоящие дефекты в коде — их стоит сразу исправить, не вникая глубоко в логику программы, т.к. проблемы очевидны.

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

Рисунок 1 - Разные отступы в коде.


Рисунок 1 — Разные отступы в коде.

Давайте рассмотрим некоторые ошибки, которые показались мне наиболее интересными.

Проблемы наследования


Picture 5



V599 The virtual destructor is not present, although the 'FunctionParser' class contains virtual functions. functionparser.cpp 39
class FunctionParser
{
friend class FunctionParsersManager;
public:
  FunctionParser(....): ....{};

  virtual void parse(....) = 0;
  void funcParse(....);
  bool isInZones(....);
protected:
  generic_string _id;
  generic_string _displayName;
  generic_string _commentExpr;
  generic_string _functionExpr;
  std::vector _functionNameExprArray;
  std::vector _classNameExprArray;
  void getCommentZones(....);
  void getInvertZones(....);
  generic_string parseSubLevel(....);
};

std::vector _parsers;

FunctionParsersManager::~FunctionParsersManager()
{
  for (size_t i = 0, len = _parsers.size(); i < len; ++i)
  {
    delete _parsers[i]; // <=
  }

  if (_pXmlFuncListDoc)
    delete _pXmlFuncListDoc;
}

Анализатором была найдена серьёзная ошибка, приводящая к неполному разрушению объектов. У базового класса FunctionParser присутствует виртуальная функция parse(), но отсутствует виртуальный деструктор. В иерархии наследования от этого класса присутствуют такие классы, как FunctionZoneParser, FunctionUnitParser и FunctionMixParser:
class FunctionZoneParser : public FunctionParser
{
public:
  FunctionZoneParser(....): FunctionParser(....) {};

  void parse(....);
  
protected:
  void classParse(....);

private:
  generic_string _rangeExpr;
  generic_string _openSymbole;
  generic_string _closeSymbole;

  size_t getBodyClosePos(....);
};

class FunctionUnitParser : public FunctionParser
{
public:
  FunctionUnitParser(....): FunctionParser(....) {}

  void parse(....);
};

class FunctionMixParser : public FunctionZoneParser
{
public:
  FunctionMixParser(....): FunctionZoneParser(....), ....{};

  ~FunctionMixParser()
  {
    delete _funcUnitPaser;
  }

  void parse(....);

private:
  FunctionUnitParser* _funcUnitPaser = nullptr;
};

Для наглядности я составил схему наследования для этих классов:

Рисунок 2 - Схема наследования от класса FunctionParser


Рисунок 2 — Схема наследования от класса FunctionParser

Таким образом, созданные объекты будут разрушаться не полностью. Это приведёт к неопределённому поведению программы. Нельзя сказать как будет вести себя программа после того, как в ней возникнет UB, но на практике в данном случае, как минимум, произойдёт утечка памяти, так как код «delete _funcUnitPaser» не будет выполнен.

Рассмотрим следующую ошибку.

V762 It is possible a virtual function was overridden incorrectly. See first argument of function 'redraw' in derived class 'SplitterContainer' and base class 'Window'. splittercontainer.h 61
class Window
{
  ....
  virtual void display(bool toShow = true) const
  {
    ::ShowWindow(_hSelf, toShow ? SW_SHOW : SW_HIDE);
  }

  virtual void redraw(bool forceUpdate = false) const
  {
    ::InvalidateRect(_hSelf, nullptr, TRUE);
    if (forceUpdate)
      ::UpdateWindow(_hSelf);
  }
  ....
}

class SplitterContainer : public Window
{
  ....
  virtual void display(bool toShow = true) const; // <= good

  virtual void redraw() const;                    // <= error
  ....
}

В коде Notepad++ найдено несколько проблем с перегрузкой функций. В классе SplitterContainer, унаследованного от класса Window, метод display() перегружен правильно, а при перегрузке метода redraw() допустили ошибку.

Ещё несколько неправильных мест:
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'UserDefineDialog' and base class 'StaticDialog'. userdefinedialog.h 332
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'FindReplaceDlg' and base class 'StaticDialog'. findreplacedlg.h 245
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'GoToLineDlg' and base class 'StaticDialog'. gotolinedlg.h 45
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'FindCharsInRangeDlg' and base class 'StaticDialog'. findcharsinrange.h 52
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'ColumnEditorDlg' and base class 'StaticDialog'. columneditor.h 45
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'WordStyleDlg' and base class 'StaticDialog'. wordstyledlg.h 77
  • V762 It is possible a virtual function was overridden incorrectly. See first argument of function 'redraw' in derived class 'WordStyleDlg' and base class 'Window'. wordstyledlg.h 99
  • V762 It is possible a virtual function was overridden incorrectly. See third argument of function 'create' in derived class 'PluginsAdminDlg' and base class 'StaticDialog'. pluginsadmin.h 107

Утечки памяти


Picture 4



V773 The function was exited without releasing the 'pXmlDocProject' pointer. A memory leak is possible. projectpanel.cpp 326
bool ProjectPanel::openWorkSpace(const TCHAR *projectFileName)
{
  TiXmlDocument *pXmlDocProject = new TiXmlDocument(....);
  bool loadOkay = pXmlDocProject->LoadFile();
  if (!loadOkay)
    return false;        // <=

  TiXmlNode *root = pXmlDocProject->FirstChild(TEXT("Note...."));
  if (!root) 
    return false;        // <=

  TiXmlNode *childNode = root->FirstChildElement(TEXT("Pr...."));
  if (!childNode)
    return false;        // <=

  if (!::PathFileExists(projectFileName))
    return false;        // <=

  ....

  delete pXmlDocProject; // <= free pointer
  return loadOkay;
}

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

V773 Visibility scope of the 'pTextFind' pointer was exited without releasing the memory. A memory leak is possible. findreplacedlg.cpp 1577
bool FindReplaceDlg::processReplace(....)
{
  ....
  TCHAR *pTextFind = new TCHAR[stringSizeFind + 1];
  TCHAR *pTextReplace = new TCHAR[stringSizeReplace + 1];
  lstrcpy(pTextFind, txt2find);
  lstrcpy(pTextReplace, txt2replace);
  ....
}

Функция processReplace() вызывается при каждой замене некой подстроки в документе. В коде выделяется память под два буфера: pTextFind и pTextReplace. В один буфер копируется искомая строка, а в другой — строка для замены. Тут присутствует несколько ошибок, следствием которых является утечка памяти:
  1. Буфер pTextFind не очищается и вообще не используется в функции. Для замены используется исходный буфер txt2find.
  2. Буфер pTextReplace в дальнейшем используется, но память тоже не освобождается.

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

Ошибки с указателями


Picture 9



V595 The 'pScint' pointer was utilized before it was verified against nullptr. Check lines: 347, 353. scintillaeditview.cpp 347
LRESULT CALLBACK ScintillaEditView::scintillaStatic_Proc(....)
{
  ScintillaEditView *pScint = (ScintillaEditView *)(....);

  if (Message == WM_MOUSEWHEEL || Message == WM_MOUSEHWHEEL)
  {
    ....
    if (isSynpnatic || makeTouchPadCompetible)
      return (pScint->scintillaNew_Proc(....); // <=
    ....
  }
  if (pScint)
    return (pScint->scintillaNew_Proc(....));
  else
    return ::DefWindowProc(hwnd, Message, wParam, lParam);
}

В одном месте пропустили проверку указателя pScint на валидность.

V713 The pointer _langList[i] was utilized in the logical expression before it was verified against nullptr in the same logical expression. parameters.h 1286
Lang * getLangFromID(LangType langID) const
{
  for (int i = 0 ; i < _nbLang ; ++i)
  {
    if ((_langList[i]->_langID == langID) || (!_langList[i]))
      return _langList[i];
  }
  return nullptr;
}

Автор кода допустил ошибку при записи условного выражения. Он сначала обращается к полю _langID, используя указатель _langList[i], а потом сравнивает этот указатель с нулём.

Скорее всего, правильный код должен быть таким:
Lang * getLangFromID(LangType langID) const
{
  for (int i = 0 ; i < _nbLang ; ++i)
  {
    if ( !_langList[i] && _langList[i]->_langID == langID )
      return _langList[i];
  }
  return nullptr;
}

Разные ошибки


Picture 6



V501 There are identical sub-expressions to the left and to the right of the '!=' operator: subject != subject verifysignedfile.cpp 250
bool VerifySignedLibrary(...., const wstring& cert_subject, ....)
{
  wstring subject;
  ....
  if ( status && !cert_subject.empty() && subject != subject)
  {
    status = false;
    OutputDebugString(
      TEXT("VerifyLibrary: Invalid certificate subject\n"));
  }
  ....
}

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

На фоне этого проверка
subject != subject

выглядит крайне подозрительно, скорее всего, правильно должно быть так:
if ( status && !cert_subject.empty() && cert_subject != subject)
{
  ....
}

V560 A part of conditional expression is always true: 0xff. babygrid.cpp 711
TCHAR GetASCII(WPARAM wParam, LPARAM lParam)
{
  int returnvalue;
  TCHAR mbuffer[100];
  int result;
  BYTE keys[256];
  WORD dwReturnedValue;
  GetKeyboardState(keys);
  result = ToAscii(static_cast(wParam),
    (lParam >> 16) && 0xff, keys, &dwReturnedValue, 0); // <=
  returnvalue = (TCHAR) dwReturnedValue;
  if(returnvalue < 0){returnvalue = 0;}
  wsprintf(mbuffer, TEXT("return value = %d"), returnvalue);
  if(result!=1){returnvalue = 0;}
  return (TCHAR)returnvalue;
}

Всегда истинные или всегда ложные условные выражения выглядят очень подозрительно. Константа 0xff всегда истинна. Возможно, допустили опечатку в операторе и параметр функции ToAscii() должен был быть таким:
(lParam >> 16) & 0xff

V746 Type slicing. An exception should be caught by reference rather than by value. filedialog.cpp 183
TCHAR* FileDialog::doOpenSingleFileDlg()
{
  ....
  try {
    fn = ::GetOpenFileName(&_ofn)?_fileName:NULL;
    
    if (params->getNppGUI()._openSaveDir == dir_last)
    {
      ::GetCurrentDirectory(MAX_PATH, dir);
      params->setWorkingDir(dir);
    }
  } catch(std::exception e) {                             // <=
    ::MessageBoxA(NULL, e.what(), "Exception", MB_OK);
  } catch(...) {
    ::MessageBox(NULL, TEXT("....!!!"), TEXT(""), MB_OK);
  }

  ::SetCurrentDirectory(dir); 

  return (fn);
}

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

V519 The 'lpcs' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 3116, 3117. babygrid.cpp 3117
LRESULT CALLBACK GridProc(HWND hWnd, UINT message,
                          WPARAM wParam, LPARAM lParam)
{
  ....
  case WM_CREATE:
    lpcs = &cs;
    lpcs = (LPCREATESTRUCT)lParam;
  ....
}

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

V601 The 'false' value becomes a class object. treeview.cpp 121
typedef std::basic_string generic_string;

generic_string TreeView::getItemDisplayName(....) const
{
  if (not Item2Set)
    return false;                     // <=
  TCHAR textBuffer[MAX_PATH];
  TVITEM tvItem;
  tvItem.hItem = Item2Set;
  tvItem.mask = TVIF_TEXT;
  tvItem.pszText = textBuffer;
  tvItem.cchTextMax = MAX_PATH;
  SendMessage(...., reinterpret_cast(&tvItem));
  return tvItem.pszText;
}

Возвращаемым значением функции является строка, но вместо пустой строки кто-то решил сделать «return false».

Чистка кода


Picture 8



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

V668 There is no sense in testing the 'source' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. notepad_plus.cpp 1149
void Notepad_plus::wsTabConvert(spaceTab whichWay)
{
  ....
  char * source = new char[docLength];
  if (source == NULL)
    return;
  ....
}

Вот зачем здесь эта проверка? Согласно современному стандарту C++, оператор new бросает исключение при нехватке памяти, а не возвращает nullptr.

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

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

V713 The pointer commentLineSymbol was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 3928
bool Notepad_plus::doBlockComment(comment_mode currCommentMode)
{
  ....
  if ((!commentLineSymbol) ||       // <=
      (!commentLineSymbol[0]) ||
       (commentLineSymbol == NULL)) // <= WTF?
  { .... }
  ....
}

Таких странных и бесполезных проверок найдено десять штук:
  • V713 The pointer commentLineSymbol was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 3928
  • V713 The pointer commentStart was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 3931
  • V713 The pointer commentEnd was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 3931
  • V713 The pointer commentStart was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 4228
  • V713 The pointer commentEnd was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 4228
  • V713 The pointer commentLineSymbol was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 4229
  • V713 The pointer commentStart was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 6554
  • V713 The pointer commentEnd was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 6554
  • V713 The pointer commentLineSymbol was utilized in the logical expression before it was verified against nullptr in the same logical expression. notepad_plus.cpp 6555

V601 The 'true' value is implicitly cast to the integer type. pluginsadmin.cpp 603
INT_PTR CALLBACK PluginsAdminDlg::run_dlgProc(UINT message, ....)
{
  switch (message)
  {
    case WM_INITDIALOG :
    {
      return TRUE;
    }
    ....
    case IDC_PLUGINADM_RESEARCH_NEXT:
      searchInPlugins(true);
      return true;

    case IDC_PLUGINADM_INSTALL:
      installPlugins();
      return true;
    ....
  }
  ....
}

Функция run_dlgProc() и так возвращает значение далеко не логического типа, так ещё в коде возвращают то true/false, то TRUE/FALSE. Хотел написать, что в функции хотя бы отступы одного типа, но нет: из 90 строк функции в одной строке все равно присутствует смесь из табуляций и пробелов. В остальных строках используются символы табуляции. Да, это всё не критично, но код выглядит для меня, как стороннего наблюдателя, неаккуратным.

V704 '!this' expression in conditional statements should be avoided — this expression is always false on newer compilers, because 'this' pointer can never be NULL. notepad_plus.cpp 4980
void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask)
{
  // To avoid to crash while MS-DOS style is set as default 
  // language,
  // Checking the validity of current instance is necessary.
  if (!this) return;
  ....
}

К бесполезному коду я бы ещё отнёс такие проверки. Как видно из комментария, раньше проблема разыменования нулевого this была. Согласно же современному стандарту языка C++, такая проверка является лишней.

Список всех таких мест:
  • V704 'this && type == DOCUMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 505
  • V704 'this && type == ELEMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 506
  • V704 'this && type == COMMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 507
  • V704 'this && type == UNKNOWN' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 508
  • V704 'this && type == TEXT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 509
  • V704 'this && type == DECLARATION' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxmla.h 510
  • V704 'this && type == DOCUMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 505
  • V704 'this && type == ELEMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 506
  • V704 'this && type == COMMENT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 507
  • V704 'this && type == UNKNOWN' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 508
  • V704 'this && type == TEXT' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 509
  • V704 'this && type == DECLARATION' expression should be avoided: 'this' pointer can never be NULL on newer compilers. tinyxml.h 510
  • V704 'this' expression in conditional statements should be avoided — this expression is always true on newer compilers, because 'this' pointer can never be NULL. nppbigswitch.cpp 119

Заключение


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

Конечно, обычному пользователю описанные проблемы не видны. Модули оперативной памяти сейчас больших объёмов и дешёвые :). Тем не менее, развитие проекта продолжается, а качество кода, как и удобство его поддержки, можно значительно улучшить, исправив найденные ошибки и удалив пласты устаревшего кода.

По моим расчётам, на 1000 строк кода анализатор PVS-Studio выявлял 2 настоящие ошибки. Конечно, это не все ошибки. Думаю, на самом деле их будет где-то 5-10 на 1000 строк кода, что соответствует небольшой плотности ошибок. Размер проекта Notepad++ составляет 95 KLoc, а значит типичная плотность ошибок для проектов этого размера: 0-40 ошибок на 1000 строк кода. Впрочем, источник этих чисел стар, и я считаю, что, в среднем, качество кода сейчас стало выше.

Ещё раз хочу поблагодарить авторов Notepad++ за их работу над крайне полезным инструментом и желаю им всевозможных успехов.



Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Svyatoslav Razmyslov. Checking Notepad++: five years later

Прочитали статью и есть вопрос?
Часто к нашим статьям задают одни и те же вопросы. Ответы на них мы собрали здесь: Ответы на вопросы читателей статей про PVS-Studio, версия 2015. Пожалуйста, ознакомьтесь со списком.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330394/


«Искусство в мире развлечений»: Чем занимаются художники в игровой индустрии

Среда, 07 Июня 2017 г. 08:13 + в цитатник
Видеоигры проделали долгий путь с момента их зарождения в 70-х годах прошлого века. Сегодня они остаются одним из самых популярных развлечений, в немалой степени благодаря распространению мобильных платформ. Что же делает современные игры популярными? В основном это заслуга трех составляющих: сюжета, музыкального сопровождения и графики. Все они взаимосвязаны, но «картинка» при этом является одним из самых важных компонентов — это то, что видят игроки.

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

Photo by Inventain

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

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

Создание эффекта погружения


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

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

Мобильные игры также следуют этому правилу. Например, проекты Inventain Bowmasters и Happy Racing выполнены в уникальном, развиваемом компанией стиле. Обе эти игры посвящены созданию хаоса, и артстайл дополняет то безумие, которое происходит на экране мобильного устройства. Задачей художников в этом случае было «всколыхнуть» сознание клиентов и сделать то, чего в мобильной индустрии еще никто не делал.

Photo by Inventain

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

Примером проекта с достоверными обликами может служить The Banner Saga. Художник и дизайнер Виктория Смит (Victoria Smith) отмечает, что «некачественные» костюмы могут испортить даже самых сильных персонажей. Поэтому при работе над одеждой героев The Banner Saga, разработчики старались достигнуть максимальной исторической достоверности.

Команда Inventain тоже уделяет внимание мелочам. Во время дизайна меню или уровней они прилагают усилия, чтобы достичь wow-эффекта в самых (казалось бы) незначительных моментах. Даже если в какое-либо место на уровне или страницу в меню зайдет всего 5% пользователей, они все равно найдут в их проектах интересные детали и приятные мелочи.

Креативная подача и взаимодействие с пользователями


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

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

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

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

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

Переосмысление и доработка


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

Одним из самых громких ремейков последних лет стал DOOM. Разработчикам удалось воссоздать ту самую игру, но в новых декорациях. Художники перенесли на современный движок всех монстров из оригинала, сохранив их образы, но при этом придав им лоска. Благодаря этому DOOM получил награды за лучший гейм-дизайн и разошелся тиражом практически в 2 млн копий.

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

Поэтому если программисты способны творить, нужно позволить им это делать — это рождает интересные идеи. Также это упрощает процессы коммуникации в команде — художникам становится проще донести мысль до «мастеров кода». Вкупе все эти особенности помогают создать удивительные миры и уровни, которые будут удерживать игрока в напряжении, и заставлять его возвращаться туда снова и снова.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330388/


Метки:  

Вышло обновление Apache Hadoop впервые за два года

Среда, 07 Июня 2017 г. 08:04 + в цитатник
Пятого июня Apache Software Foundation впервые за два года выпустила обновление фреймворка для разработки и выполнения распределённых программ Apache Hadoop. Версия Apache Hadoop 2.8 получила ряд улучшений, связанных с облачными технологиями и безопасностью.

/ фото Jermaine Janszen CC

Хотя большинство клиентов используют фреймворк для работы с физическими кластерами и устройствами хранения в собственных дата-центрах, новая версия делает упор на функции для пользователей, работающих с Hadoop в облачных инфраструктурах. Значительный вклад в релиз сделали такие компании, как Microsoft и Amazon Web Services, поэтому одним из нововведений является поддержка Microsoft Azure Data Lake.

Релиз Apache Hadoop 2.8, явившийся результатом двухлетней работы и вобравший в себя почти 3 тыс. коммитов, также получил важные улучшения в безопасности, включая защиту от атак вида Cross-Frame Scripting (XFS) в Hadoop UI и атак Cross-Site Request Forgery (CSRF) в Hadoop REST API.

Значительные улучшения были произведены в области масштабирования, производительности и безопасности у клиента S3A, предназначенного для работы с данными в облаке Amazon S3. Разработчикам удалось достигнуть скорости работы клиента, которая не уступает закрытому решению Amazon EMR.

Также были сделаны улучшения в WebHDFS: реализована фильтрация CSRF-атак, поддержка OAuth2, разрешение/запрет снапшотов. Была улучшена интеграция с другими приложениями благодаря вынесению hdfs-клиента в отдельный JAR-файл.

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

Полный список функций, улучшений и исправлений Apache Hadoop 2.8 можно найти по ссылке.

P.S. О чем еще мы пишем в Первом блоге о корпоративном IaaS:

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

https://habrahabr.ru/post/330336/


Метки:  

Netflix выходит из «битвы» за сетевой нейтралитет

Среда, 07 Июня 2017 г. 08:03 + в цитатник
На конференции Code Conference 2017 генеральный директор Netflix Рид Хастингс (Reed Hastings) заявил, что компания прекращает поддержку концепции сетевого нейтралитета, которой угрожает предложение Федеральной комиссии по связи (FCC) США отозвать запрет на приоритизацию одних классов приложений (например, World Wide Web) перед другими (например, IP-телефония) провайдерами телекоммуникационных услуг.

Mark Bonica / Flickr / CC

Сетевой нейтралитет — это право человека на равный доступ ко всем интернет-ресурсам. Термин придумал профессор Колумбийского университета Тим Ву (Tim Wu) в начале 2000 годов. Речь идёт прежде всего о скорости подключения и необходимости дополнительной платы за него в определённых случаях.

И в 2012 году, когда компания Netflix была маленькой (обладая только стриминговыми сервисами и сервисами аренды DVD), она занимала активную позицию по защите сетевого нейтралитета. Когда Microsoft решила позволить провайдерам (в частности, Comcast) использовать Xbox в качестве устройства аутентификации для существующих абонентов кабельного ТВ, Хастингс раскритиковал это решение. С тех пор Netflix еще много раз поддерживали идею нейтральности сети.

Однако с каждым годом поддержка Netflix ослабевала, и вот — прекратилась совсем. «Теперь это не наша битва, — отметил Хастингс. — Мы довольно большая компания, потому можем заключать сделки, которые захотим».

Хастингс открыто заявил, что Netflix больше не заинтересована в сохранении сетевой нейтральности, поскольку платформа является лидером на видеостриминговом рынке. Решение FCC позволит Netflix укрепить свои позиции как минимум в краткосрочной перспективе. Если сетевой нейтралитет «падет», то Netflix установит высокий порог вхождения на рынок, и эту планку не смогут преодолеть новые стриминговые сервисы.

Однако есть основания полагать, что FCC проиграет суд по этому вопросу, поскольку согласно опросу, проведенному в США, общественность настроена против прекращения существования концепции нейтральности. Поэтому к чему приведет высказывание CEO Netflix, сейчас определить сложно.

P.S. Еще несколько материалов из блога VAS Experts:

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

https://habrahabr.ru/post/330306/


Метки:  

MySQL 8, Postgres NoSQL, Tarantool Винил, CockroachDB, ClickHouse, и все-же, почему Uber ушел от Postgresql?

Среда, 07 Июня 2017 г. 07:38 + в цитатник
17 июня в Москве, Измайлово пройдет конференция Devconf::Storage

Базы данных становятся все чудесатее и чудесатее. Традиционные RDBMS становятся NoSQL, а новые движки становятся кластерными, распределенными и колоночными.

Олег Бартунов, известный разработчик Postgres, хочет рассказать чем их база лучше MongoDB при работе с JSON, а его коллега Иван Панченко — о том, как писать для постгреса на perl, python и javascript.
Антон Околелов расскажет как перейти с MySQL, чтобы ощутить мощь Postgres, а другой докладчик, Алексей Копытов расскажет почему Uber сделал точно наоборот, и ушел с Postgres на MySQL.

Дмитрий Ленев и Игорь Ильин из команды MySQL расскажут о новых возможностях своего продукта. Нас будут радовать асимптотическим приближением к полной реализации SQL, оконными функциями, традиционным улучшением INFORMATION_SCHEMA, индексов, NOWAIT в SELECT и групповой репликацией.

Константин Осипов проводит углубленный экскурс в логово своего питомца Tarantool, который поселился в корнях LSM-дерева.

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

До встречи на конференции сообществ разработчиков DevConf 2017!
Какая ваша любимая база данных?

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

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

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

https://habrahabr.ru/post/330386/


Метки:  

[recovery mode] Несколько слов про «наш» микроконтроллер

Среда, 07 Июня 2017 г. 05:25 + в цитатник

В статье речь пойдёт про отечественный МК фирмы Миландр 1886ВЕ5У, будет совсем немного кода и много нытья.

Данный МК построен на ядре PIC17, что заметно при разработке — так как у меня уже есть солидная кодовая база для PIC, мне было чуть проще начать. Также под данный МК можно приобрести отладочную плату — о ней я тоже пару слов напишу.

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

Итак, поехали.


Первое, с чем в 2017-м году столкнётся желающий использовать в своих разработках МК от Миландра — это сложности с покупкой. Даже не говоря о цене, вам для этого скорее всего потребуется как минимум какое-нибудь юр.лицо. По крайней мере, когда я звонил им в отдел маркетинга и узнавал о покупке как физ.лицо, мне ясно дали понять, что в этом случае мне проще будет найти какого-нибудь поставщика (цены у которых ещё выше). В общем, с маркетингом всё печально. С другой стороны, сайт они вон уже обновили, может и до маркетинговой политики руки дойдут как-нибудь.

Корявая документация.


Несмотря на то что 1886ВЕ5У вышел уже лет пять назад минимум, «детские болезни» никуда не делись. При чтении тех.документации создаётся ощущение, что делали её наспех. Нет, критически важная информация там, в принципе, присутствует, только вот структурирована она достаточно странно. В тексте периодически встречаются опечатки, да и сама структура документа, на мой взгляд, не блещет логичностью. В итоге при разработке вместо изучения одного единого документа периодически приходится метаться между несколькими открытыми окнами или искать нужные в текущий момент фрагменты в основном даташите, которые могут располагаться в документе достаточно далеко друг от друга, даже если относятся к одному блоку чипа.

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

В качестве иллюстрации приведу один пример. Для расчёта скорости CAN-интерфейса нам предлагают воспользоваться несколькими формулами.

При расчёте получается, что итоговая формула, фактически, будет иметь пять параметров (BRP, PRSEG, SEG1, SEG2, Fosc). Сама формула и зависимость параметров от значений бит в регистрах разнесены страниц на пятнадцать. В итоге, проще сделать скрин с таблицей значений регистров и открывать его в пэинте, пока разбираешься с формулой.

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

Вопрос к составителям документации — собственно, а в чём проблема была добавить всего пару страниц с таблицами, содержащими базовые значения при нескольких значениях параметров? За примером далеко ходить не надо — даже в документации на PIC такие таблицы есть, например, в разделах про настройку скорости UART.

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

В общем, если у нас есть два устройства на 1886ВЕ5У, одно из которых работает на 16 МГц (отладочная плата, например), а второе на 10 МГц (наша железка), то связать их, скорее всего, получится только на низкой скорости, и то не факт. И вот почему.

Во первых — максимальная скорость (для железки работающей на 10 МГц) при всех выключенных делителях ограничена 390.6 кБит/с.

Во вторых — при 10 МГц дискретность изменения такова, что получить, например, стандартные 250, 125 или 100 кБит/с никак не получится. По расчётам самое близкое получается, например 104.2 кБит/с (BRP=1, PRSEG=1, SEG1=5, SEG2=5). В общем, ошибка в несколько % так или иначе будет присутствовать. Я уже писал выше — пока ещё я не дофига спец в данном протоколе, возможно он и с такой ошибкой заработает на низких скоростях — в конце концов у данной шины весьма большой запас по надёжности передачи данных.

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

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


Вообще вся «демо-программа» для работы с отладочной платой на PC (называется она, почему-то, Eval12.exe) достаточно убогая. Из настроек там буквально только параметры COM-порта, через который вы будете с платой связываться и всё. Ну то есть, вообще всё. Скорость CAN изменить через неё никак нельзя. Изменять параметры МК, установленного в отладочную плату тоже нельзя, хотя это бывает весьма кстати.

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

Далее я взял исходники из папки Demo_CAN, которая шла на диске с отладочной платой, надеясь просто перекомпилировать их, задав необходимые BRP, PRSEG, SEG1, SEG2. При попытке компиляции данного проекта IDE выдала прекрасную ошибку:

"Программа защищена. По вопросам приобретения обратитесь в компанию МИЛАНДР."

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

Бардак в заголовочных файлах.


С диска, который шёл с отладочной платой я забрал папку "komplekt_1886BE5\Демо программы".

Там лежали отдельные папки с исходниками примеров работы с CAN и LIN.
При этом в main.c этих исходников были включён следующий хедер:

#include

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

Далее, последовав совету тех.поддержки (пользуясь случаем, хочу поблагодарить сих достойнейших граждан за терпение и профессионализм — помогли мне решить пару тупых вопросов) я скачал с сайта Миландра IDE (Dev-C++ какой-то древней версии) и компилятор (CC7A).

Каково же было моё удивление, когда IDE отказалась собирать мой исходник с указанным выше хедером. Далее выяснилось, что с компилятором под мой чип идёт свой хедер — 1886VE5.h

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

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

В общем-то проблема не критичная, но осадочек, как говорится, остался.

Среда, компилятор и их, кхм… особенности


В качестве среды и компилятора для 1886ВЕ5У Миландр предлагает нам использовать связку IDE1886 (на базе Dev-C++) и CC7A. В общем-то про среду ничего особо плохого сказать не могу — с программатором работает нормально, отладчик тоже вроде сносно отлаживает, разве что подсветка синтаксиса печальная, конечно. Наверняка есть какие-нибудь плагины или ещё что-то, но по дефолту это прям чуть ли не Виндовый блокнот — выделяет камменты, инклюды и некоторые ключевые слова, на этом бонусы редактора заканчиваются.

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

Ещё один момент, конечно, скорее говорит о моём малом опыте разработчика, но каково же было моё удивление, когда я, после нескольких часов ковыряния в отладчике и попытках разобраться почему же генерируемый компилятором ассемблерный код работает так странно, прочёл в документации, что тип int по умолчанию у данного компилятора имеет размер 8 бит, а не 16, как принято в том же XC8 для PIC.

Поэтому скажу банальность, но всё же — внимательней изучайте документацию перед разработкой =)

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

Компилятор совершенно не способен переварить вот такую несложную конструкцию:

TXSTA1 = ((CSRC & 0x01) << 7) | ((TX9 & 0x01) << 6) |((TXEN & 0x01) << 5) |((SYNC & 0x01) << 4);


На это он просто выдаёт сакраментальное: "Unable to generate code."

Чтобы он понял чего я от него хочу, приходится расписывать это на банальный и объёмный код:

temp0 = ((CSRC & 0x01) << 7);
temp1 = ((TX9 & 0x01) << 6);
temp2 = ((TXEN & 0x01) << 5);
temp3 = ((SYNC & 0x01) << 4);


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

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

Напоследок


Есть ещё один момент, вероятно, связанный с архитектурой ядра. В описании к 1886ВЕ5У на сайте Миландра можно найти упоминание, что он построен на ядре PIC17. Я так понимаю, что данная особенность, свойственна всем контроллерам на ядре PIC17 — при возникновении прерывания, они не сохраняют состояние регистров, соответственно, этот момент надо реализовывать программно при необходимости. Вот это меня, честно говоря, тоже поразило — неужели в 1886ВЕ5У никак нельзя было реализовать это аппаратно?

Вообще, попробовав писать под данный МК я был вынужден ковыряться в ассемблерном коде, разбираться что это там за циферки меняются в окне «RAM» во время отладки и прочее. Это, безусловно, повысило мою квалификацию как разработчика, поскольку я чуть лучше стал понимать что там внутри и как работает. Однако, после того же Microchip'а (который частенько ругают за «безумную» Errata), кодинг под «наш» МК ощущается прям как программирование под какой-нибудь 386-й в DOS. Кстати, по поводу Errata — к данному МК вообще ничего типа Errata нет.

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

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

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

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

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

https://habrahabr.ru/post/330384/


Метки:  

Генерируем произвольные последовательности на выводах платы Raspberry Pi

Вторник, 06 Июня 2017 г. 23:36 + в цитатник


Автор: Николай Хабаров, Embedded Expert DataArt, евангелист технологий умного дома.

В этой статье я расскажу, как написать обычное user space-приложение на Python для современного ARM-процессора с ОС Linux для генерирования сложных последовательностей импульсов на выводах платы. Суть идеи — использовать DMA-модуль процессора для копирования из предварительно подготовленного буфера в памяти в GPIO с высокой точностью по времени.

Когда речь заходит о необходимости сгенерировать сложную последовательность импульсов, например, для шаговых двигателей, обычно используют старые добрые простенькие микроконтроллеры с установленной специальной операционной системой реального времени или вообще без операционной системы. Реализация при этом, в лучшем случае, написана на C++. Сейчас процессоры шагнули далеко вперед и имеют массу преимуществ: производительность, возможность использования операционной системы Linux со всей инфраструктурой и ПО, а также высокоуровневых языков программирования, таких как Python. И все же современные микроконтроллеры для генерирования сложных последовательностей на выводах GPIO, как правило, не используют.

Я реализовал генерацию импульсов для управления шаговыми двигателями проекта PyCNC — проекта контроллера машин с ЧПУ, станков, 3D-принтеров, полностью написанного на Python и запускаемого на современном ARM-процессоре на плате Raspberry Pi.

Статья может быть полезна желающим реализовать генерацию сложных последовательностей установки уровней на выводах одного или нескольких GPIO на других высокоуровневых языках программирования, используя DMA-модули других процессоров. Читать дальше →

https://habrahabr.ru/post/330378/


HP DL120 G7 — вторая жизнь сервера

Вторник, 06 Июня 2017 г. 21:20 + в цитатник


Привет Хабр! За бортом 2017 год и на рынке доступны новые сервера поколения HP G9, а скоро думаю появятся и HP G10.

Но «денег нет», и вы приняли решение купить БУ сервер или провести оптимизацию существующего парка серверов. И в этом случаи я хочу обратить ваше внимание на пару моментов связанных с дисковой подсистемой сервера HP DL120 G7.

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

Мне достался сервер 628692-421 c хот плаг дисками 3,5(4 шт), процессором Xeon E3-1240, 16гб рам и контроллер Smart Array P212/256MB c дисками SAS 10k 400GB.

HP Smart Array P212


Этот контроллер можно встретить почти во всех серверах HP поколения G5/G6/G7. Список серверов можно найти на сайте HPE QuickSpecs.

Если в сервере установлен опциональный контроллер Smart Array, вы сможете мониторить состояние дисков через ILO3.



На скриншоте вы можете наблюдать состояние диска HGST HTS721010A, устанавливая не оригинальные диски в сервера HP вы рискуете получать не достоверную информацию про диски. В данном случаи не правильно определяется температура диска, в результате сервер выводит обороты вентиляторов на 100% скорости и серверная превращается в пилораму.

Вывод № 1 – не все диски одинаково полезны, «выбирайте оригинальные диски HP».

По умолчанию контроллер HP Smart Array P212 кэширует только операции чтения, а для включения кэширования операций записи рекомендуется установка Battery Kit.



При отсутствии Battery Kit есть вероятность потерять данные при отключении электричества. Если вы включили кэширование операций записи без батарейки — делаете это вы на свой страх и риск.

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

Давайте посмотрим на то как настройки кэширования влияют на скорость.


В качестве попугаев я выбрал скорость клонирования VM размером 38 ГБ.

1 — Копирование с диска SAS 10k на диск SATA 7k
2 — Копирование с диска SAS 10k на диск SAS 10k(2,5inch)
3 — Копирование с диска SATA 7k на диск SAS 10k
4 — Копирование с диска SATA 7k на диск SAS 10k(2,5inch)
5 — Копирование с диска SAS 10k(2,5inch) на диск SATA 7k



Вывод № 2 – отдавайте на запись не менее 50% от размера кеш памяти.

Про SAS диски


Обратите внимание на копирование между SAS 10к дисками, в некоторых случаях 10к проигрывает 7к SATA дискам.

Стоит признать что локальные диски SAS 10k в серверах все менее актуальны, эти диски не могут конкурировать по количеству операций с SSD.

HP Smart Array P212 + SSD


В серверах у меня все еще нету SSD и я решил посмотреть как не самый новый Smart Array контроллер переживет подключение SSD.

У меня был один единственный SSD Kingston SHFS37 на 120 ГБ который я вынул из ноутбука. Хочу сразу отметить что для серверов необходимо выбирать SSD с защитой от пропадания питания, такая защита заявлена производителями в дисках Intel DC и Kingston KC400.

SSD определился и его состояние можно наблюдать через ILO3.



Тестирование SSD


1,2 — Копирование с диска SATA на диск SSD
3,4 — Копирование с диска SSD на диск SATA
5,6 — Копирование с диска SATA на диск SATA
7,8,9 — Копирование с диска SSD на диск SSD



Если отключить кэширование записи, потеря скорости SSD не заметна, в то время как SATA HDD заметно проседает.



Вывод № 3 – SSD показывает отличную скорость и его можно использовать без кэширования операций записи.

HP Smart Array B110i


Если опциональный HP Smart Array контролер отсутствует в сервере, диски будут работать с контроллером на материнской плате HP Smart Array B110i. К B110i можно подключить только SATA диски.

HP Smart Array B110i Можно встретить в серверах HP ML110, ML150, ML330, DL120, DL160, DL180, DL320 поколения G6, и в серверах ML110, DL120, DL165 поколения G7. Также этот контроллер встречается в некоторых серверах серии SL.

Контроллер по умолчанию работает в режиме SATA Legacy, сразу отмечу что это не самый удачный режим, с такими настройками диски будут работать очень медленно.

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

Доступны три режима работы контроллера:
1 — SATA RAID
2 — SATA AHCI
3 — SATA Legacy



VMware ESXi не умеет работать с дисками собранными в рейд и подключенные к этому контроллеру, и по этому дальше я буду тестировать сервер установив на него WS2012R2.

1 — SATA Legacy


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



После отключения кэширования падение скорости для обычных дисков ужасна, 20 MB/s это очень удачный скриншот — и результаты могут быть гораздо хуже.


2 — SATA AHCI


Программное кэширование операций записи также включено по умолчанию.


После отключения кэширования HDD просели не так сильно как в случаи SATA Legacy.



Вывод номер 4 – В случаи если вам не нужен аппаратный RAID, HDD должны работать в режиме AHCI, а программное кэширование операций записи следует отключить чтобы гарантировать сохранность данных.

3 — SATA RAID


HP Smart Array B110i поддерживает только «программный рейд» R10 и R1. Хочется написать про него что-то плохое — но не думаю что у вас могут быть с ним проблемы, но все же при любой возможности делайте апдейт до полноценного HP HP Smart Array, с кэш памятью и батарейками.

Включить кэширование записи в Windows не получится, данная ф-ция не поддерживается драйверами контроллера. Для HP Smart Array P212 программное кэширование включить также не получится.


В этот раз я объединил два сата диска в R1, и по этому средняя скорость получилась больше.



Про надежность и сохранность данных


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

Обращаю внимание на это по тому что HP ранее заявляли совместимость конфигурация рейд массивов при перестановки дисков между контроллерами или между серверами.



Вывод номер 5 – храните резервные копии на отдельном устройстве.

ИТОГО


1 – Не все диски одинаково полезны, «выбирайте оригинальные диски HP».
2 – Отдавайте на запись не менее 50% от размера кеш памяти.
3 – SSD показывает отличную скорость и его можно использовать без кэширования операций записи.
4 – В случаи если вам не нужен аппаратный RAID, HDD должны работать в режиме AHCI, а программное кэширование операций записи следует отключить чтобы гарантировать сохранность данных.
5 – храните резервные копии на отдельном устройстве.

П.С.


Для настройки дисковой подсистемы из графической консоли нужно скачать образ загрузочного диска HP Smart Start CD 8.70(B).

Для большего удобства при работе с сервером не помешает лицензия на HP ILO Advanced, демо лицензию можно получить тут.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330286/



Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 996 995 [994] 993 992 ..
.. 1 Календарь