[PHP] INI Class probleem

Pagina: 1
Acties:
  • 150 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo,

Aangezien er nog geen class was voor INI Files ben ik er zelf maar een gaan schrijven. Alle functies werken maar er is één belangrijk probleem. Mijn class gebruikt buffering om de snelheid te vergroten. Bij de functie $ini->connect("file.ini"); wordt alle data uit het bestand gehaald en in een Array geplaatst, pas bij de functie $ini->close($link_identifer); wordt alle data naar het bestand teruggeschreven.

Maar dan nu het grote probleem:

Waneer twee mensen tegelijk, hetzelfde bestand willen aanpassen ontstaan er problemen.

Voor het gemakt zat ik de twee gebruikers X en Y noemen.

[example]

Inhoud van test.ini:

[gegevens]
voornaam=Piet
achternaam=Heijn

X opent het bestand "test.ini"
Y opent het bestand "test.ini"

Tot zover geen problemen, zowel X als Y hebben dezelfde buffer.
Maar dan gaat zowel X als Y veranderingen doorvoeren.

X veranderd de voornaam in Klaas. zijn buffer is nu:
[gegevens]
voornaam=Klaas
achternaam=Heijn

Y veranderd de achternaam in Kaas. Zijn buffer is nu:
[gegevens]
voornaam=Piet
achternaam=Kaas

Als nu eerst X de gegevens wegschrijft en daarna Y dan worden de aanpassingen van X overschreven door die van Y.

[/example]

Zoals jullie zien schuilt hier dus een groot probleem in. Ik heb al enkele dagen nagedacht over een oplossing, maar ik kan er geen vinden (geen goede...).

Als een van jullie een goede oplossing weet, vertel het me, want ik wordt gek.

Alvast bedankt

Acties:
  • 0 Henk 'm!

Verwijderd

Ik zou niet willen dat twee personen hetzelfde bestand KUNNEN openen in die situatie. Dus in jouw voorbeeld:

A probeert bestand te openen
-> gelukt
B probeert bestand te openen
-> niet gelukt (error: bestand nog in gebruik)

Hoe dit op te lossen in je code?
Neem bijv het volgende op in je $ini->connect en close functie:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function connect($file) {
  if (file_exists($file . "_lock")) {
     produceError("File is locked. No access allowed.");
  }
  else {
     $array = open($file);
     writeToFile($file . "_lock","1");
  }
}

function close($file) {
  unset($file . "_lock");
  writeToFile($file, $array);
}

* Een paar functies bestaan niet in bovenstaand voorbeeld, maar you get the picture neem ik aan. Bij het proberen te openen van je bestand, checkt de functie of er niet een bestand is dat gelijk is aan $file + _lock. Indien het geval, geef dan een foutmelding "bestand bezet". Indien het bestand niet bestaat, dan kun je de ini file openen, en maak je een lock bestand erbij aan.

Hoop dat dat wat helpt.

Acties:
  • 0 Henk 'm!

Verwijderd

En ik bedoel trouwens unlink, niet unset :)

Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Verwijderd schreef op 16 november 2002 @ 10:27:
* Een paar functies bestaan niet in bovenstaand voorbeeld, maar you get the picture neem ik aan. Bij het proberen te openen van je bestand, checkt de functie of er niet een bestand is dat gelijk is aan $file + _lock. Indien het geval, geef dan een foutmelding "bestand bezet". Indien het bestand niet bestaat, dan kun je de ini file openen, en maak je een lock bestand erbij aan.
Concurrency control! :) Hier krijg je dus zeker race situaties in.
Stel je voor dat user A en user B vlak na elkaar dezelfde file willen openen.

A doet een connect( ) en doorloopt de if, komt bij de else en opent de file en leest hem in de array. Echter dan besluit het OS dat de timeslice van de thread die A afhandelt voorbij is en geeft de beurt aan B
B doet hetzelfde en schrijft ook de lockfile nog

Hierna is na een tijd A weer aan de beurt. A schrijft ook nog een lockfile'tje en ze zijn beide in de veronderstelling dat alles OK is :)

Dit soort problemen blijf je houden totdat je een optie krijgt om een functie compleet synchronized te maken (niet te accessen zodra een thread hem aanroept)

Acties:
  • 0 Henk 'm!

Verwijderd

Da's inderdaad tot op diehard niveau :)
Het probleem is in ieder geval een klein beetje ingedamd zo.
Je zou dan ook natuurlijk nog een check kunnen inbouwen die voor het wegschrijven van je ini array naar ini file, je oorspronkelijke, onbewerkte, array vergelijkt met de inhoud van het bestand. Is het anders, dan zijn er toch nog 2 of meer users doorheen geglipt, en kun je alsnog een foutmelding produceren (of bijv de optie, net als in een ontwikkelomgeving of zo, "wilt u het veranderde bestand opnieuw laden, of overschrijven zonder opnieuw te laden?").

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb net een uurtje op de bank liggen denken en ben tot de volgende oplossing gekomen.
(Hij lijkt op die van talk2me)

Ik zorg dat twee mensen niet tegelijk hetzelfde bestand kunnen openen. Ik houd een soort wachtrij bij. Tijdens het connecten wacht de functie net zo lang tot dat hij aan de beurt is. Zo voorkom je dat 2 dingen tegelijk gebeuren.

Ziet niemand problemen in deze oplossing? Of heb je dan nog steeds hetzelfde probleem als van talk2me???

Acties:
  • 0 Henk 'm!

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Kijk, als php/apache nou een shared memory functionaliteit zou hebben, dan zou je een shared functie kunnen maken die alles afhandeld. Daar is dus dan maar 1 instantie van, en 1 functie die alles inleest en eventueel cached. :)

Acties:
  • 0 Henk 'm!

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Verwijderd schreef op 16 november 2002 @ 11:05:
Ik zorg dat twee mensen niet tegelijk hetzelfde bestand kunnen openen. Ik houd een soort wachtrij bij. Tijdens het connecten wacht de functie net zo lang tot dat hij aan de beurt is. Zo voorkom je dat 2 dingen tegelijk gebeuren.
• Je zal toch een lockfile moeten schrijven dan, anders kan B nog openen nadat A geopend heeft
• Je rij moet applicatie globaal zijn. Hoe ga je dat doen?

http://www.php.net/manual/en/ref.shmop.php kan, maar is niet echt een oplossing imho

Acties:
  • 0 Henk 'm!

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12:56
staat er op http://www.phpfreakz.com niet een kant en klaar script in de script library?

Acties:
  • 0 Henk 'm!

Verwijderd

Use the flock

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dat script heb ik gemaakt djluc :)

Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Rustacean


Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Voor het wegschrijven checken of de file bewerkt is door een ander (met bijvoorbeeld een CRC ofzo) is geen oplossing?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

Verwijderd

Ik zou even kijken naar de concurrency control methoden die SQL gebruikt....
'lost update problem', 'uncommitted dependency problem' en 'iconsistent analysis problem'

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Manuzhai: Ja ik ken die functie en die functie gebruik ik ook tijdens de functie connect();

Allemaal bedankt voor jullie reacties, het probleem is nu opgelost. Het script werkt nu met een wachtrij. De timelimit wordt op 0 gezet, voor het geval dat het wachten langer dan 30 seconden duurt.

Acties:
  • 0 Henk 'm!

  • kvdveer
  • Registratie: November 2000
  • Laatst online: 07-11-2023

kvdveer

Z.O.Z.

PHP heeft gewoon lockingfunctions hoor... Die kun je prima gebruiken voor dit soort doeleinden.

Localhost, sweet localhost

Pagina: 1