Особенность разработки программного обеспечения

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

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 14.03.2016
Размер файла 763,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Рисунок 10. Пользовательский интерфейс в режиме конфигуратора при добавлении процессов на узел

2.2 Разработка алгоритмов и программного обеспечения модуля менеджера проектов кластера

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

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

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

Блок работы с файлами проектов: созданию, сохранению, редактированию и открытию проектов

Блок менеджера проектов работает в 2х режимах:

- открытие, просмотр и редактирование проекта;

- создание, заполнение и сохранение проекта.

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

Рисунок 11. Файловая структура проекта

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

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

Рисунок 12. Внешний вид всплывающих уведомлений

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

Графический интерфейс пользователя в режиме работы с проектами

Внешний вид меню файлового навигатора менеджера проектов и его окно с древовидным отображением структуры каталогов представлено на рис. 14.

Рисунок 14. Меню для открытия проектов и окно навигации по папкам

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

В окне изменения названия и описания проектов доступно 2 текстовых поля ввода соответственно. Также присутствуют 3 кнопки; «Загрузить», «Сохранить» и «Закрыть». Последняя была введена вместо стандартного крестика закрывания окна, чтобы предотвратить случайное закрытие и потерю данных. Нажатие на довольно крупную кнопку с соответствующей надписью будет с большей степенью вероятности сознательным, также при закрытии поля ввода будут проверены на корректность и заполненность, а в случае ошибки будет выдано всплывающее предупреждение.

Рисунок 15. Окно ввода описания проекта и подсказка пользователю

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

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

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

Блок обработки получаемой по кластеру статистики от стороннего программного обеспечения

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

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

- информацию о запущенных на узле процессах;

- информацию о загруженности узла задачами.

Запущенные задачи на узле делятся на 3 типа:

1. задачи, изначально запущенные на узле;

2. задачи, переданные на обработку узлу другим узлом;

3. задачи, отданные другому узлу на обработку.

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

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

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

Графический интерфейс отображения общего состояния узлов сети в режиме мониторинга кластера на основе статистики

Графический интерфейс режима мониторинга состоит из:

1. изображений компьютеров, обозначающих узлы кластера;

2. текстовых полей, закрепленных «вместо» мониторов компьютеров, служащих для отображения состояния узлов в текстовом виде;

3. мигающий надписи «Главный узел», которая раз в секунду меняет цвет между черным и красным;

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

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

Рисунок 17. Главное окно мониторинга состояния кластера

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

При нажатии на кнопку с изображением узла происходит открытие нового окна подробной статистики по узлу. Окно отображает;

- номер выбранного для просмотра узла;

- статус его активности в последний момент времени;

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

- процессы, имеющие отношение к узлу и разделенные на 3 группы в зависимости от их текущего места исполнения.

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

Рисунок 18. Окно подробной статистики выбранного узла в режиме мониторинга

Глава 3. Отладка и тестирование программного обеспечения

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

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

2. конфигуратор кластера собирает и модифицирует конфигурационные структуры разработанного формата в выделяемой оперативной памяти с последующей их записью или «превращением» в реальные конфигурационные файлы узлов;

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

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

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

Для проведения модульного тестирования был составлен алгоритм, показанный на рис. 19, отражающий последовательность действий оператора при работе с программным комплексом на всех стадиях подготовки кластера к функционированию: от создания проекта, до инициализации созданной конфигурации и слежения за ее работоспособностью. Согласно алгоритму проводилось тестирование программы, включающее создание тестовых конфигураций кластера. В качестве тестовой конфигурации создавалось 3 узла в конфигураторе и за каждым из них закреплялось по несколько тестовых процессов, с заданными параметрами (порядок запуска, приоритет и т.д.). Каждый раз процессы распределялись по разному и конфигурация инициализировалась в реальную работающую систему. После инициализации программа запускалась в режиме мониторинга и подключалась к сети. Отображаемая статистическая информация сравнивалась с реальным состоянием узлов и в случае возникновения ошибок код корректировался.

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

Глава 4. Контрольный пример

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

Для того чтобы эмулировать различные отказы, были использованы стандартные утилиты операционных систем типа unix:

- утилита /bin/cat - для эмуляции процесса, выполняющегося без каких-либо ошибок;

- утилиты /bin/echo и /bin/ls - для эмуляции процессов, завершившихся после непродолжительной работы в системе;

- утилита /bin/true - для эмуляции процесса, завершившегося сразу после создания;

- утилита /bin/sleep - для эмуляции процессов, завершающихся в произвольный момент времени.

Конфигурация для каждого из узлов приведены в таблицах 3-5.

Таблица 3. Конфигурация первого узла кластера

Идентификатор процесса в системе

Путь к процессу

Аргументы командной строки

Зависимости от других процессов

Начальный приоритет

1

/bin/echo

Cluster test

8, 2, 4, 5

20

2

/bin/cat

-u -c

8, 7

10

3

/bin/cat

4, 7

10

4

/bin/cat

10

101

/bin/cat

10

102

/bin/true

10

103

/bin/sleep

60

10

Таблица 4. Конфигурация второго узла кластера

Идентификатор процесса в системе

Путь к процессу

Аргументы командной строки

Зависимости от других процессов

Начальный приоритет

5

/bin/cat

2, 7

10

6

/bin/cat

18, 8

10

7

/bin/cat

-u

8

10

201

/bin/cat

10

202

/bin/true

10

203

/bin/true

10

204

/bin/ls

-l /home/cluster/node_2

10

205

sleep

120

10

Таблица 5. Конфигурация третьего узла кластера

Идентификатор процесса в системе

Путь к процессу

Аргументы командной строки

Зависимости от других процессов

Начальный приоритет

8

/bin/cat

17, 18

20

9

/bin/cat

1

20

10

/bin/cat

17, 13

20

13

/bin/cat

17

20

17

/bin/cat

10

18

/bin/cat

26

10

20

/bin/cat

-u

10

21

/bin/cat

18

10

22

/bin/cat

21

10

23

/bin/cat

22

10

24

/bin/cat

23

10

25

/bin/cat

24

10

28

/bin/cat

10

31

/bin/cat

35, 32, 33

10

32

/bin/cat

35, 33

10

33

/bin/cat

10

35

/bin/cat

10

301

/bin/cat

10

302

/bin/ls

-l /home/cluster/node_3

10

303

/bin/sleep

600

10

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

Рисунок 20. Графический интерфейс пользователя в режиме мониторинга состояния кластера

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

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

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

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

Рисунок 21. Окно режима мониторинга узлов

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

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

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

Заключение

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

- Разработан блок создания, применения, изменения и сохранения различных конфигурация кластера;

- Разработан блок менеджера проектов, позволяющего производить удобную навигацию между сохраненными конфигурациями с возможность вывода их описания;

- Разработан блок мониторинга узлов кластера и графического отображения их состояния на экране удаленного терминала;

- Разработан блок взаимодействия со сторонним программным обеспечением, собирающим статистику работы узлов и данные для резервирования;

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

- Разработан программный модуль диспетчера высокой готовности для ОСРВ QNX 4.25;

- Проведена отладка и тестирование разработанного программного продукта.

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

Список литературы

1. Алексеев Д. - Практика работы с QNX.- М.: Издательский дом «КомБук», 2004.

2. Зыль С.Н. - QNX: Основы применения. - СПб.: БХВ-Петербург, 2005.

3. Робачевский А.М. - Операционная система UNIX. - СПб.: БХВ-Петербург, 2002.

4. Кондукова Е. - Операционная система реального времени QNX. Системная архитектура. - СПб.: БХВ-Петербург, 2006.

5. Зыль С.Н. - Операционная система реального времени QNX: от теории к практике. - СПб.: БХВ-Петербург, 2004.

6. К.А. Иыуду, С.А. Кривощеков, Математические модели отказоустойчивых ВС. -М., МАИ, 1989.

7. Л.П. Глазунов и др. Основы теории надежности автоматических систем управления. -М.,Энергоатомиздат, 1984.

8. К.Ю. Богачев. Операционные системы реального времени. М. 2001.

9. Зыль С. Н. Проектирование, разработка и анализ программного обеспечения систем реального времени

Приложение

//communication.cpp

//Dmitry Saraev

//ARGON, 2012

#include "communication.h"

Communication::Communication(WCValSList <int> listOfNodes)

{

int regState;

nodeList = listOfNodes;

nodeNamePrefix = "/ARGON_CLUSTER_NODE_";

activeNodeName = "/ARGON_CLUSTER_NODE_MAIN";

regState = registerMyNodeName();

if(regState == -1)

{

cerr << "Error! Cant attach name: "

<< nodeNamePrefix << getnid() << endl;

}

}

int Communication::registerMyNodeName()

{

return qnx_name_attach(0, nodeNamePrefix + String(getnid()));

}

void Communication::registerMyNodeAsMainNode()

{

mainNodeNameId = qnx_name_attach(0, nodeNamePrefix + "MAIN");

}

void Communication::unregisterMyNodeAsMainNode()

{

qnx_name_detach(0, mainNodeNameId);

}

int Communication::nextNode(int nodeNum)

{

int nodeIndex;

int totalNodes = nodeList.entries();

if(totalNodes == 1)

{

return 0;

}

nodeIndex = nodeList.index(nodeNum);

assert(nodeIndex != -1);

if((nodeIndex + 1) < totalNodes)

{

cout << "COMMUNICATION.CPP:if next node = " << nodeList.find(nodeIndex + 1) << endl;

return nodeList.find(nodeIndex + 1);

}

else

{

cout << "COMMUNICATION.CPP:else next node = " << nodeList.find(0) << endl;

return nodeList.find(0);

}

}

int Communication::sendMessageToNextNode(message_struct *message)

{

int sendStatus = -1;

int receiverNode = getnid();

do

{

receiverNode = nextNode(receiverNode);

if((receiverNode == getnid()) || (receiverNode == 0))

{

return MESSAGE_CANT_SEND;

}

pid_t receiver = qnx_name_locate(0,

nodeNamePrefix + String(receiverNode), sizeof(message_struct), NULL);

if(receiver != -1)

{ резервирование вычислитель кластер интерфейс

sendStatus = Send(receiver, message, message,

sizeof(message_struct), sizeof(message_struct));

qnx_vc_detach(receiver);

}

} while(sendStatus != 0);

return MESSAGE_SEND;

}

pid_t Communication::getMessage(message_struct *message)

{

pid_t sender;

sender = Creceive(0, message, sizeof(message_struct));

if(sender == -1)

{

return NO_NEW_MESSAGES;

}

return sender;

}

int Communication::sendReplyMessage(message_struct *message, pid_t sender)

{

int replyState = Reply(sender, message, sizeof(message_struct));

return replyState;

}

//communication.h

//Dmitry Saraev

//ARGON, 2012

#ifndef COMMUNICATION_H

#define COMMUNICATION_H

#include "message_types.h"

#include "parse_config.h"

#include <sys/types>

#include <sys/name.h>

#include <sys/kernel.h>

#include <sys/vc.h>

#include <unistd.h>

#include <assert.h>

//info about state of nodes

#define NODE_STATE_ACTIVE 1

#define NODE_STATE_PASSIVE 0

#define NODE_STATE_UNAVALIBLE 2

//info about state of send message

#define MESSAGE_CANT_SEND 0

#define MESSAGE_SEND 1

//info about state of send reply to message

#define REPLY_CANT_SEND -1

#define REPLY_SEND 0

//info about avalible nodes

#define NODE_AVALIBLE 1

#define NODE_UNAVALIBLE 0

#define NO_NEW_MESSAGES 0

class Communication

{

public:

Communication(WCValSList <int> listOfNodes);

int sendMessageToNextNode(message_struct *message);

pid_t getMessage(message_struct *message);

int sendReplyMessage(message_struct *message, pid_t sender);

void registerMyNodeAsMainNode();

void unregisterMyNodeAsMainNode();

private:

String nodeNamePrefix;

String activeNodeName;

int registerMyNodeName();

int mainNodeNameId;

WCValSList <int> nodeList;

int nextNode(int nodeNum);

};

#endif

//proc_watch.cpp

//Dmitry Saraev

//ARGON, 2012

#include "proc_watch.h"

LogEvents * log;

SysProc::operator==(const SysProc &proc2) const

{

return (*procInfo == *proc2.procInfo);

}

SysProc::SysProc(ProcInfo *proc)

{

procInfo = proc;

pid = -1;

vid = -1;

}

SysProc::startOn(nid_t node)

{

pid_t procId;

if((realStartNode == node) && (isRun()))

{

state = PROC_RUN;

return PROC_START_OK;

}

//change qnx_spawn_options

qnx_spawn_options.node = node;

qnx_spawn_options.priority = procInfo->prio;

log->startEvent("START-PROC :tag " + toString(procInfo->tag) + " :onNode " + toString(node));

if(procInfo->options == "")

{

procId = spawnl(P_NOWAIT, procInfo->filename,

procInfo->filename, NULL);

}

else

{

char** options = stringToOptionList(

procInfo->filename + " " + procInfo->options);

procId = spawnv(P_NOWAIT, procInfo->filename,

(char const * const *)options);

}

//restore qnx_spawn_options

qnx_spawn_options.node = 0L;

qnx_spawn_options.priority = -1;

if(procId == -1)

{

state = PROC_NOT_RUN;

log->endEvent("ERROR");

return PROC_START_ERROR;

}

realStartNode = node;

vid = procId;

if(node == getnid())

{

pid = vid;

}

else

{

_psinfo data;

qnx_psinfo(0, vid, &data, 0, NULL);

pid = data.un.vproc.remote_pid;

}

qnx_vc_detach(vid);

state = PROC_RUN;

log->endEvent("OK :pid " + toString(pid));

return PROC_START_OK;

}

int SysProc::isRunLocalCheck()

{

if(pid == -1)

{

state = PROC_NOT_RUN;

return PROC_NOT_RUN;

}

_psinfo data;

if(qnx_psinfo(0, pid, &data, 0, NULL) == -1)

{

state = PROC_NOT_RUN;

return PROC_NOT_RUN;

}

else if(data.pid != vid)

{

state = PROC_NOT_RUN;

return PROC_NOT_RUN;

}

else if(data.state == STATE_DEAD)

{

state = PROC_NOT_RUN;

return PROC_NOT_RUN;

}

else

{

state = PROC_RUN;

return PROC_RUN;

}

}

int SysProc::isRunGlobalCheck()

{

if(pid == -1)

{

state = PROC_NOT_RUN;

return PROC_NOT_RUN;

}

waitpid(vid, NULL, WNOHANG);

int oldVid = vid;

vid = qnx_vc_attach(realStartNode, pid, 1000, 0);

if(vid == -1)

{

state = PROC_NOT_RUN;

qnx_vc_detach(oldVid);

return PROC_NOT_RUN;

}

_psinfo data;

if(qnx_psinfo(0, vid, &data, 0, NULL) == -1)

{

state = PROC_NOT_RUN;

qnx_vc_detach(vid);

return PROC_NOT_RUN;

}

else if(data.pid != vid)

{

state = PROC_NOT_RUN;

qnx_vc_detach(vid);

return PROC_NOT_RUN;

}

else if(data.state == STATE_DEAD)

{

state = PROC_NOT_RUN;

qnx_vc_detach(vid);

return PROC_NOT_RUN;

}

else

{

state = PROC_RUN;

qnx_vc_detach(vid);

return PROC_RUN;

}

}

int SysProc::isRun()

log->startEvent("IS-PROC-RUN :tag " + toString(procInfo->tag));

if(realStartNode == getnid())

{

isRunLocalCheck();

}

else

{

isRunGlobalCheck();

}

if(state == PROC_RUN)

{

log->endEvent("RUN");

}

else

{

log->endEvent("NOT-RUN");

}

return state;

}

int SysProc::stop()

{

log->startEvent("STOP-PROC :tag " + toString(procInfo->tag) + " :node "

+ toString(realStartNode) + " :pid " + toString(pid));

if(isRun() == PROC_NOT_RUN)

{

log->endEvent("OK");

return PROC_STOPPED;

}

sendSignalToMe(SIGTERM);

if(isRun() == PROC_NOT_RUN)

{

log->endEvent("OK");

return PROC_STOPPED;

}

sendSignalToMe(SIGKILL);

if(isRun() == PROC_NOT_RUN)

{

log->endEvent("OK");

return PROC_STOPPED;

}

log->endEvent("ERROR");

return PROC_CANT_STOPPED;

}

void SysProc::sendSignalToMe(int signalNumber)

{

String killCommand;

char strNode[3];

char strPid[10];

char strSignal[3];

itoa(realStartNode, strNode, 10);

itoa(pid, strPid, 10);

itoa(signalNumber, strSignal, 10);

killCommand = "on -n " + String(strNode) + " kill -" +

String(strSignal) + " " + String(strPid);

system(killCommand);

}

char ** SysProc::stringToOptionList(String s)

{

WCPtrSList <String> list;

String sep = " ";

String sepOpen = "\"";

String sepClose = "\"";

int done = 0;

int beginPos = 0;

int endPos = 0;

while(!done)

{

String * tmpStr = new(String);

if(s[beginPos] == sepOpen)

{

++beginPos;

endPos = s.index(sepClose, beginPos);

*tmpStr = String(s, beginPos, endPos - beginPos);

if(s.length() == endPos + 1)

{

done = 1;

}

++endPos;

}

else

{

endPos = s.index(sep, beginPos);

if(endPos == -1)

{

endPos = s.length();

done = 1;

}

*tmpStr = String(s, beginPos, endPos - beginPos);

}

list.append(tmpStr);

beginPos = endPos + 1;

}

//create option list

char** opList = (char**)malloc(sizeof(char*) * (list.entries() + 1));

//convert from strings to char* []

int opNum = list.entries();

int opCounter = 0;

while(opCounter < opNum)

{

String strOpt = *list.get();

char* option = (char*)malloc(sizeof(char) * (strOpt.length() + 1));

strcpy(option, strOpt);

opList[opCounter] = option;

++opCounter;

}

opList[opCounter] = NULL;

list.clearAndDestroy();

return opList;

}

ProcWatch::ProcWatch(WCPtrSList <NodeInfo> nodes, WCPtrSList <ProcInfo> procs)

{

nodeNamePrefix = NODE_NAME_PREFIX;

int nodeNum = nodes.entries();

int nodeCount = 0;

WCPtrSList <RealNodeInfo> realNodesInfo;

while(nodeCount < nodeNum)

NodeInfo * node = nodes.find(nodeCount);

realNodes.append(node->node);

RealNodeInfo * realNodeInfo = new RealNodeInfo(node->node, NS_PASSIVE);

realNodesInfo.append(realNodeInfo);

cout << "debug: add node " << node->node << " to realNodesInfo" << endl;

++nodeCount;

}

nodesInfo = new NodesInfo(realNodesInfo);

}

int ProcWatch::myState()

{

return nodesInfo->realNodeState(getnid());

}

void ProcWatch::startMonitoring()

{

clusterState = new ClusterState();

int selectionTimeout = getnid() * 5;

registerMyNodeName();

delay(5000);

int noNodesTime;

while(1)

{

delay(MESSAGE_TIMEOUT);

++clusterState->cycle;

log->startEvent("MONITORING :cycle " + toString(clusterState->cycle));

answerToAllMessages();

if(myState() == NS_PASSIVE)

{

if(clusterState->cycleOfLastMessage < clusterState->cycle - (getnid() * 5))

{

nodesInfo->reset();

if(startSelection() == MESSAGE_CANT_SEND)

{

log->startEvent("SET-MY-NODE-AS-MAIN");

setMyState(NS_ACTIVE);

log->endEvent("OK");

}

}

}

if(myState() == NS_ACTIVE)

{

if(sendMsgClusterState() == MESSAGE_CANT_SEND) //TODO this function

{

int myOldState = myState();

nodesInfo->reset();

if(myOldState != myState())

{

RealNodeInfo * myNode = nodesInfo->getNode(getnid());

myNode->status = myOldState;

}

}

}

log->endEvent("OK");

}

}

int ProcWatch::sendMsgClusterState()

{

message_struct message;

message.magic_number = ARGON_MAGIC_NUMBER;

message.type = MT_CLUSTER_CHANGES;

message.sender = getnid();

message.message_body.changes_in_cluster.cluster_state_rev = clusterState->currentRev;

message.message_body.changes_in_cluster.node_count = realNodes.entries();

int nodesTotal = realNodes.entries();

int nodesCount = 0;

while(nodesCount < nodesTotal)

{

int currentNode = realNodes.find(nodesCount);

assert(currentNode != -1);

if(currentNode == getnid())

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = getnid();

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_ACTIVE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(getnid());

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

else

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = currentNode;

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_UNAVAILIBLE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(currentNode);

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

++nodesCount;

}

return sendMessageToNextNode(&message);

}

int ProcWatch::updateNodesList()

{

cout << "(SEND-MESSAGE LIST_OF_NODES)" << endl;

message_struct message;

message.magic_number = ARGON_MAGIC_NUMBER;

message.type = MT_LIST_OF_NODES;

message.sender = getnid();

message.message_body.node_list.node_count = 1;

message.message_body.node_list.nodes[0].node_number = getnid();

message.message_body.node_list.nodes[0].node_status = myState();

message.message_body.node_list.nodes[0].node_weight = nodesInfo->getWidthOnNode(getnid());

return sendMessageToNextNode(&message);

}

int ProcWatch::startSelection()

{

cout << "(SEND-MESSAGE SELECTION)" << endl;

message_struct message;

message.magic_number = ARGON_MAGIC_NUMBER;

message.type = MT_SELECTION;

message.sender = getnid();

message.message_body.changes_in_cluster.cluster_state_rev = 0;

message.message_body.changes_in_cluster.node_count = realNodes.entries();

int nodesTotal = realNodes.entries();

int nodesCount = 0;

while(nodesCount < nodesTotal)

{

int currentNode = realNodes.find(nodesCount);

assert(currentNode != -1);

if(currentNode == getnid())

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = getnid();

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_ACTIVE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(getnid());

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

else

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = currentNode;

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_UNAVAILIBLE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(currentNode);

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

++nodesCount;

}

return sendMessageToNextNode(&message);

}

void ProcWatch::setMyState(int nodeState)

{

if(myState() == nodeState)

{

return;

}

else if(myState() == NS_ACTIVE)

{

unregisterMyNodeAsMainNode();

}

else if(myState() == NS_PASSIVE)

{

registerMyNodeAsMainNode();

}

RealNodeInfo * myNode = nodesInfo->getNode(getnid());

myNode->status = nodeState;

}

void ProcWatch::setNodeState(int nodeNum, int nodeState)

{

RealNodeInfo * node = nodesInfo->getNode(nodeNum);

node->status = nodeState;

}

int ProcWatch::answerMessage(message_struct * message, message_struct * newMessage)

{

log->startEvent("(GET_MESSAGE)");

int sendToNextNode;

switch(message->type)

{

case MT_SELECTION:

sendToNextNode = answerToMtSelection(message, newMessage);

break;

case MT_NEW_ACTIVE_NODE:

sendToNextNode = answerToMtNewActiveNode(message, newMessage);

break;

case MT_LIST_OF_NODES:

sendToNextNode = answerToMtListOfNodes(message, newMessage);

break;

case MT_CLUSTER_CHANGES:

sendToNextNode = answerToMtClusterChanges(message, newMessage);

break;

case MT_TOTAL_PROCS_COUNT:

sendToNextNode = answerToMtTotalProcsCount(message, newMessage);

break;

case MT_PROCS_STATUS:

sendToNextNode = answerToMtProcsStatus(message, newMessage);

break;

case MT_TOTAL_UPDATED_PROCS:

sendToNextNode = answerToMtTotalUpdatedProcs(message, newMessage);

break;

case MT_UPDATE_IN_PROCS_LIST:

sendToNextNode = answerToMtUpdateInProcsList(message, newMessage);

break;

case MT_UPDATE_IN_NODES_LIST:

sendToNextNode = answerToMtUpdateInNodesList(message, newMessage);

break;

}

log->endEvent("[OK]");

return sendToNextNode;

}

int ProcWatch::answerToMtSelection(message_struct * message, message_struct * newMessage)

{

cout << "debug: ProcWatch::answerToMtSelection" << endl;

//int answer = answerToMtUpdateInNodesList(message, newMessage);

if(getnid() != message->sender)

{

*newMessage = *message;

int nodesTotal = message->message_body.changes_in_cluster.node_count;

int nodesCounter = 0;

while(nodesCounter < nodesTotal)

{

node_changes_struct node = message->message_body.changes_in_cluster.nodes[nodesCounter];

if(node.node_number == getnid())

{

node.node_status = myState();

node.node_weight = nodesInfo->getWidthOnNode(getnid());

node.node_have_changes = NC_NONE;

newMessage->message_body.changes_in_cluster.nodes[nodesCounter] = node;

break;

}

++nodesCounter;

}

return SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

if(nodesInfo->haveActiveNode())

{

cout << "debug: active Node exist" << endl;

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

int newMainNode = nodesInfo->findMinWidthRealNode();

*newMessage = generateMtNewActiveNode(newMainNode);

cout << "active Node not exist new active node is: " << newMainNode << endl;

return SEND_MESSAGE_TO_NEXT_NODE;

}

}

}

int ProcWatch::answerToMtListOfNodes(message_struct * message, message_struct * newMessage)

{

int totalAvailibleNodes = 0;

int nodesCount = 0;

int totalNodes = realNodes.entries();

while(nodesCount < totalNodes)

{

int nodeNum = realNodes.find(nodesCount);

if(nodesInfo->isRealNodeAvailible(nodeNum))

{

RealNodeInfo * node = nodesInfo->getNode(nodeNum);

message->message_body.node_list.nodes[nodesCount].node_number = node->node;

message->message_body.node_list.nodes[nodesCount].node_status = node->status;

message->message_body.node_list.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(nodeNum);

++totalAvailibleNodes;

}

++nodesCount;

}

message->message_body.node_list.node_count = totalAvailibleNodes;

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtClusterChanges(message_struct * message, message_struct * newMessage)

{

if(getnid() == message->sender)

{

int myOldState = myState();

int nodesCount = 0;

int totalNodes = message->message_body.node_list.node_count;

while(nodesCount < totalNodes)

{

node_changes_struct node = message->message_body.changes_in_cluster.nodes[nodesCount];

RealNodeInfo * realNode = nodesInfo->getNode(node.node_number);

realNode->status = node.node_status;

realNode->haveChanges = node.node_have_changes;

++nodesCount;

}

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

*newMessage = *message;

int nodesCount = 0;

int totalNodes = newMessage->message_body.node_list.node_count;

while(nodesCount < totalNodes)

{

if(newMessage->message_body.changes_in_cluster.nodes[nodesCount].node_number == getnid())

{

newMessage->message_body.changes_in_cluster.nodes[nodesCount].node_status = myState();

newMessage->message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(getnid());

return SEND_MESSAGE_TO_NEXT_NODE;

}

++nodesCount;

}

return SEND_MESSAGE_TO_NEXT_NODE;

}

}

int ProcWatch::answerToMtNewActiveNode(message_struct * message, message_struct * newMessage)

{

if((myState() == NS_ACTIVE)

&& (getnid() != message->message_body.node_number))

{

setMyState(NS_PASSIVE);

}

else if(getnid() == message->message_body.node_number)

{

setMyState(NS_ACTIVE);

}

setNodeState(message->message_body.node_number, NS_ACTIVE);

*newMessage = *message;

if(getnid() == message->sender)

{

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

return SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtTotalProcsCount(message_struct * message, message_struct * newMessage)

{

//message->message_body.proc_count = runtimeProcs.entries();

//driver_begin

message->message_body.proc_count = 123;

//driver_end

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtProcsStatus(message_struct * message, message_struct * newMessage)

{

int procCount = 0;

int totalProcInMsg = message->message_body.procs_status.procs_count;

proc_struct proc;

while(procCount < totalProcInMsg)

{

proc = message->message_body.procs_status.procs[procCount];

++procCount;

}

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtTotalUpdatedProcs(message_struct * message, message_struct * newMessage)

{

if(message->sender == getnid())

{

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

clusterState->newRev = message->message_body.num_of_updates.cluster_state_rev;

if((clusterState->newRev == (clusterState->currentRev + 1))

|| ((clusterState->newRev != clusterState->currentRev)

&& (message->message_body.num_of_updates.update_type == UT_FULL)))

{

clusterState->remainingUpdates = message->message_body.num_of_updates.total_updates;

}

}

return SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtUpdateInProcsList(message_struct * message, message_struct * newMessage)

{

if(message->sender == getnid())

{

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

return SEND_MESSAGE_TO_NEXT_NODE;

}

int ProcWatch::answerToMtUpdateInNodesList(message_struct * message, message_struct * newMessage)

{

if(message->sender == getnid())

{

return NOT_SEND_MESSAGE_TO_NEXT_NODE;

}

else

{

int totalLogicalNodes = message->message_body.logical_nodes.total;

int logicalNodesCount = 0;

while(logicalNodesCount < totalLogicalNodes)

{

int logicalNode = message->message_body.logical_nodes.nodes[logicalNodesCount].logical_node_num;

int realNode = message->message_body.logical_nodes.nodes[logicalNodesCount].real_node_num;

nodesInfo->setRealNodeToLogicalNode(logicalNode, realNode);

++logicalNodesCount;

}

}

return SEND_MESSAGE_TO_NEXT_NODE;

}

message_struct ProcWatch::generateBaseMessage()

{

message_struct message;

message.magic_number = ARGON_MAGIC_NUMBER;

message.sender = getnid();

return message;

}

message_struct ProcWatch::generateMtSelection()

{

message_struct message = generateBaseMessage();

message.type = MT_SELECTION;

message.message_body.changes_in_cluster.cluster_state_rev = 0;

message.message_body.changes_in_cluster.node_count = realNodes.entries();

int nodesTotal = realNodes.entries();

int nodesCount = 0;

while(nodesCount < nodesTotal)

{

int currentNode = realNodes.find(nodesCount);

assert(currentNode != -1);

if(currentNode == getnid())

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = getnid();

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_ACTIVE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(getnid());

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

else

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = currentNode;

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_UNAVAILIBLE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(currentNode);

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

++nodesCount;

}

return message;

}

message_struct ProcWatch::generateMtClusterChanges()

{

message_struct message = generateBaseMessage();

message.type = MT_CLUSTER_CHANGES;

message.message_body.changes_in_cluster.cluster_state_rev = clusterState->currentRev;

message.message_body.changes_in_cluster.node_count = realNodes.entries();

int nodesTotal = realNodes.entries();

int nodesCount = 0;

while(nodesCount < nodesTotal)

{

int currentNode = realNodes.find(nodesCount);

assert(currentNode != -1);

if(currentNode == getnid())

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = getnid();

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_ACTIVE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(getnid());

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

else

{

message.message_body.changes_in_cluster.nodes[nodesCount].node_number = currentNode;

message.message_body.changes_in_cluster.nodes[nodesCount].node_status = NS_UNAVAILIBLE;

message.message_body.changes_in_cluster.nodes[nodesCount].node_weight = nodesInfo->getWidthOnNode(currentNode);

message.message_body.changes_in_cluster.nodes[nodesCount].node_have_changes = NC_NONE;

}

++nodesCount;

}

return message;

}

message_struct ProcWatch::generateMtNewActiveNode(int newActiveNode)

{

message_struct message = generateBaseMessage();

message.type = MT_NEW_ACTIVE_NODE;

message.message_body.node_number = nodesInfo->findMinWidthRealNode();

return message;

}

message_struct ProcWatch::generateMtTotalProcsCount()

{

message_struct message = generateBaseMessage();

message.type = MT_TOTAL_PROCS_COUNT;

message.message_body.proc_count = runtimeProcs.entries();

return message;

}

message_struct ProcWatch::generateMtTotalUpdatedProcs(int updateType)

{

assert((updateType == UT_FULL) || (updateType == UT_PARTIAL));

message_struct message = generateBaseMessage();

message.type = MT_TOTAL_UPDATED_PROCS;

message.message_body.num_of_updates.cluster_state_rev = clusterState->currentRev;

message.message_body.num_of_updates.update_type = updateType;

if(updateType == UT_FULL)

{

message.message_body.num_of_updates.total_updates = runtimeProcs.entries();

}

else if(updateType == UT_PARTIAL)

{

message.message_body.num_of_updates.total_updates = 0/* procsInfo->totalChangedProcs()*/;

}

return message;

}

message_struct ProcWatch::generateMtUpdateInProcsList()

{

message_struct message = generateBaseMessage();

message.type = MT_UPDATE_IN_PROCS_LIST;

message.message_body.procs_status.cluster_state_rev = clusterState->currentRev;

int procsTotal = 0;

int procsCounter = 0;

while(procsCounter < procsTotal)

{

//TODO: add info about procs

++procsCounter;

}

return message;

message_struct ProcWatch::generateMtUpdateInNodesList()

{

message_struct message = generateBaseMessage();

message.type = MT_UPDATE_IN_NODES_LIST;

int nodesTotal = realNodes.entries();

message.message_body.logical_nodes.total = nodesTotal;

int nodesCounter = 0;

while(nodesCounter < nodesTotal)

{

++nodesCounter;

}

return message;

}

int ProcWatch::messageSize(int messageType)

{

int size = 3 * sizeof(int); //magic_number + type + sender

switch(messageType)

{

case MT_SELECTION:

size += sizeof(changes_in_cluster_struct);

break;

case MT_NEW_ACTIVE_NODE:

size += sizeof(int);

break;

case MT_LIST_OF_NODES:

size += sizeof(node_list_struct);

break;

case MT_TOTAL_PROCS_COUNT:

size += sizeof(int);

break;

case MT_PROCS_STATUS:

size += sizeof(procs_status_struct);

break;

case MT_CLUSTER_CHANGES:

size += sizeof(changes_in_cluster_struct);

break;

case MT_TOTAL_UPDATED_PROCS:

size += sizeof(num_of_updates_struct);

break;

case MT_UPDATE_IN_PROCS_LIST:

size += sizeof(procs_status_struct);

break;

case MT_UPDATE_IN_NODES_LIST:

size += sizeof(logical_nodes_struct);

break;

case MT_REPLY:

size += sizeof(int);

break;

}

//return size;

return sizeof(message_struct);

}

int ProcWatch::nextNode(int nodeNum)

{

log->startEvent("ProcWatch::nextNode :forNode" + toString(nodeNum));

WCValSList <int> nodeList = realNodes;

int nodeIndex;

int totalNodes = nodeList.entries();

if(totalNodes == 1)

{

log->endEvent("Have only one node in list");

return 0;

}

nodeIndex = nodeList.index(nodeNum);

assert(nodeIndex != -1);

if((nodeIndex + 1) < totalNodes)

{

log->endEvent(toString(nodeList.find(nodeIndex + 1)));

return nodeList.find(nodeIndex + 1);

}

else

{

log->endEvent(toString(nodeList.find(0)));

return nodeList.find(0);

}

}

int ProcWatch::sendMessageToNextNode(message_struct * message)

{

log->startEvent("ProcWatch::sendMessageToNextNode");

int sendStatus = -1;

int receiverNode = getnid();

do

{

answerToAllMessages();

receiverNode = nextNode(receiverNode);

if((receiverNode == getnid()) || (receiverNode == 0))

{

log->endEvent("Cant selfsend message");

return MESSAGE_CANT_SEND;

}

pid_t receiver = qnx_name_locate(0,

nodeNamePrefix + toString(receiverNode), sizeof(message_struct), NULL);

if(receiver != -1)

{

sendStatus = Send(receiver, message, message,

messageSize(message->type), sizeof(message_struct));

qnx_vc_detach(receiver);

//node who send message now unavailible

if((sendStatus != 0) && (receiverNode == message->sender))

{

log->endEvent("message cant send to sender");

return MESSAGE_CANT_SEND;

}

}

else if(receiverNode == message->sender)

{

log->endEvent("message cant send to sender");

return MESSAGE_CANT_SEND;

}

} while(sendStatus != 0);

delay(MESSAGE_TIMEOUT);

log->endEvent("message send");

return MESSAGE_SEND;

}

int ProcWatch::registerMyNodeName()

return qnx_name_attach(0, nodeNamePrefix + toString(getnid()));

void ProcWatch::registerMyNodeAsMainNode()

mainNodeNameId = qnx_name_attach(0, nodeNamePrefix + "main");

}

void ProcWatch::unregisterMyNodeAsMainNode()

{

qnx_name_detach(0, mainNodeNameId);

}

pid_t ProcWatch::getMessage(message_struct *message)

{

pid_t sender;

sender = Creceive(0, message, sizeof(message_struct));

if(sender == -1)

{

return NO_NEW_MESSAGES;

}

return sender;

}

int ProcWatch::sendReplyMessage(message_struct *message, pid_t sender)

{

int replyState = Reply(sender, message, sizeof(message_struct));

return replyState;

}

void ProcWatch::answerToAllMessages()

{

message_struct newMsg;

message_struct incomingMsg;

pid_t sender;

while((sender = getMessage(&incomingMsg)) != NO_NEW_MESSAGES)

{

clusterState->cycleOfLastMessage = clusterState->cycle;

log->startEvent("HAVE_NEW_MSG");

int sendNextNode = answerMessage(&incomingMsg, &newMsg);

sendReplyMessage(&incomingMsg, sender);

log->endEvent("MSG_PROCESSED");

if(sendNextNode == SEND_MESSAGE_TO_NEXT_NODE)

{

sendMessageToNextNode(&newMsg);

}

}

}

LRNode::LRNode(int lNode, int nodeWidth)

{

logicalNode = lNode;

realNode = 0;

logicalNodeWidth = nodeWidth;

}

LRNode::operator==(const LRNode &node) const

{

return(logicalNode == node.logicalNode);<...


Подобные документы

  • Проектирование программного модуля: сбор исходных материалов; описание входных и выходных данных; выбор программного обеспечения. Описание типов данных и реализация интерфейса программы. Тестирование программного модуля и разработка справочной системы.

    курсовая работа [81,7 K], добавлен 18.08.2014

  • Порядок автоматизации расчетов себестоимости и длительности программного обеспечения производственного предприятия. Выбор языка программирования и системы управления базами данных. Разработка алгоритмов расчета себестоимости программного обеспечения.

    дипломная работа [1,7 M], добавлен 13.06.2017

  • Проектирование структур данных и пользовательского интерфейса. Разработка руководства системного программиста и пользователя. Основные элементы организации работы менеджера по работе с клиентами. Характеристика программного обеспечения ООО "Доминион+".

    курсовая работа [1,7 M], добавлен 14.10.2012

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

    дипломная работа [3,1 M], добавлен 19.01.2017

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

    курсовая работа [449,8 K], добавлен 14.01.2011

  • Классификация служебных программных средств. Файловая структура операционных систем. Основы графического интерфейса пользователя Windows XX. Анализ алгоритмов решения задач. Описание процесса разработки программного обеспечения и результатов работы.

    курсовая работа [2,4 M], добавлен 14.11.2016

  • Принципы автоматизации делопроизводства. Общие понятия документооборота. Проектирование программного обеспечения. Стадии и этапы создания информационных систем, средства их разработки. Анализ алгоритмов работы с базой данных, разработка интерфейса.

    дипломная работа [3,4 M], добавлен 07.11.2015

  • Характеристика объектно-ориентированного, процедурного, функционального программирования. Выбор языка программирования для создания программного обеспечения для управления справочником "Спортсмены". Алгоритм работы приложения, пользовательский интерфейс.

    курсовая работа [1,6 M], добавлен 23.02.2016

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

    курсовая работа [97,7 K], добавлен 14.12.2012

  • Функционально-модульная структура программного обеспечения контроллера домофона. Электронная схема электронного замка, модуля микрофона и динамика. Выбор комбинированного источника питания. Разработка программного модуля. Программа управления домофоном.

    курсовая работа [484,7 K], добавлен 29.03.2017

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

    курсовая работа [332,3 K], добавлен 09.12.2014

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

    дипломная работа [2,7 M], добавлен 07.07.2022

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

    курсовая работа [2,0 M], добавлен 24.06.2012

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

    дипломная работа [1,1 M], добавлен 18.07.2014

  • Реализация программного средства "Действия над матрицами". Разработка кода программного продукта на основе готовой спецификации на уровне модуля. Использование инструментальных средств на этапе отладки программного модуля. Выбор стратегии тестирования.

    отчет по практике [296,1 K], добавлен 19.04.2015

  • Разработка системы управления проектами для компании ЗАО "Диакон". Экономические параметры разработки и внедрения электронной информационной системы. Технология разработки программного обеспечения. Выбор типа графического интерфейса, его составляющие.

    дипломная работа [1,4 M], добавлен 10.06.2014

  • Структурная диаграмма программного модуля. Разработка схемы программного модуля и пользовательского интерфейса. Реализация программного модуля: код программы; описание использованных операторов и функций. Вид пользовательской формы с заполненной матрицей.

    курсовая работа [215,3 K], добавлен 01.09.2010

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

    дипломная работа [101,2 K], добавлен 17.06.2011

  • Предметная область, цель создания и группы пользователей информационно-программного изделия. Сетевая организация распределения приложения в архитектуре клиент-сервер. Интерфейс пользователя. Реализация транзакций. Защита от несанкционированного доступа.

    курсовая работа [1,8 M], добавлен 15.01.2013

  • Анализ предметной области. Средства и технологии разработки программного обеспечения. Требования к аппаратным и операционным ресурсам. Создание навигационного меню. Структура данных таблиц. Разработка интерфейса модуля. Сортировка и фильтрация данных.

    дипломная работа [3,7 M], добавлен 12.05.2018

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.