變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)報(bào)告.docx_第1頁
變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)報(bào)告.docx_第2頁
變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)報(bào)告.docx_第3頁
變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)報(bào)告.docx_第4頁
變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)報(bào)告.docx_第5頁
已閱讀5頁,還剩5頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

20140316變長并發(fā)日志文件的設(shè)計(jì)及實(shí)現(xiàn)目錄程序員簡介2設(shè)計(jì)要求2系統(tǒng)組成2主要功能2結(jié)構(gòu)設(shè)計(jì)與分析2文件結(jié)構(gòu)設(shè)計(jì)2數(shù)據(jù)類型設(shè)計(jì)3寫入數(shù)據(jù)設(shè)計(jì)3文件鎖的設(shè)計(jì)3寫入數(shù)據(jù)設(shè)計(jì)4讀出數(shù)據(jù)設(shè)計(jì)5時(shí)間獲取轉(zhuǎn)換方法5讀取數(shù)據(jù)設(shè)計(jì)5運(yùn)行結(jié)果截圖6遇到的問題及心得8采用的技術(shù)8開發(fā)環(huán)境9程序員簡介姓名:李爾楠學(xué)號:11281008班級:計(jì)科1101設(shè)計(jì)要求系統(tǒng)組成系統(tǒng)由兩個(gè)文件組成,日志文件及索引文件;日志文件存放日志記錄,日志記錄由日志記錄結(jié)構(gòu)描述,及日志記錄體組成;每個(gè)日志記錄可包含任意條數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)可是任意數(shù)據(jù)類型及長度;日志記錄結(jié)構(gòu)描述對本記錄的每個(gè)數(shù)據(jù)項(xiàng)進(jìn)行描述。包括數(shù)據(jù)類型及長度;日志記錄體根據(jù)日志記錄結(jié)構(gòu)描述來存放日志記錄數(shù)據(jù)。索引文件存放自動增長的日志記錄號,日志記錄發(fā)生的日期及時(shí)間,指向日志文件中相應(yīng)日志記錄的文件指針。主要功能增加日志記錄:生成日志記錄并寫入。根據(jù)本次日志記錄各數(shù)據(jù)項(xiàng)生成日志記錄結(jié)構(gòu)描述,再生成日志記錄體,并追加到日志文件尾。追加日志記錄時(shí)要考慮并發(fā)寫入問題(加鎖)根據(jù)當(dāng)前日期時(shí)間,及日志記錄的位置生成索引記錄,并發(fā)寫入索引文件。日志記錄與索引記錄要同時(shí)鎖定,否則會發(fā)生錯(cuò)誤瀏覽日志:瀏覽給定時(shí)間段日志。根據(jù)給定時(shí)間段,遍歷索引文件找到給定時(shí)間段的索引記錄,然后根據(jù)索引記錄讀出日志記錄并顯示,直到時(shí)間段結(jié)束。結(jié)構(gòu)設(shè)計(jì)與分析文件結(jié)構(gòu)設(shè)計(jì)本程序總體設(shè)計(jì)為兩個(gè)txt文件,即一個(gè)日志文件Log,一個(gè)索引文件Index。其中日志文件中主要保存當(dāng)前記錄的總長度,當(dāng)前記錄的每個(gè)內(nèi)容的類型及長度,還有具體內(nèi)容這三部分;索引文件中則保存的是寫入日志的當(dāng)前時(shí)間和當(dāng)前日志開始的位置指針。其結(jié)構(gòu)體分別定義如下:struct logStructure int dataType; int dataSize;typedef struct indexStructure time_t writeTime; int logF;indexStructure_t;數(shù)據(jù)類型設(shè)計(jì)由于要求隨機(jī)寫入隨機(jī)的數(shù)據(jù)類型,所以在此定義了6種數(shù)據(jù)類型,分別為char int short long float double類型,另外用字符數(shù)組來存放string類型的數(shù)據(jù)。數(shù)據(jù)類型及數(shù)據(jù)類型的長度保存方法如下: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;寫入數(shù)據(jù)設(shè)計(jì)文件鎖的設(shè)計(jì)在本次的實(shí)驗(yàn)中,要求實(shí)現(xiàn)多線程同時(shí)訪問文件并進(jìn)行并發(fā)式的寫入,為此需要對訪問文件進(jìn)行上鎖。為了盡可能的提高并發(fā)度,文件的打開方式設(shè)置為共享打開方式,這樣就可以多個(gè)線程同時(shí)打開文件了。下面討論如何實(shí)現(xiàn)并發(fā)。在本次實(shí)驗(yàn)中,我才用的方式是當(dāng)線程訪問文件時(shí)先對文件的大小進(jìn)行改變,然后在寫入數(shù)據(jù),因?yàn)橄鄬τ诟淖兾募笮?,寫入?shù)據(jù)的時(shí)間是相對慢一些的,這樣就可以讓各個(gè)線程先進(jìn)行對文件大小的修改,然后再各自慢慢的寫入數(shù)據(jù)。所以在寫入數(shù)據(jù)時(shí)并不需要進(jìn)行加鎖,因?yàn)榇蠹叶纪约焊倪^的空間里寫入數(shù)據(jù),需要加鎖的地方只是在修改文件大小的時(shí)候。然而,要更改文件的大小實(shí)際上是修改文件的屬性中的Size值,如圖1-1所示,文件的Size屬性在文件的頭部,而_locking函數(shù)所的是從文件體的當(dāng)前指針位置指定的長度,此操作并沒有將文件頭部鎖住,所以在實(shí)現(xiàn)并發(fā)的過程中就可能出現(xiàn)多個(gè)線程同時(shí)修改Size的情況導(dǎo)致寫入混亂。圖1-1所以在此處我采用的方法為設(shè)置一個(gè)互斥變量int test = 0;然后每條線程在打開文件后均進(jìn)行while循環(huán)當(dāng)test = 1時(shí)進(jìn)循環(huán)并輸出等待信息,當(dāng)test = 0時(shí),跳出循環(huán)然后將test置一表示當(dāng)前有線程在進(jìn)行文件屬性的修改其他線程則繼續(xù)進(jìn)行while循環(huán)。寫入數(shù)據(jù)設(shè)計(jì)在產(chǎn)生數(shù)據(jù)方面根據(jù)要求所有的內(nèi)容都是隨機(jī)的,這樣我的設(shè)計(jì)方案是,首先進(jìn)行播種,然后隨機(jī)生成一條記錄要寫的總字節(jié)數(shù)即WriteSize。首先將總字節(jié)數(shù)寫入到一條記錄的最前面4個(gè)字節(jié)方便以后向外讀。然后將type隨機(jī)產(chǎn)生個(gè)數(shù)模7確定隨機(jī)產(chǎn)生的類型,將該類型和該類型的長度作為描述寫入日志中,然后寫入對應(yīng)的隨機(jī)產(chǎn)生的該類型的數(shù)據(jù)。就這樣一個(gè)數(shù)據(jù)一個(gè)數(shù)據(jù)寫入,每寫一次WriteSize減去一個(gè)log結(jié)構(gòu)體的字節(jié)大小即數(shù)據(jù)類型描述的大小,再減去一個(gè)數(shù)據(jù)類型長度的大小即寫入內(nèi)容的字節(jié)數(shù),這樣直到WriseSize小于或等于0的時(shí)候結(jié)束循環(huán)不再寫入。文件內(nèi)容存儲方式如圖1-2所示:圖1-2讀出數(shù)據(jù)設(shè)計(jì)時(shí)間獲取轉(zhuǎn)換方法根據(jù)題目要求,在讀取數(shù)據(jù)的時(shí)候需要可以讓用戶按照指定的時(shí)間范圍來獲取對應(yīng)的日志記錄,這樣就需要將用戶輸入的字符串類型的日期(年月日時(shí)分秒)如20140316164800轉(zhuǎn)換成系統(tǒng)時(shí)間的time_t類型。此方法需要運(yùn)用系統(tǒng)的tm結(jié)構(gòu)體,進(jìn)行一系列簡單的運(yùn)算即可完成,因?yàn)閠ime_t類型,我在查看VS2010對其聲明的時(shí)候發(fā)現(xiàn),它就是一個(gè)64為的int型長整數(shù)。具體的轉(zhuǎn)換方法見代碼。讀取數(shù)據(jù)設(shè)計(jì)此部分的大體思想和寫入時(shí)很相近,也是將每條記錄的數(shù)據(jù)根據(jù)其描述按類型一個(gè)一個(gè)讀取出來。由于功能上要求用戶可以按所輸入的時(shí)間范圍讀取日志記錄,所以在這里需要先建立一個(gè)indexStructure類型的數(shù)組來將索引文件中的時(shí)間都保存到其中。然后將獲取的用戶輸入的時(shí)間轉(zhuǎn)換成長整型數(shù),這樣就可以通過大小的比較來確定到底要讀取那條記錄了。接下來只需將文件指針移動到索引中保存的記錄開始位置,進(jìn)行讀取,方法同寫入時(shí)一樣,先讀取4個(gè)字節(jié)獲取當(dāng)時(shí)的WriteSize,在此命名為ReadSize,然后讀sizeof(logStructure)長度的字節(jié)獲取該數(shù)據(jù)的類型,然后按照類型讀入,再按照類型輸出即可。運(yùn)行結(jié)果截圖寫日志:圖1-4讀日志:圖1-5圖1-6遇到的問題及心得在本次實(shí)驗(yàn)中起初設(shè)計(jì)的比較簡單,為了實(shí)現(xiàn)并發(fā)我講文件的打開方式設(shè)置為追加方式,同時(shí)為不可共享方式,這樣在一個(gè)線程打開該文件的情況下其他文件就無法打開,其他文件就進(jìn)行死循環(huán)判斷直到能打開為止。這種方法下遇到的第一個(gè)問題就是每條線程都要打開和關(guān)閉2個(gè)文件這樣就出現(xiàn)了死循環(huán),以2個(gè)線程為例如圖1-3所示:圖1-3這樣當(dāng)?shù)谝粋€(gè)線程成功打開日志和索引正在寫入,當(dāng)寫入結(jié)束時(shí),線程2判斷能不能打開日志文件結(jié)果不能,這時(shí)線程1將日志文件釋放,再將索引文件釋放;線程2再判斷能不能打開索引文件判斷為能打開,但是并不是同時(shí)打開日志和索引,索引就循環(huán)回去重新判斷,此時(shí)日志文件可以打開了但是索引文件已經(jīng)是打開狀態(tài)了此時(shí)就會發(fā)生線程2第二次判斷索引文件為打不開,這樣就會死循環(huán)在這里。解決的辦法為當(dāng)發(fā)生這種一個(gè)打開一個(gè)沒打開的情況時(shí)就將打開的那個(gè)文件指針釋放,這樣就解決了問題。但在之后的討論中這種方法由于并發(fā)度過低決定放棄使用。之后便想到先改文件大小再寫日志的方法,在這里出現(xiàn)的問題就是運(yùn)用_locking函數(shù)上鎖的時(shí)候然后執(zhí)行寫入操作的時(shí)候總會出現(xiàn)錯(cuò)誤,這個(gè)問題通過前面敘述的設(shè)置一個(gè)變量即可解決。在調(diào)試到最后的過程中,出現(xiàn)了個(gè)最可笑的錯(cuò)誤,就是前面剛寫入WriteSize時(shí)為了看看是不是正確寫入了,當(dāng)時(shí)我就寫了一個(gè)Read進(jìn)行測試。結(jié)果在寫讀取函數(shù)的時(shí)候發(fā)現(xiàn),怎么讀好像指針都指的位置不對,每次讀出來的不是笑臉就是零星,通過單步調(diào)試發(fā)現(xiàn)讀

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論