diff --git a/.gitignore b/.gitignore index 45e47dc..7215a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # custom files db.sqlite settings.py - +.idea # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f38fb48 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +django +mercantile +geojson diff --git a/tileservermapping/slowtiles/admin.py b/tileservermapping/slowtiles/admin.py new file mode 100644 index 0000000..d492e63 --- /dev/null +++ b/tileservermapping/slowtiles/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +# Register your models here. +from .models import SlowTiles + +admin.site.register(SlowTiles) diff --git a/tileservermapping/slowtiles/migrations/0001_initial.py b/tileservermapping/slowtiles/migrations/0001_initial.py new file mode 100644 index 0000000..b6ee9e4 --- /dev/null +++ b/tileservermapping/slowtiles/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.1 on 2020-02-09 20:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('mapping', '0006_auto_20181226_1555'), + ] + + operations = [ + migrations.CreateModel( + name='SlowTiles', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('z', models.IntegerField()), + ('x', models.IntegerField()), + ('y', models.IntegerField()), + ('count', models.IntegerField(default=1)), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mapping.Server')), + ], + options={ + 'unique_together': {('z', 'x', 'y')}, + }, + ), + ] diff --git a/tileservermapping/slowtiles/migrations/__init__.py b/tileservermapping/slowtiles/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tileservermapping/slowtiles/models.py b/tileservermapping/slowtiles/models.py new file mode 100644 index 0000000..6b33e2e --- /dev/null +++ b/tileservermapping/slowtiles/models.py @@ -0,0 +1,39 @@ +from django.db import models, transaction +from tileservermapping.mapping.models import Server + + +class SlowTiles(models.Model): + z = models.IntegerField(null=False) + x = models.IntegerField(null=False) + y = models.IntegerField(null=False) + + server = models.ForeignKey(Server, on_delete=models.CASCADE) + + count = models.IntegerField(default=1) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + class Meta: + unique_together = ['z', 'x', 'y'] + + def __str__(self): + return "".format(self.z, self.x, self.y, self.count) + + @staticmethod + def insert(z, x, y): + """ + inserts a tile z/x/y into the slow tile list, or increase the counter on an existing tile + :return: the current counter on this tile, or -1 if no tile server is responsible + """ + server = Server.get_server(z, x, y) + if server == Server.objects.get(z=0, x=0, y=0): + # we can not do anything on the external instance + return -1 + with transaction.atomic(): + try: + tile = SlowTiles.objects.get(z=z, x=x, y=y) + tile.count += 1 + except models.ObjectDoesNotExist: + tile = SlowTiles(z=z, x=x, y=y, server=server) + tile.save() + return tile.count diff --git a/tileservermapping/slowtiles/urls.py b/tileservermapping/slowtiles/urls.py new file mode 100644 index 0000000..1c108aa --- /dev/null +++ b/tileservermapping/slowtiles/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from .views import insert_tile, get_server_list, upload_tile + +urlpatterns = [ + path('add///', insert_tile, name="insert_tile"), + path('server_list///', get_server_list, name="server_list"), + path('upload_tile///.', upload_tile, name='upload_tile'), +] diff --git a/tileservermapping/slowtiles/views.py b/tileservermapping/slowtiles/views.py new file mode 100644 index 0000000..0c967f5 --- /dev/null +++ b/tileservermapping/slowtiles/views.py @@ -0,0 +1,46 @@ +from pathlib import Path + +from django.conf import settings +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.http import require_POST + +from tileservermapping.mapping.models import Server +from tileservermapping.slowtiles.models import SlowTiles + + +def insert_tile(request, z, x, y): + tile_count = SlowTiles.insert(z, x, y) + if tile_count < 0: + return HttpResponse("No server responsible", content_type='text', status=404) + return HttpResponse("Added: {}/{}/{} Count: {}\n".format(z, x, y, tile_count), content_type='text') + + +def get_server_list(request, z, x, y): + server = Server.get_server(z, x, y) + tiles = SlowTiles.objects.filter(server=server, count__gte=5) + answer = "" + for tile in tiles: + answer += "{}/{}/{}\n".format(tile.z, tile.x, tile.y) + return HttpResponse(answer, content_type='text') + + +def handle_uploaded_file(path, f): + with open(path, 'wb') as destination: + for chunk in f.chunks(): + destination.write(chunk) + +@require_POST +@csrf_exempt +def upload_tile(request, z, x, y, format): + # TODO auth oth server + # TODO check if tile in server + if not SlowTiles.objects.filter(x=x, y=y, z=z, count__gte=5).count(): + return HttpResponse('Tile should not be static\n', content_type="text", status=403) + path = Path(settings.TILE_WEBSERVER_DIR) / str(z) / str(x) + if not path.exists(): + path.mkdir(parents=True) + file = path / "{}.{}".format(y, format) + existed = file.exists() + handle_uploaded_file(file, request.FILES['tile']) + return HttpResponse('Updated\n' if existed else 'OK\n', content_type='text') diff --git a/tileservermapping/urls.py b/tileservermapping/urls.py index e72163e..794b46f 100644 --- a/tileservermapping/urls.py +++ b/tileservermapping/urls.py @@ -24,6 +24,7 @@ urlpatterns = [ + path('slow_tiles/', include('tileservermapping.slowtiles.urls')), path("api//", include("tileservermapping.mapping.urls")), path("mappings/", include("tileservermapping.mapping.urls")), # included for compatibility to old url schema