Проектирование и разработка подсистемы управления транзакциями для АСУД "ЕВФРАТ"
Механизмы управления транзакциями в СУБД. Обзор средств удаленного взаимодействия с объектами. Разработка подсистемы управления транзакциями. Практический анализ производительности подсистемы. Способы защиты пользователей от опасных и вредных факторов.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 14.03.2013 |
Размер файла | 449,9 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
{
if (OnCommit != null)
OnCommit(this, null);
_connection.Commit();
_cTrans.Commit();
//Применяем изменения к файлам транзакции
//Перед этим должны быть созданы по идее резервные копии..
foreach (TransactionFile tfile in _transactionFiles.Values)
tfile.Flush();
//добавляем задачу очистки ресурсов транзакции
_myThread.queue.Push(new WorkItem(new WorkItem.anywork(this.FreeResources)));
}
else
{
WorkItem wi = new WorkItem(new WorkItem.anywork(this.Commit));
EnqueueWorkItem(wi);
wi.AsyncWaitHandle.WaitOne();
// _completeHandle.WaitOne();
}
}
/// <summary>
/// добавляет задачу для выполнения в рамках транзакции
/// </summary>
/// <param name="wi">задача для выполнения</param>
/// <remarks>
/// Задача помещается в очередь задач потока и одновременно в очередь незавершенных задач
/// транзакции. После выполнения задачи она удаляется из очереди незавершенных задач транзакции.
///
/// При выполнении задачи в контекст устанавливается текущая транзакция
///
/// Если при выполнении задачи в транзакции возникло исключение - транзакция автоматически откатывается
/// </remarks>
/// <exception cref="InvalidOperationException">Транзакция находится в состоянии завершения и не может принимать новых задач</exception>
public void AddAction(Cognitive.Threading.WorkItem wi)
{
lock (_locker)
{
if (_rollbackFlag || _commitFlag)
throw new InvalidOperationException("Транзакция находится в состоянии завершения и не может принимать новых задач");
EnqueueWorkItem(wi);
}
}
private void Run(Cognitive.Threading.WorkItem wi)
{
lock (_locker)
{
if (_myThread.State == WorkingThreadStates.Stopping)
{ //Фиктивное завершение
(wi.AsyncWaitHandle as System.Threading.ManualResetEvent).Set();
return;
}
wi.WorkException += new WorkItemExceptionDelegate(wi_WorkException);
wi.WorkComplete += new WorkItemEventDelegate(wi_WorkComplete);
wi.WorkActivating += new WorkItemEventDelegate(wi_WorkActivating);
_running = wi;
_myThread.queue.Push(_running);
}
}
private void EnqueueWorkItem(Cognitive.Threading.WorkItem wi)
{
if (wi == null)
throw new NullReferenceException("wi не может быть null");
lock (_locker)
{
if (_running == null)
Run(wi); //ничего не выполняется - сразу запускаем
else
{
if (_myThread.State == WorkingThreadStates.Stopping)
{ //Фиктивное завершение
(wi.AsyncWaitHandle as System.Threading.ManualResetEvent).Set();
return;
}
_transactionQueue.Enqueue(wi); //кладем в очередь
}
}
}
class CWIAsync : IAsyncResult
{
WorkItem _wi;
bool _Complete = false;
public CWIAsync(WorkItem wi)
{
_wi = wi;
_wi.WorkComplete += new WorkItemEventDelegate(_wi_WorkComplete);
}
void _wi_WorkComplete(WorkItem source)
{
_Complete = true;
}
#region IAsyncResult Members
public object AsyncState
{
get { return null; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get {
return _wi.AsyncWaitHandle;
}
}
public bool CompletedSynchronously
{
get { return _Complete; }
}
public bool IsCompleted
{
get { return _Complete; }
}
#endregion
}
public Object Invoke(Delegate del, params object[] p)
{
WorkItem wi = null;
switch (p.Length)
{
case 0:
wi = new WorkItem(del);
break;
case 1:
wi = new WorkItem(del, p[0]);
break;
case 2:
wi = new WorkItem(del, p[0], p[1]);
break;
case 3:
wi = new WorkItem(del, p[0], p[1], p[2]);
break;
case 4:
wi = new WorkItem(del, p[0], p[1], p[2], p[3]);
break;
default:
throw new NotImplementedException();
}
Exception ex = null;
WorkItemExceptionDelegate we = (s, e) => { ex = e; };
wi.WorkException += we;
/**/
AddAction(wi);
/*EnqueueWorkItem(wi);*/
wi.AsyncWaitHandle.WaitOne();
if (ex != null)
throw new System.Reflection.TargetInvocationException(ex);
return wi.Result;
}
public IAsyncResult InvokeAsync(Delegate del, params object[] p)
{
WorkItem wi = null;
switch (p.Length)
{
case 0:
wi = new WorkItem(del);
break;
case 1:
wi = new WorkItem(del, p[0]);
break;
case 2:
wi = new WorkItem(del, p[0], p[1]);
break;
case 3:
wi = new WorkItem(del, p[0], p[1], p[2]);
break;
case 4:
wi = new WorkItem(del, p[0], p[1], p[2], p[3]);
break;
default:
throw new NotImplementedException();
}
IAsyncResult ar = new CWIAsync(wi);
/**/
AddAction(wi);
/*EnqueueWorkItem(wi);*/
return ar;
}
private Microsoft.Samples.DbConnectionScope.DbConnectionScope _dbScope;
/// <summary>
/// обрабатываемый WorkItem
/// </summary>
private WorkItem CurrentWorkItem
{
get{
lock (_locker)
{
return _running;
}
}
}
/// <summary>
/// попытка войти в режим блокировки
/// </summary>
/// <param name="lockId">идентификатор блокировки</param>
/// <returns></returns>
public bool TryEnterLock(String lockId)
{
if (!this.Equals(Transaction.Current))
throw new InvalidOperationException("TryEnterLock может быть вызван только из потока транзакции");
if (Transaction.Current._server.blockMan.TryEnterBlock(lockId))
return true;
return false;
}
public bool IsInLock(String lockId)
{
return _server.blockMan.IsInLock(this, lockId);
}
/// <summary>
/// вход в режим блокировки с ожиданием
/// </summary>
/// <param name="lockId">идентификатор блокировки</param>
public void EnterLock(String lockId)
{
if (Transaction.Current != null)
throw new InvalidOperationException("Для внесения блокировки заданием следует использовать TryEnterLock вместо EnterLock");
AddAction(new CLockWorkItem(this, lockId));
}
/// <summary>
/// При выполнении задачи в контекст ее потока устанавливается текущая транзакция
/// </summary>
/// <param name="source"></param>
void wi_WorkActivating(WorkItem source)
{
lock (_locker)
{
if (!_myThread.Context.ContainsKey("Transaction"))
_myThread.Context.Add("Transaction", this);
}
///Устанавливаем текущую транзакцию
System.Transactions.Transaction.Current = _cTrans;
_dbScope = new Microsoft.Samples.DbConnectionScope.DbConnectionScope();
_dbScope.AddConnection(_sqlConn.ConnectionString, _sqlConn);
}
/// <summary>
/// Выполнение задачи завершилось и она удаляется из очереди незавершенных задач транзакции
/// </summary>
/// <param name="source"></param>
void wi_WorkComplete(WorkItem source)
{
lock (_locker)
{
WorkItem wi = _running;
//закрываем открытый scope соединения
if (_dbScope != null)
{
_dbScope.AddConnection(_sqlConn.ConnectionString, new SqlConnection());
_dbScope.Dispose();
_dbScope = null;
}
_MyIdleStart = DateTime.Now;
_running = null;
if (source is CLockWorkItem)
{
if (true != (bool)source.Result)
{
Run(((CLockWorkItem)source).Copy());
return;
}
}
///вытаскиваем следующий элемент из очереди
if (_transactionQueue.Count > 0)
Run(_transactionQueue.Dequeue());
}
}
private Exception _lastException;
/// <summary>
/// Откат, если при выполнении задачи в транзакции возникло исключение
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
void wi_WorkException(WorkItem source, Exception e)
{
Trace.WriteLine("исключение в транзакции " + this._MyIndex.ToString());
lock(_locker)
{
//Исключение не в коммите и не в роллбэке
if (!_commitFlag && !_rollbackFlag && _lastException == null)
_lastException = e;
_commitFlag = false; //Нельзя коммитить то, что ошиблось
if (_rollbackFlag)
throw e; //падение при роллбэке обработать не можем
}
//Вызов происходит из рабочего потока, в его очередь ставится откат и, затем, освобождение
//ресурсов, которые сразу и выполняются
Rollback();
if (_lastException != null)
return;
//После этого можно кинуть исключение
throw e;
}
/// <summary>
/// создание файла в транзакции
/// </summary>
public TransactionFile CreateFile(string name)
{
TransactionFile tf = new TransactionFile(name);
lock (_locker)
{
_transactionFiles.Add(tf.id, tf);
}
return tf;
}
/// <summary>
/// возвращает созданный файл по его идентификатору
/// </summary>
public TransactionFile GetFile(string fileid)
{
lock (_locker)
{
if (_transactionFiles.ContainsKey(fileid))
return _transactionFiles[fileid];
return null;
}
}
/// <summary>
/// возврашает текущую транзакцию
/// </summary>
/// <remarks>
/// возвращает текущую транзакцию из контекста выполнения
/// </remarks>
public static Transaction Current
{
get
{
try
{
if (WorkingThread.Current == null)
return null;
return WorkingThread.Current.Context["Transaction"] as Transaction;
}
catch(NullReferenceException )
{
return null;
}
catch(KeyNotFoundException )
{
return null;
}
}
}
#region IDFObjectsProvider Members
/// <summary>
/// выполняет конструирование объектов по идентификатору в контексте транзакции
/// </summary>
/// <param name="id">полный идентификатор объекта</param>
/// <returns>созданный объект</returns>
/// <remarks>
/// Этот метод выполняет конструирование и кэширование ранее запрошенных объектов в рамках транзакции
/// При завершении транзакции выполняется полная очистка кэша
/// </remarks>
public Environment.IDFObject CreateObject(string id)
{
Environment.IDFContainerObject root = _server.CreateRootObject(this._connection);
if (String.IsNullOrEmpty(id))
return root;
///разбор пути, конструирование и кэширование объектов
String[] ObjectKeys = id.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
Environment.IDFContainerObject tempContObj = root;
Environment.IDFObject tempObj = null;
foreach (String CurrentKey in ObjectKeys)
{
tempObj = tempContObj.GetChild(CurrentKey);
if (!(tempObj is Environment.IDFContainerObject))
return tempObj;
tempContObj = (tempObj as Environment.IDFContainerObject);
}
return tempObj;
}
#endregion
/// <summary>
/// возвращает соединение, связанное с транзакцией
/// </summary>
public CTNKDESMLib.ICTDEDatabase Connection
{
get{
return _connection;
}
}
/// <summary>
/// возвращает объект для управления взаимодействией в рамках транзакции
/// </summary>
public Interaction.Interaction Interaction
{
get
{
return new Interaction.Interaction(_connection);
}
}
/// <summary>
/// добавление объекта в конекст транзакции
/// </summary>
/// <param name="key"></param>
/// <param name="p"></param>
public void AddContextObject(String key, Object p)
{
lock (_locker)
{
if (_ctx.ContainsKey(key))
_ctx[key] = p;
else
_ctx.Add(key, p);
}
}
/// <summary>
/// получение объекта из контекста транзакции
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Object GetContextObject(String key)
{
lock (_locker)
{
if (_ctx.ContainsKey(key))
return _ctx[key];
else return null;
}
}
}
/// <summary>
/// контекст транзакции
/// </summary>
public class TransactionContext : System.Collections.Generic.Dictionary<string, Object>
{
}
internal class CLockWorkItem : WorkItem
{
private delegate bool TryEnterLockDelegate(String x);
private String _LockId;
private Transaction _Trans;
public CLockWorkItem(Transaction tr, String lockId)
:base(new TryEnterLockDelegate(tr.TryEnterLock), lockId)
{
_Trans = tr;
_LockId = lockId;
}
internal WorkItem Copy()
{
return new CLockWorkItem(_Trans, _LockId);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Cognitive.Docflow.Transactions
{
/// <summary>
/// Класс, описывающий файл, созданный в рамках транзакции
/// </summary>
public class TransactionFile : IDisposable
{
private String _id;
private FileStream _fs;
private Transaction _transaction;
private String _externalFullPath;
private String _internalFullPath;
private FileAccess _access;
/// <summary>
/// Копирует файл во временную директорию и работает с ним до завершения транзакции
/// </summary>
/// <param name="path">Полное имя файла (не пустое, если файл не существует, он будет создан после коммита)</param>
internal TransactionFile(string path)
{
if (String.IsNullOrEmpty(path))
throw new ArgumentException("Невозможно создать TransactionFile: полное имя файла не должно быть пустым.");
if (!Directory.Exists(Path.GetDirectoryName(path)))
throw new ArgumentException(String.Format("Невозможно создать TransactionFile {0}: его путь не существует!", path));
_transaction = Transaction.Current;
_internalFullPath = Path.GetTempFileName();
if (File.Exists(path))
File.Copy(path, _internalFullPath, true);
_externalFullPath = path;
_id = _externalFullPath + "||" + Guid.NewGuid().ToString();
_access = FileAccess.Read;
}
/// <summary>
/// Чистка
/// </summary>
~TransactionFile()
{
Dispose();
}
/// <summary>
/// Чистка
/// </summary>
public void Dispose()
{
if (_fs != null)
_fs.Dispose();
if (File.Exists(_internalFullPath))
File.Delete(_internalFullPath);
}
/// <summary>
/// идентификатор файла
/// </summary>
public String id {
get
{ return _id; }
}
/// <summary>
/// транзакция, к которой относится данный файл
/// </summary>
public Transaction transaction
{
get
{
return _transaction;
}
}
/// <summary>
/// возвращает поток для доступа к содержимому файла
/// </summary>
/// <param name="access"></param>
/// <returns></returns>
public FileStream GetStream(FileAccess access)
{
if (_fs == null || !(_fs.CanRead || _fs.CanWrite) || access != _access)
{
if (_fs != null)
_fs.Close();
_access = access;
if (!File.Exists(_internalFullPath) && File.Exists(_externalFullPath))
File.Copy(_externalFullPath, _internalFullPath);
_fs = File.Open(_internalFullPath, FileMode.OpenOrCreate, _access);
}
return _fs;
}
/// <summary>
/// закрывает открытый поток и сбрасываем содержимое на диск
/// (применяет к файлу все изменения)
/// </summary>
public void Flush()
{
///если производилась работа с потоком, то производим сброс изменений на диск
if (_fs != null)
_fs.Close();
if (!File.Exists(_internalFullPath))
return;
if (!Directory.Exists(Path.GetDirectoryName(_externalFullPath)))
throw new InvalidOperationException(String.Format("Невозможно записать содержимое TransactionFile на диск в файл {0}, т.к. пути его размещения не существует!!", _externalFullPath));
File.Copy(_internalFullPath, _externalFullPath, true);
File.Delete(_internalFullPath);
}
/// <summary>
/// возвращает полный путь к файлу
/// </summary>
public String FullPath { get { return _externalFullPath; } }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cognitive.Docflow;
namespace Cognitive.Docflow.Environment
{
/// <summary>
/// серверная среда выполнения
/// </summary>
public abstract class EnvironmentServer
{
Transactions.ConnectionPool _cpool = null;
Cognitive.Threading.ThreadPool _tpool = null;
private BlockManager _blockManager = null;
private object _locker = new object();
private bool _stopping = false;
/// <summary>
/// конструктор серверной среды выполнения
/// </summary>
/// <param name="sqlConnectionString"></param>
protected EnvironmentServer(String sqlConnectionString)
{
//конструируем пул соединений
_cpool = new Transactions.ConnectionPool(sqlConnectionString, String.Empty, String.Empty);
//конструируем пул потоков
_tpool = new Cognitive.Threading.ThreadPool(4, TimeSpan.FromSeconds(1));
_blockManager = new BlockManager();
_tpool.OnIdle += new Cognitive.Threading.ThreadPoolEvent(ThreadPooll_OnIdle);
}
/// <summary>
/// конструктор серверной среды выполнения
/// </summary>
/// <param name="sqlConnectionString"></param>
/// <param name="threadsCount"></param>
protected EnvironmentServer(String sqlConnectionString, int threadsCount)
{
//конструируем пул соединений
_cpool = new Transactions.ConnectionPool(sqlConnectionString, String.Empty, String.Empty);
//конструируем пул потоков
_tpool = new Cognitive.Threading.ThreadPool(threadsCount, TimeSpan.FromMinutes(5));
_blockManager = new BlockManager();
_tpool.OnIdle += new Cognitive.Threading.ThreadPoolEvent(ThreadPooll_OnIdle);
}
internal BlockManager blockMan {
get { return _blockManager; }
}
private static Func<bool> _IdleProc
= new Func<bool>(() =>
{
if (Transactions.Transaction.Current.TryEnterLock("IDLE"))
return Transactions.Transaction.Current.Interaction.Idle();
return false;
});
private static Func<EnvironmentServer, Delegate, int> _TransactionCall =
new Func<EnvironmentServer, Delegate, int>((server, d) =>
{
Transactions.Transaction tr = server.OpenTransaction();
tr.Invoke(d);
tr.Commit();
return 0;
}
);
/// <summary>
/// запуск выполнения фоновых задач в рамках отдельной транзакции
/// </summary>
/// <param name="source"></param>
void ThreadPooll_OnIdle(Cognitive.Threading.ThreadPool source)
{
lock (_openTransactions)
{
if (_stopping)
return;
}
_TransactionCall.BeginInvoke(this, _IdleProc, null, null);
lock (_openTransactions)
{
foreach (Transactions.Transaction trans in _openTransactions)
{//Поиск транзакций слишком долго простаивающих и их откат, если они уже не откатываются и не накатываются
if (trans.MyIdleInterval > TimeSpan.FromMinutes(5)) //тайм-аут транзакции 5 минут
trans.Rollback();
}
}
}
/// <summary>
/// запуск рабочих потоков среды выполнения
/// </summary>
virtual public void Run()
{
}
/// <summary>
/// остановка рабочих потоков среды выполнения
/// </summary>
virtual public void Stop()
{
if (Threading.WorkingThread.Current != null)
throw new InvalidOperationException("Остановка сервера не может быть вызвана из рабочего потока");
lock (_openTransactions)
{
_stopping = true;
}
///проверяет есть ли еще открытые транзакции
Func<bool> HasOpenTrans = new Func<bool>(() =>
{
lock(_openTransactions)
{
return _openTransactions.Count > 0;
}
});
///возвращает последнюю открытую транзакцию
Func<Transactions.Transaction> CurrentTrans =
new Func<Transactions.Transaction>(() =>
{
lock (_openTransactions)
{
if (_openTransactions.Count > 0)
return _openTransactions[_openTransactions.Count - 1];
}
return null;
});
DateTime dtWaitFor = DateTime.Now + TimeSpan.FromMinutes(1);
while (HasOpenTrans() && (DateTime.Now < dtWaitFor))
System.Threading.Thread.Sleep(50);
///пока есть открытые транзакции - завершаем их
while (HasOpenTrans())
{
Transactions.Transaction curTrans = CurrentTrans();
if (curTrans == null)
continue;
curTrans.Rollback();
curTrans.CompleteHandle.WaitOne();
}
_tpool.Stop();
}
private List<Transactions.Transaction> _openTransactions =
new List<Cognitive.Docflow.Transactions.Transaction>();
/// <summary>
/// открытие транзакции
/// </summary>
/// <returns>созданный и проинициализированный объект транзакции</returns>
/// <remarks>
/// Создает транзакцию и связывает её с рабочим потоком.
/// Все открытае транзакции запоминаются.
/// В случае принудительной остановки сервера происходит откат всех незавершенных транзакций
/// </remarks>
virtual public Transactions.Transaction OpenTransaction()
{
Transactions.Transaction tr = Transactions.Transaction.CreateInstance(this, _cpool, _tpool);
lock (_openTransactions)
{
if (_stopping)
throw new InvalidOperationException("Нельзя создавать транзакции когда сервер находится в состоянии завершения");
_openTransactions.Add(tr);
}
tr.Complete += new Cognitive.Docflow.Transactions.TransactionEventHandler(tr_Complete);
return tr;
}
void tr_Complete(Cognitive.Docflow.Transactions.Transaction sender, EventArgs e)
{
lock (_openTransactions)
{
_openTransactions.Remove(sender);
}
}
public abstract IProtocolWriter GetProtocol(ActionPriority priority);
/// <summary>
/// конструирует корневой объект бизнес-логики
/// </summary>
/// <param name="datasource">соединение со средой хранения</param>
/// <returns></returns>
public abstract Environment.IDFContainerObject CreateRootObject(CTNKDESMLib.ICTDEDatabase datasource);
}
}
Размещено на Allbest.ru
Подобные документы
Анализ технических средств, разработка структуры подсистемы. Создание программного приложения в среде InduSoft Web Studio. Информационный расчет аналогового ввода сигналов. Адресация каналов модулей. Экспериментальная проверка подсистемы в составе стенда.
дипломная работа [1,7 M], добавлен 16.05.2017Анализ функциональной структуры и обеспечивающей части АСУ. Проектирование функциональной структуры подсистемы управления проблемами, разработка модели в среде CPN Tools и алгоритма работы. Описание программного и технического обеспечения проекта.
дипломная работа [5,6 M], добавлен 26.06.2011Декомпозиция автоматической системы управления на подсистемы и комплексы задач. Программное обеспечение комплекса задач подсистемы управления закупкой оборудования. Анализ существующей локальной вычислительной сети. Выбор дополнительных сетевых сервисов.
дипломная работа [4,0 M], добавлен 06.03.2013Управление предприятием ООО "Автотрансобслуживание", цели его деятельности. Концептуальный план создания автоматической системы управления (АСУ). Проектирование подсистемы производственно-диспетчерской службы, выбор системы управления базой данных.
дипломная работа [2,6 M], добавлен 28.06.2011Варианты использования информационной подсистемы "InventoryManagement". Основные проблемные ситуации, возникающие при функционировании, методы и средства для их решения. Информационное и программное обеспечение подсистемы. Разработка базы данных.
дипломная работа [6,7 M], добавлен 29.06.2011Анализ функциональной структуры автоматизированной системы управления. Обоснование необходимости создания подсистемы учета материальных средств, проектирование информационной базы данных. Расчет себестоимости разработки внедряемого программного продукта.
дипломная работа [5,4 M], добавлен 26.06.2011Диагностический анализ системы управления предприятия, его организационной и функциональной структуры. Разработка проекта подсистемы учёта средств вычислительной техники, описание технического обеспечения базы данных. Характеристика программного продукта.
дипломная работа [7,2 M], добавлен 28.06.2011Разработка функциональной модели подсистемы "Правительственная информационно-аналитическая система чрезвычайных ситуаций" на языке СУБД; проект базы данных при помощи современных CASE-средств. Отладка продукта, его тестирование; подсистема напоминания.
дипломная работа [2,8 M], добавлен 03.12.2011Реализация подсистемы управления файлами, использующей в качестве способа физической организации файла связанный список блоков. Разработка общей структуры модуля. Описание реализуемых в программе алгоритмов. Ввод в действие программного комплекса.
курсовая работа [666,0 K], добавлен 10.07.2015Транзакции как одно из свойств, отличающих базу данных от файловой системы. Операторы управления транзакциями в Оracle, пример неделимости. Работа с журналами повторного выполнения (активные и архивные журналы). Преимущества данной СУБД при работе.
презентация [618,1 K], добавлен 14.02.2014