Skip to content

Commit 03b87c9

Browse files
committed
Add filelock to ensure file access single thread
Manual release file lock
1 parent aa4ed25 commit 03b87c9

File tree

8 files changed

+102
-53
lines changed

8 files changed

+102
-53
lines changed

drls/app.py

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
from drls.extensions import bcrypt, cache, csrf_protect, db, debug_toolbar, login_manager, migrate, webpack
77
from drls.settings import ProdConfig
88
from drls.utils import JSONR
9+
from filelock import Timeout, FileLock
10+
11+
import os
912

1013

1114
def create_app(config_object=ProdConfig):
@@ -20,6 +23,7 @@ def create_app(config_object=ProdConfig):
2023
register_errorhandlers(app)
2124
register_shellcontext(app)
2225
register_commands(app)
26+
register_user_variable(app)
2327
return app
2428

2529

@@ -72,3 +76,19 @@ def register_commands(app):
7276
app.cli.add_command(commands.lint)
7377
app.cli.add_command(commands.clean)
7478
app.cli.add_command(commands.urls)
79+
80+
def register_user_variable(app):
81+
app.config.lock_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['LOCK_FILE_NAME'])
82+
app.config.seed_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMSEED_FILE_NAME'])
83+
app.config.xls_file_path = os.path.join(app.config['UPLOAD_FOLDER'], app.config['STUDATA_FILE_NAME'])
84+
app.config.num_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMNUM_FILE_NAME'])
85+
86+
app.config.lock_file_lock_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['LOCK_FILE_NAME']+'.lock')
87+
app.config.seed_file_lock_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMSEED_FILE_NAME']+'.lock')
88+
app.config.xls_file_lock_path = os.path.join(app.config['UPLOAD_FOLDER'], app.config['STUDATA_FILE_NAME']+'.lock')
89+
app.config.num_file_lock_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMNUM_FILE_NAME']+'.lock')
90+
91+
app.config.num_file_lock = FileLock(app.config.num_file_lock_path)
92+
app.config.seed_file_lock = FileLock(app.config.seed_file_lock_path)
93+
app.config.xls_file_lock = FileLock(app.config.xls_file_lock_path)
94+
app.config.lock_file_lock = FileLock(app.config.lock_file_lock_path)

drls/data/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ studata.xls
33
random.txt
44
num.txt
55
lock.txt
6+
*.lock

drls/data/random_seed.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1155123

drls/public/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# -*- coding: utf-8 -*-
22
"""The public module, including the homepage and user auth."""
33
from . import views # noqa
4+

drls/public/views.py

+70-51
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
from drls.utils import read_excel, cal_range, file_exists,allowed_file,app_dir,load_md,JSONR
77
from drls.rng import RandomGenerator
88
from werkzeug.utils import secure_filename
9-
import hashlib
109

1110
import os
12-
import json
1311
import drls.errcode as ERRCODE
1412

13+
14+
1515
blueprint = Blueprint('public', __name__, static_folder='../static')
1616

1717

@@ -22,8 +22,8 @@ def home():
2222
# if lock.txt exits, hide select excel form
2323
# 如果 studta.xls文件存在,则显示之前的random连接
2424
# 如果 lock.txt文件存在,则不显示选取文件表单
25-
show_previous=file_exists(os.path.join(app.config['UPLOAD_FOLDER'],app.config['STUDATA_FILE_NAME']))
26-
lock_form = file_exists(os.path.join(app.config['UPLOAD_FOLDER'],app.config['LOCK_FILE_NAME']))
25+
show_previous=file_exists(app.config.xls_file_path)
26+
lock_form = file_exists(app.config.lock_file_path)
2727
return render_template('public/home.html', data_exist=show_previous, lock=lock_form)
2828

2929
@blueprint.route('/about/')
@@ -41,34 +41,37 @@ def upload():
4141
app.logger.info(seed)
4242
app.logger.info(num)
4343
# check passwd
44-
lock_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['LOCK_FILE_NAME'])
45-
lock = file_exists(lock_file_path)
44+
lock = file_exists(app.config.lock_file_path)
4645
if lock:
4746
passwd = request.form['passwd']
4847
app.logger.info(passwd)
4948
app.logger.info(lock)
50-
passwd_file = open(lock_file_path,'r')
51-
real_passwd = passwd_file.readline().strip()
52-
passwd_file.close()
49+
app.config.lock_file_lock.acquire()
50+
passwd_file = open(app.config.lock_file_path,'r')
51+
try:
52+
real_passwd = passwd_file.readline().strip()
53+
finally:
54+
passwd_file.close()
55+
app.config.lock_file_lock.release()
5356
if real_passwd != passwd:
5457
return JSONR(ERRCODE.UNAUTHORIZED,'password was wrong')
55-
else:
56-
pass
57-
seed_file_path = os.path.join(app.config['UPLOAD_FOLDER'], app.config['RANDOMSEED_FILE_NAME'])
58-
num_file_path = os.path.join(app.config['UPLOAD_FOLDER'], app.config['RANDOMNUM_FILE_NAME'])
5958

6059
# save random_seed
61-
seed_file = open(seed_file_path,'w')
60+
app.config.seed_file_lock.acquire()
61+
seed_file = open(app.config.seed_file_path,'w')
6262
try:
6363
random_seed = int(seed)
6464
seed_file.write(str(random_seed))
6565
except ValueError:
6666
return JSONR(ERRCODE.FORMAT_ERROR,'random seed format error', seed)
6767
finally:
6868
seed_file.close()
69+
app.config.seed_file_lock.release()
6970

71+
app.config.num_file_lock.acquire()
7072
# save random_num
71-
num_file = open(num_file_path,'w')
73+
num_file = open(app.config.num_file_path,'w')
74+
7275
try:
7376
random_num = int(num)
7477
num_file.write(str(random_num))
@@ -77,67 +80,73 @@ def upload():
7780
return JSONR(ERRCODE.FORMAT_ERROR,'random num format error', num)
7881
finally:
7982
num_file.close()
83+
app.config.num_file_lock.release()
8084

8185
# save stu file
82-
file = request.files['fileUploaded']
83-
if file and allowed_file(file.filename,app.config['ALLOWED_EXTENSIONS']):
84-
filename = secure_filename(file.filename)
85-
# app.logger.info(filename.split('.',1)[0])
86-
# target_filename = filename.split('.',1)[0] + '-' + str(hashlib.sha224(filename).hexdigest()) +'.'+ filename.split('.',1)[1]
87-
# TODO only support xls type file
88-
target_filename = app.config['STUDATA_FILE_NAME']
89-
file.save(os.path.join(app.config['UPLOAD_FOLDER'], target_filename))
90-
# return redirect(url_for('public.random',filename=filename))
91-
return JSONR(ERRCODE.SUCCESS,'success')
92-
else:
93-
return JSONR(ERRCODE.INVALID_FILE,'invalid file extension')
86+
app.config.xls_file_lock.acquire()
87+
try:
88+
file = request.files['fileUploaded']
89+
if file and allowed_file(file.filename,app.config['ALLOWED_EXTENSIONS']):
90+
filename = secure_filename(file.filename)
91+
# app.logger.info(filename.split('.',1)[0])
92+
# target_filename = filename.split('.',1)[0] + '-' + str(hashlib.sha224(filename).hexdigest()) +'.'+ filename.split('.',1)[1]
93+
# TODO only support xls type file
94+
target_filename = app.config['STUDATA_FILE_NAME']
95+
file.save(os.path.join(app.config['UPLOAD_FOLDER'], target_filename))
96+
# return redirect(url_for('public.random',filename=filename))
97+
return JSONR(ERRCODE.SUCCESS,'success')
98+
else:
99+
return JSONR(ERRCODE.INVALID_FILE,'invalid file extension')
100+
finally:
101+
app.config.xls_file_lock.release()
102+
94103
return JSONR(ERRCODE.INVALID_REQUEST,'only support post method')
95104

96105
@blueprint.route('/random/', methods=['GET'])
97106
def random():
98107
"""random page."""
99108
if file_exists(os.path.join(app.config['UPLOAD_FOLDER'],app.config['STUDATA_FILE_NAME'])):
100-
seed_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMSEED_FILE_NAME'])
101-
num_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMNUM_FILE_NAME'])
102109

103110
random_num = 0
104111
random_seed =0
105-
if file_exists(seed_file_path):
106-
seed_file = open(seed_file_path)
112+
app.config.seed_file_lock.acquire()
113+
if file_exists(app.config.seed_file_path):
114+
seed_file = open(app.config.seed_file_path)
107115
try:
108116
seed = seed_file.readline().strip()
109117
random_seed = int(seed)
110118
except ValueError:
111119
return render_template('public/random.html',random_seed=0, random_num=0)
112120
finally:
113121
seed_file.close()
122+
app.config.seed_file_lock.release()
114123

115-
if file_exists(num_file_path):
116-
num_file = open(num_file_path)
124+
app.config.num_file_lock.acquire()
125+
if file_exists(app.config.num_file_path):
126+
num_file = open(app.config.num_file_path)
117127
try:
118128
num = num_file.readline().strip()
119129
random_num = int(num)
120130
except ValueError:
121131
return render_template('public/random.html',random_seed=random_seed, random_num=0)
122132
finally:
123133
num_file.close()
124-
return render_template('public/random.html',random_seed=random_seed, random_num=random_num)
134+
app.config.num_file_lock.release()
135+
return render_template('public/random.html',random_seed=random_seed, random_num=random_num)
125136

126137
return redirect(url_for('public.home'))
127138

128139

129140
@blueprint.route('/rand/', methods=['POST'])
130141
def rand():
131142
"""rand"""
132-
xls_file = os.path.join(app.config['UPLOAD_FOLDER'],app.config['STUDATA_FILE_NAME'])
133143
# get random seed
134-
seed_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMSEED_FILE_NAME'])
135-
num_file_path = os.path.join(app.config['UPLOAD_FOLDER'],app.config['RANDOMNUM_FILE_NAME'])
136144

137145
random_num = 0
138146
random_seed =0
139-
if file_exists(seed_file_path):
140-
seed_file = open(seed_file_path)
147+
app.config.seed_file_lock.acquire()
148+
if file_exists(app.config.seed_file_path):
149+
seed_file = open(app.config.seed_file_path)
141150
seed = 0
142151
try:
143152
seed = seed_file.readline().strip()
@@ -146,8 +155,11 @@ def rand():
146155
return JSONR(ERRCODE.FORMAT_ERROR,'convert random seed failed',seed)
147156
finally:
148157
seed_file.close()
149-
if file_exists(num_file_path):
150-
num_file = open(num_file_path)
158+
app.config.seed_file_lock.release()
159+
160+
app.config.num_file_lock.acquire()
161+
if file_exists(app.config.num_file_path):
162+
num_file = open(app.config.num_file_path)
151163
num = 0
152164
try:
153165
num = num_file.readline().strip()
@@ -156,17 +168,24 @@ def rand():
156168
return JSONR(ERRCODE.FORMAT_ERROR,'convert random num failed',num)
157169
finally:
158170
num_file.close()
171+
app.config.num_file_lock.release()
172+
159173
# calc random result
160-
if file_exists(xls_file):
174+
app.config.xls_file_lock.acquire()
175+
if file_exists(app.config.xls_file_path):
161176
# rand
162-
dicts = read_excel(xls_file)
163-
res = RandomGenerator(random_seed, cal_range(dicts), random_num, dicts)
164-
studs = res.GenerateResult()
165-
res = []
166-
for key in dicts:
167-
res.append({"key":key,"value":dicts[key]})
168-
app.logger.info(res)
169-
data = {'allstus': res,'studs':studs }
170-
return JSONR(ERRCODE.SUCCESS,'success',data)
177+
try:
178+
dicts = read_excel(app.config.xls_file_path)
179+
res = RandomGenerator(random_seed, cal_range(dicts), random_num, dicts)
180+
studs = res.GenerateResult()
181+
res = []
182+
for key in dicts:
183+
res.append({"key":key,"value":dicts[key]})
184+
app.logger.info(res)
185+
data = {'allstus': res,'studs':studs }
186+
187+
return JSONR(ERRCODE.SUCCESS,'success',data)
188+
finally:
189+
app.config.xls_file_lock.release()
171190
return JSONR(ERRCODE.UNKNOW,'failed')
172191

drls/settings.py

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class Config(object):
2727

2828

2929

30+
31+
3032
class ProdConfig(Config):
3133
"""Production configuration."""
3234

requirements/prod.txt

+3
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,6 @@ markdown2==2.3.5
4242

4343
#Excel
4444
xlrd==1.1.0
45+
46+
#filelock
47+
filelock==3.0.4

tests/test_rng.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import unittest
22

33
from drls.rng import RandomGenerator
4+
from drls.utils import cal_range
45

56

67
if __name__ == "__main__":
7-
dict = {'21751117': 1.0,'21751114': 1.0,'21751115': 1.0, '21751110': 1.0,'21751111': 1.0, '21751464': 1.0, '21751465': 1.0, '21751462': 1.0, '21751463': 1.0}
8-
res = RandomGenerator(1,9,5,dict)
8+
dict = {'21751117': 100.0,'21751114': 1.0,'21751115': 1.0, '21751110': 1.0,'21751111': 1.0, '21751464': 1.0, '21751465': 1.0, '21751462': 1.0, '21751463': 1.0}
9+
sum = cal_range(dict)
10+
res = RandomGenerator(1,sum,1,dict)
911
studs = res.GenerateResult()
1012
print studs

0 commit comments

Comments
 (0)