Skip to content

Commit 9d581bc

Browse files
authored
Merge pull request #1945 from ivanistheone/bugfixed/1818
Cleaned up version of fixes for #1818
2 parents 19a9ce1 + a23aa81 commit 9d581bc

File tree

5 files changed

+48
-17
lines changed

5 files changed

+48
-17
lines changed

kolibri/content/api.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from django.db.models import Q, Sum
88
from django.db.models.aggregates import Count
99
from kolibri.content import models, serializers
10-
from kolibri.content.content_db_router import get_active_content_database
10+
from kolibri.content.content_db_router import get_active_content_database, using_content_database
1111
from kolibri.logger.models import ContentSessionLog, ContentSummaryLog
1212
from le_utils.constants import content_kinds
1313
from rest_framework import filters, pagination, viewsets
@@ -359,10 +359,11 @@ def get_queryset(self):
359359

360360
class ChannelFileSummaryViewSet(viewsets.ViewSet):
361361
def list(self, request, **kwargs):
362-
file_summary = models.File.objects.aggregate(
363-
total_files=Count('pk'),
364-
total_file_size=Sum('file_size')
365-
)
366-
file_summary['channel_id'] = get_active_content_database()
367-
# Need to wrap in an array to be fetchable as a Collection on client
368-
return Response([file_summary])
362+
with using_content_database(kwargs['channel_id']):
363+
file_summary = models.File.objects.aggregate(
364+
total_files=Count('pk'),
365+
total_file_size=Sum('file_size')
366+
)
367+
file_summary['channel_id'] = get_active_content_database()
368+
# Need to wrap in an array to be fetchable as a Collection on client
369+
return Response([file_summary])

kolibri/content/middleware.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ class ContentDBRoutingMiddleware(object):
99
"""
1010

1111
def process_view(self, request, view_func, view_args, view_kwargs):
12-
request.PREVIOUSLY_ACTIVE_CONTENT_DATABASE = get_active_content_database(return_none_if_not_set=True)
13-
if "channel_id" in view_kwargs:
14-
set_active_content_database(view_kwargs["channel_id"])
12+
if view_func.__name__ == 'TasksViewSet':
13+
pass # Fix #1818.1: skip get_active_content_database for Task workers to avoid locking DB
14+
else:
15+
request.PREVIOUSLY_ACTIVE_CONTENT_DATABASE = get_active_content_database(return_none_if_not_set=True)
16+
if "channel_id" in view_kwargs:
17+
set_active_content_database(view_kwargs["channel_id"])
1518

1619
def process_response(self, request, response):
1720
set_active_content_database(getattr(request, "PREVIOUSLY_ACTIVE_CONTENT_DATABASE", None))

kolibri/content/utils/annotation.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ def update_channel_metadata_cache():
3232
if ch_metadata_obj.last_updated is None:
3333
ch_metadata_obj.last_updated = local_now()
3434
ch_metadata_obj.save()
35+
36+
# Fix #1818.1 content database files get locked (this is called on startup)
37+
from django.db import connections
38+
connections.close_all()

kolibri/content/utils/channels.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,15 @@ def enumerate_content_database_file_paths(content_database_dir):
5353
def read_channel_metadata_from_db_file(channeldbpath):
5454
# import here to avoid circular imports whenever kolibri.content.models imports utils too
5555
from kolibri.content.models import ChannelMetadata
56-
5756
with using_content_database(channeldbpath):
58-
return ChannelMetadata.objects.first()
57+
channel_metadata = ChannelMetadata.objects.first()
58+
59+
# FIX for #1818.2: DB file on removable media remains locked after import
60+
from django.db import connections
61+
connections.close_all()
62+
63+
return channel_metadata
64+
5965

6066
def get_channels_for_data_folder(datafolder):
6167
channels = []

kolibri/tasks/api.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import requests
1515
from django.core.management import call_command
1616
from django.http import Http404
17+
from django.db import connections
1718
from django.utils.translation import ugettext as _
1819
from kolibri.content.models import ChannelMetadataCache
1920
from kolibri.content.utils.channels import get_mounted_drives_with_channel_info
@@ -143,37 +144,53 @@ def localdrive(self, request):
143144

144145

145146
def _networkimport(channel_id, update_progress=None):
146-
call_command("importchannel", "network", channel_id)
147+
call_command(
148+
"importchannel",
149+
"network",
150+
channel_id,
151+
update_progress=update_progress)
147152
call_command(
148153
"importcontent",
149154
"network",
150155
channel_id,
151156
update_progress=update_progress)
152-
157+
connections.close_all() # close all DB connections (FIX for #1818)
153158

154159
def _localimport(drive_id, update_progress=None):
155160
drives = get_mounted_drives_with_channel_info()
156161
drive = drives[drive_id]
162+
# copy channel's db file then copy all the content files from sorage dir
157163
for channel in drive.metadata["channels"]:
158-
call_command("importchannel", "local", channel["id"], drive.datafolder)
164+
call_command(
165+
"importchannel",
166+
"local",
167+
channel["id"],
168+
drive.datafolder,
169+
update_progress=update_progress)
159170
call_command(
160171
"importcontent",
161172
"local",
162173
channel["id"],
163174
drive.datafolder,
164175
update_progress=update_progress)
176+
connections.close_all() # close all DB connections (FIX for #1818)
165177

166178

167179
def _localexport(drive_id, update_progress=None):
168180
drives = get_mounted_drives_with_channel_info()
169181
drive = drives[drive_id]
170182
for channel in ChannelMetadataCache.objects.all():
171-
call_command("exportchannel", channel.id, drive.datafolder)
183+
call_command(
184+
"exportchannel",
185+
channel.id,
186+
drive.datafolder,
187+
update_progress=update_progress)
172188
call_command(
173189
"exportcontent",
174190
channel.id,
175191
drive.datafolder,
176192
update_progress=update_progress)
193+
connections.close_all() # close all DB connections (FIX for #1818)
177194

178195

179196
def _job_to_response(job):

0 commit comments

Comments
 (0)