Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#8

Re: Paradox-DB: ständig Index-Fehler

  Alt 25. Mai 2005, 09:52
Wenn Du mit dBase zufrieden bist... Wieso migrierst du nicht einfach auf die MSDE... Man muss ja nicht gleich alle features nutzen?

Zu Deinem Problem mit dem Exklusivzugriff: Du kannst ja bei einem Fehler eine Message an alle Nutzer schicken (per 'mail' broadcast). Die kappen die Verbindung, Du reparierst den Müll, dann eine Mail, das Du fertig bist und fertig...

Zum Thema mail (geht nur bei Domänen, soweit ich weiss):
Der Empfänger erzeugt ein mail-hande, indem er ein 'mailslot' mit irgendeinem Namen (Hier: "Client") erzeugt.
Delphi-Quellcode:
Procedure TMailReceiver.CreateMailSlot;
Begin
  aPath := '\\.\mailslot\Client';
  fHandle := CreateMailSlot(PChar(aPath), 0, MAILSLOT_WAIT_FOREVER, nil);
End;
Offiziel geht der Empfang so: Ich eröffne den mailslot *nicht* mit MAILSLOT_WAIT_FOREVER, sondern mit einem Timeout und schaue dann immer wieder nach, ob was angekommen ist. Die Anzahl der Bytes wird zurückgeliefert. Dann hole ich die Daten ab. Das hat den Vorteil, das ich beliebig lange Nachrichten verschicken kann, aber den Nachteil, das ich eben 'pollen' muss.

Ich mache das Anders: Ich setze mich einfach auf das Handle und vereinbare eine maximale Länge. Sobald was angekommen ist, weiss ich auch, wieviele Bytes die Nachricht enthält...
Delphi-Quellcode:
procedure TMailReceiver.Execute;
Var
  aSize : DWord;

begin
  While Not Terminated Do Begin
    SetLength (fMessage, fMaxLength); // fMessage ist ein privates String-Feld...
    if ReadFile(fHandle, PChar(fMessage)^, fMaxLength, aSize, nil) Then Begin
      If not terminated Then Begin
   SetLength (fMessage, aSize);
        Synchronize (DoOnMailReceived);
        End
    End
end;
Der Sender macht Folgendes:
Delphi-Quellcode:
Procedure SendMail (aComputer, aSlotName, aMessage : String);
var
  Bytes: DWord;
  aPath : String;
  aHandle : THandle;

begin
  If aComputer = 'Then Exit;
  aPath := '\\' + aComputer + '\mailslot\' + aSlotName;
  aHandle := CreateFile(PChar(aPath), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  try
    if aHandle = INVALID_HANDLE_VALUE then
      If aComputer='*Then
        SendMail('.',aSlotName, aMessage)
      Else
        Raise EInOutError.CreateFmt('Cannot create mailslot %s\%s',[aComputer,aSlotName])
    else
      If not WriteFile(aHandle, Pointer(aMessage)^, Length(aMessage), Bytes, nil) Then
        If aComputer='*Then
          SendMail('.',aSlotName, aMessage)
        Else
          Raise EInOutError.CreateFmt('Cannot write to mailslot %s\%s',[aComputer,aSlotName]);
  finally
    if aHandle <> INVALID_HANDLE_VALUE Then
      CloseHandle(aHandle);
    end;
end;
Wenn ich als Computernamen ein '*' übergebe, wird die Nachricht an ALLE Computer in der Domäne verschickt. Um also, an den Computer 'FOO' (der ein mailslot mit Namen 'BAR' erzeugt hat und wartet...) eine Nachricht zu schicken, rufe ich einfach
"Sendmail ('FOO','BAR','Hello foo')" auf. Um eine Nachricht an ALLE Computer zu schicken, benutze ich "Sendmail ('*','BAR','Hello foo')".

Bevor ich hier gepeitscht werde: Es geht auch mit UDP, aber ich habs nunmal mit den mailslots gemacht
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat