变长并发日志文件的设计及实现报告.docx_第1页
变长并发日志文件的设计及实现报告.docx_第2页
变长并发日志文件的设计及实现报告.docx_第3页
变长并发日志文件的设计及实现报告.docx_第4页
变长并发日志文件的设计及实现报告.docx_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

20140316变长并发日志文件的设计及实现目录程序员简介2设计要求2系统组成2主要功能2结构设计与分析2文件结构设计2数据类型设计3写入数据设计3文件锁的设计3写入数据设计4读出数据设计5时间获取转换方法5读取数据设计5运行结果截图6遇到的问题及心得8采用的技术8开发环境9程序员简介姓名:李尔楠学号:11281008班级:计科1101设计要求系统组成系统由两个文件组成,日志文件及索引文件;日志文件存放日志记录,日志记录由日志记录结构描述,及日志记录体组成;每个日志记录可包含任意条数据项,每个数据项可是任意数据类型及长度;日志记录结构描述对本记录的每个数据项进行描述。包括数据类型及长度;日志记录体根据日志记录结构描述来存放日志记录数据。索引文件存放自动增长的日志记录号,日志记录发生的日期及时间,指向日志文件中相应日志记录的文件指针。主要功能增加日志记录:生成日志记录并写入。根据本次日志记录各数据项生成日志记录结构描述,再生成日志记录体,并追加到日志文件尾。追加日志记录时要考虑并发写入问题(加锁)根据当前日期时间,及日志记录的位置生成索引记录,并发写入索引文件。日志记录与索引记录要同时锁定,否则会发生错误浏览日志:浏览给定时间段日志。根据给定时间段,遍历索引文件找到给定时间段的索引记录,然后根据索引记录读出日志记录并显示,直到时间段结束。结构设计与分析文件结构设计本程序总体设计为两个txt文件,即一个日志文件Log,一个索引文件Index。其中日志文件中主要保存当前记录的总长度,当前记录的每个内容的类型及长度,还有具体内容这三部分;索引文件中则保存的是写入日志的当前时间和当前日志开始的位置指针。其结构体分别定义如下:struct logStructure int dataType; int dataSize;typedef struct indexStructure time_t writeTime; int logF;indexStructure_t;数据类型设计由于要求随机写入随机的数据类型,所以在此定义了6种数据类型,分别为char int short long float double类型,另外用字符数组来存放string类型的数据。数据类型及数据类型的长度保存方法如下:const int typeSize6 = sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(float), sizeof(double);const char typeName710= char, short, int, long, float, double, char;const char output76 = %cn, %dn, %dn, %ldn, %lldn, %fn, %sn;写入数据设计文件锁的设计在本次的实验中,要求实现多线程同时访问文件并进行并发式的写入,为此需要对访问文件进行上锁。为了尽可能的提高并发度,文件的打开方式设置为共享打开方式,这样就可以多个线程同时打开文件了。下面讨论如何实现并发。在本次实验中,我才用的方式是当线程访问文件时先对文件的大小进行改变,然后在写入数据,因为相对于改变文件大小,写入数据的时间是相对慢一些的,这样就可以让各个线程先进行对文件大小的修改,然后再各自慢慢的写入数据。所以在写入数据时并不需要进行加锁,因为大家都往自己改过的空间里写入数据,需要加锁的地方只是在修改文件大小的时候。然而,要更改文件的大小实际上是修改文件的属性中的Size值,如图1-1所示,文件的Size属性在文件的头部,而_locking函数所的是从文件体的当前指针位置指定的长度,此操作并没有将文件头部锁住,所以在实现并发的过程中就可能出现多个线程同时修改Size的情况导致写入混乱。图1-1所以在此处我采用的方法为设置一个互斥变量int test = 0;然后每条线程在打开文件后均进行while循环当test = 1时进循环并输出等待信息,当test = 0时,跳出循环然后将test置一表示当前有线程在进行文件属性的修改其他线程则继续进行while循环。写入数据设计在产生数据方面根据要求所有的内容都是随机的,这样我的设计方案是,首先进行播种,然后随机生成一条记录要写的总字节数即WriteSize。首先将总字节数写入到一条记录的最前面4个字节方便以后向外读。然后将type随机产生个数模7确定随机产生的类型,将该类型和该类型的长度作为描述写入日志中,然后写入对应的随机产生的该类型的数据。就这样一个数据一个数据写入,每写一次WriteSize减去一个log结构体的字节大小即数据类型描述的大小,再减去一个数据类型长度的大小即写入内容的字节数,这样直到WriseSize小于或等于0的时候结束循环不再写入。文件内容存储方式如图1-2所示:图1-2读出数据设计时间获取转换方法根据题目要求,在读取数据的时候需要可以让用户按照指定的时间范围来获取对应的日志记录,这样就需要将用户输入的字符串类型的日期(年月日时分秒)如20140316164800转换成系统时间的time_t类型。此方法需要运用系统的tm结构体,进行一系列简单的运算即可完成,因为time_t类型,我在查看VS2010对其声明的时候发现,它就是一个64为的int型长整数。具体的转换方法见代码。读取数据设计此部分的大体思想和写入时很相近,也是将每条记录的数据根据其描述按类型一个一个读取出来。由于功能上要求用户可以按所输入的时间范围读取日志记录,所以在这里需要先建立一个indexStructure类型的数组来将索引文件中的时间都保存到其中。然后将获取的用户输入的时间转换成长整型数,这样就可以通过大小的比较来确定到底要读取那条记录了。接下来只需将文件指针移动到索引中保存的记录开始位置,进行读取,方法同写入时一样,先读取4个字节获取当时的WriteSize,在此命名为ReadSize,然后读sizeof(logStructure)长度的字节获取该数据的类型,然后按照类型读入,再按照类型输出即可。运行结果截图写日志:图1-4读日志:图1-5图1-6遇到的问题及心得在本次实验中起初设计的比较简单,为了实现并发我讲文件的打开方式设置为追加方式,同时为不可共享方式,这样在一个线程打开该文件的情况下其他文件就无法打开,其他文件就进行死循环判断直到能打开为止。这种方法下遇到的第一个问题就是每条线程都要打开和关闭2个文件这样就出现了死循环,以2个线程为例如图1-3所示:图1-3这样当第一个线程成功打开日志和索引正在写入,当写入结束时,线程2判断能不能打开日志文件结果不能,这时线程1将日志文件释放,再将索引文件释放;线程2再判断能不能打开索引文件判断为能打开,但是并不是同时打开日志和索引,索引就循环回去重新判断,此时日志文件可以打开了但是索引文件已经是打开状态了此时就会发生线程2第二次判断索引文件为打不开,这样就会死循环在这里。解决的办法为当发生这种一个打开一个没打开的情况时就将打开的那个文件指针释放,这样就解决了问题。但在之后的讨论中这种方法由于并发度过低决定放弃使用。之后便想到先改文件大小再写日志的方法,在这里出现的问题就是运用_locking函数上锁的时候然后执行写入操作的时候总会出现错误,这个问题通过前面叙述的设置一个变量即可解决。在调试到最后的过程中,出现了个最可笑的错误,就是前面刚写入WriteSize时为了看看是不是正确写入了,当时我就写了一个Read进行测试。结果在写读取函数的时候发现,怎么读好像指针都指的位置不对,每次读出来的不是笑脸就是零星,通过单步调试发现读

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论