Schreibschutz einer Datei
DeWitt
- perl
0 DeWitt
--
selfcode ie:% fl:( br:< va:) ls:} fo:| rl:( n4:° ss:) de:] js:| ch:] sh:( mo:| zu:(
<< Life is just a moment in eternity, yet every life echoes there >>
(Sry, hab grad beim Schreiben des Betreffs aus Versehen Return gedrückt...
Also zweiter Versuch:)
Ich benutze ein objektorientiert aufgebautes Package, um Dateien zu öffnen und deren Inhalt zu verarbeiten. Im Konstruktor-Modul wird der Datei-Inhalt in einem Array ausgelesen, auf das dann in den Objekt-Eigenschaften referenziert wird, sodass andere Methoden auf die Daten zugreifen können. Zuletzt soll der Inhalt der Datei bei Bedarf neu geschrieben werden.
Nun möchte ich natürlich die Datei in der Zeit, in der das Objekt darauf zugreift, für Schreib-Zugriffe sperren. Wenn ich dies jedoch über FLOCK realisiere, wird der Schreibschutz wieder deaktivert, sobald die Konstruktor-Funktion ausgeführt wurde (selbst wenn ich die Datei nicht explizit wieder schließe).
Gibt es andere/bessere Möglichkeiten außer FLOCK, um eine Datei temporär zu sperren?
Moin!
Nun möchte ich natürlich die Datei in der Zeit, in der das Objekt darauf zugreift, für Schreib-Zugriffe sperren. Wenn ich dies jedoch über FLOCK realisiere, wird der Schreibschutz wieder deaktivert, sobald die Konstruktor-Funktion ausgeführt wurde (selbst wenn ich die Datei nicht explizit wieder schließe).
Gibt es andere/bessere Möglichkeiten außer FLOCK, um eine Datei temporär zu sperren?
Du kannst innerhalb deiner Applikation natürlich jeden anderen Mechanismus, der zum gleichen Resultat kommt, implementieren. Entweder führst du eine zentrale Liste der gesperrten Dateien, oder arbeitest je Datei mit Semaphoren, oder oder oder...
Deine Vorgehensweise ist allerdings bedenklich. Während der gesamten Zeit, in der dein Objekt die Datei geöffnet hält (egal ob am Ende geschrieben wird oder nicht) darf kein anderer Prozess auf die Datei zugreifen, nicht einmal lesend. Das wird die erreichbare Performance ganz erheblich behindern, weil du dir einen künstlichen Flaschenhals baust.
Vielleicht solltest du lieber darlegen, was du da genau bauen willst - die Forumsteilnehmer sind kreativ, was das Erstellen von alternativen Lösungen angeht, solange die Möglichkeiten bekannt sind.
- Sven Rautenberg
Vielleicht solltest du lieber darlegen, was du da genau bauen willst - die Forumsteilnehmer sind kreativ, was das Erstellen von alternativen Lösungen angeht, solange die Möglichkeiten bekannt sind.
Im Endeffekt will ich eine Art eigenes "Datenbank-System" erstellen. Klar, mySQL ist heutzutage wohl das Non-Plus-Ultra, aber ich wollte das ganze eben mal selbst implementieren, in erster Linie zur Übung und aus Interesse bzw. um die auftretenden Problematiken zu verstehen.
Ich kann mein Modul gerne mal detailliert beschreiben, aber das wird natürlich ein bißchen länger ;). Ich stelle hier mal einen kleinen Auszug rein, der beschreibt, wie ich das Modul momentan verwende:
#Accounts auslesen
$accounts = database -> openFile($db) || die $@;
#Prüfen ob Account bereits existiert
die $@ unless defined (my @accnames = $accounts->getAll("Accname eq \"$useracc\"",'Accname') );
if ($#accnames >= 0) {$acc_exists = 1;}
#Fehlermeldung wenn Account bereits existiert
if ($acc_exists) {
$error = "Der gewünschte Accountname existiert bereits. Bitte wählen Sie einen anderen Account.";
}
unless ( defined($error) ) {
# Datensatz erstellen und schreben
my %data = (
Schlüssel1 => "Wert1",
Schlüssel2 => "Wert2",
#usw.
);
my $accno = $accounts -> newSet(%data) || die $@;
$accounts -> dbWrite() || die $@;
}
Beschreibung:
Falls es jemand interessiert, hier eine HTML-Darstellung meiner POD-Dokumentation des Moduls.
Das ist also mein erster Ansatz. Allerdings habe ich eben das erwähnte Schreibschutz- und Flaschenhals-Problem.
Meine Überlegung ist jetzt, im Aufruf der Konstruktor-Funktion über einen zusätzlichen Parameter festzulegen, ob auf die Datenbank nur lesend oder auch schreiben zugegriffen werden soll. Auf diese Weise können beliebig viele Prozesse die Datei lesen, während nur ein Prozess zur selben Zeit Änderungen durchführen kann.
Kurze Frage an dieser Stelle: Habe ich das richtig verstanden, dass mittels FLOCK(DATA, 1) die Datei zum lesen weiterhin freigegeben ist, allerdings nur das aktuelle Script Schreibzugriff hat?
Beispiel:
# Auslesen nicht erfolgreich
unless ( open(DATA,"+<$url") && flock(DATA, 1) ) {
$@ = "Die Datenbank '$url' konnte nicht geöffnet werden. Grund: $!";
return undef;
}
# Auslesen erfolgreich
else {
# Auf Datei zugreifen...
}
Moin!
Im Endeffekt will ich eine Art eigenes "Datenbank-System" erstellen. Klar, mySQL ist heutzutage wohl das Non-Plus-Ultra, aber ich wollte das ganze eben mal selbst implementieren, in erster Linie zur Übung und aus Interesse bzw. um die auftretenden Problematiken zu verstehen.
MySQL ist nicht das Non-plus-Ultra.
Und du arbeitest im Moment auch nicht an etwas ähnlichem, wie MySQL, sondern an etwas ähnlichem, wie der BerkeleyDB oder SQLLite - nämlich einem System, welches nur eine zentrale Speicherdatei kennt, die Zugriffe aber dezentral über jeweils eingebundene Bibliotheksmodule realisiert, und dabei natürlich gegenseitige Schreibzugriffe gegeneinander abschotten muß.
In dieser Hinsicht solltest du erst mal recherchieren. Stichworte, die ich dazu schon genannt hatte: "Semaphoren". "Locking-Konzepte".
Die Datenstruktur in der Datei ist ebenfalls relevant, denn eine Datenbank mit festen Feldlängen ist wesentlich berechenbarer und kann problemlos von verschiedenen Prozessen an unterschiedlichen Stellen parallel beschrieben werden, als wenn sich die Länge der gespeicherten Strings andauernd ändert, und somit die Datei auch andauernd komplett neu geschrieben werden muß.
Alternativ zu diesem dateibasierten Ansatz gibt es natürlich die Alternative, genau wie MySQL und alle anderen Datenbanken ein Serverprogramm zu schreiben, welches die komplette Kontrolle über die Daten behält und dadurch alles Locking intern zentral verwalten kann, sofern erforderlich. Die Kommunikation erfolgt dann nur über eine definierte Schnittstelle.
Du hast dir mit dieser Aufgabe allerdings wirklich ein Riesenstück Arbeit vorgenommen. Und ich bin sicher, dass es zu Lernzwecken vielleicht ganz interessant ist, sich für den produktiven Einsatz aber ab irgendeinem Punkt nicht mehr eignet. Du solltest dir also die Frage stellen, ob du dich wirklich zu einem Spezialisten für Datenbankherstellung entwickeln willst, oder ob es nicht ausreicht, dich zu einem Spezialisten für Datenbankbenutzung zu entwickeln.
Denn wären Datenbanken so einfach zu programmieren, wie Texteditoren, gäbe es nicht nur zwei Handvoll Datenbanksysteme - im Gegensatz zu hunderttausend Texteditoren. ;)
- Sven Rautenberg
Ich benutze ein objektorientiert aufgebautes Package, um Dateien zu öffnen und deren Inhalt zu verarbeiten. Im Konstruktor-Modul wird der Datei-Inhalt in einem Array ausgelesen, auf das dann in den Objekt-Eigenschaften referenziert wird, sodass andere Methoden auf die Daten zugreifen können. Zuletzt soll der Inhalt der Datei bei Bedarf neu geschrieben werden.
Nun möchte ich natürlich die Datei in der Zeit, in der das Objekt darauf zugreift, für Schreib-Zugriffe sperren. Wenn ich dies jedoch über FLOCK realisiere, wird der Schreibschutz wieder deaktivert, sobald die Konstruktor-Funktion ausgeführt wurde (selbst wenn ich die Datei nicht explizit wieder schließe).
Das sollte nicht passieren, dann machst du etwas falsch.
Gibt es andere/bessere Möglichkeiten außer FLOCK, um eine Datei temporär zu sperren?
andere schon, besser nicht.
Struppi.