Anzahl von Buffern in IPS(-Modulen) begrenzt?

Hi!

Kurze Frage zu Buffern ($this->SetBuffer) in IPS-Modulen…
Gibt es da eine allgemeine Begrenzung wie viele Buffer man von der Anzahl her verwenden kann, oder kann ich auch z.B. 5000 verschiedene Buffer über alle meine IPS-Module hinweg verwenden?
Sonstiges was man bei dem Thema beachten sollte an Limits oder was auch immer?

Danke und Grüße,
Chris

PS: Die Limits für einen Buffer sind mir bekannt (8kb soft, 64kb hard).

Es gibt keine Begrenzung. Du kannst du viele Puffer erstellen wie du willst. Bisher nur leider nicht „Löschen“. Du kannst diese nur „leeren“.

paresy

Gilt ja nicht für alle Module. Immer pro Instanz und eine Grenze pro Instanz kenne ich nicht.
So 20-30 habe ich bestimmt in Verwendung, je nach Modul. Einige eher klein, nur eine einstellige Zahl, andere ‚riesig‘ enthalten ganze Objekte als gesplitteten String.
Wobei ich schon darauf achte nicht über 64k zu kommen :wink:

@Paresy, reicht denn leeren ?
Das ist aktuell mein Vorgehen wenn ein ‚Objekt‘ Buffer kleiner wird.
Michael

Danke für die Info. Das mit dem Leeren ("") mache ich auch. Habe auch hauptsächlich einstellige Zahlen drin, aber es werden viiiiiele beim aktuellen Modul.

Noch eine Nachfrage - Nall chan, es klingt bei deinem Post so, als könnte ich mit Modul B nicht auf den Buffer-Wert zugreifen der durch Modul A gesetzt wurde? :confused:

Die 8kb und 64kb gelten pro Modul oder pro gesetzt Buffer-Wert?

Grüße,
Chris

Jedes Modul hat seine eigene… genauer noch:
Jede Instanz in IPS aus deinem Modul hat seine eigenen Buffer.
Das impliziert ja schon das $this-> bei den Methoden SetBuffer und GetBuffer :wink:

Wozu sollte man auch darauf direkt zugreifen? Dann wäre eine Instanz ja von ‚außen‘ angreifbar.
Wenn, dann funktioniert das nur so wie immer; über den Datenaustausch.

Pro Buffer.

Michael

Hmmmm…ok…is logisch :smiley: Aber kein Problem, habe schon ein Lösung für meinen Fall :slight_smile:

Danke!

-Chris-

Im Normalfall ja. Da es für den leeren String einen gewissen „Overhead“ gibt, könnte man bei einer unendlichen Zahl an leeren Puffern ein Speicherleck erzeugen. Ist aber eher sehr weit hergeholt.

paresy

Noch eine Frage bzw. wohl eher ein Feature-Request…

Gibt es eine Möglichkeit alle gesetzten Buffer innerhalb eines Modules zu ermitteln? Quasi im Modul etwas wie „$BuffernamesArray = $this->GetAllBuffer()“ und dann bekommt man eine Liste mit allen Buffer-Namen die grad durch die Instanz gesetzt wurden?

Aktuell muss ich immer bei einer Buffer-Änderung/Erstellung, die ich nach einem IPS-Neustart noch brauche, diese in eine Variable schreiben und beim IPS-Start wieder auslesen und neu in den Buffer schreiben. Dazu muss ich erst den Inhalt der Variable auslesen, prüfen ob der Buffer schon drin ist, wenn ja ändern, wenn nein hinzufügen. Funktioniert, finde ich aber eher unschön.
Da würde ich lieber alle aktuell gesetzten Buffer-Namen auslesen mit einer Funktion, durch eine foreach Schleife laufen lassen, dabei selektieren was ich brauche und einfach die Variable(n) neu setzen.

Grüße,
Chris

Das Thema mit persistente Daten nach einen Neustart hatten wir schon öfters. Keine Ahnung wie die Lösungen dort waren…

Buffer sind dafür ja nicht geeignet und gedacht.
Hatte selber bisher noch nie einen Fall wo ich Daten (außer die Einstellungen) behalten musste.
In der Regel werden diese Daten beim IPS-Start einfach neu aus der angeschalteten HW / SW ausgelesen.

Die Liste mit den Buffern führe ich selber.
Dort wo ich, aufgrund der zu großen Datenmenge, dynamisch Buffer belege, speichere ich einfach deren Namen in einem Array.
Dieses Array liegt dann auch wieder in einem Buffer ^_^;

Aber den Kram behalten… mal schauen wann mich das auch mal trifft.
Bisher schreibe ich alles was geht in die Settings.

Michael

Hmmm…das mit dem Array wo nur die Buffer-Namen drin sind und das in einem extra Buffer speichern ist gar kein so schlechter Workaround :slight_smile: Damit man schnell prüfen, gut verarbeiten und muss nur an die Variable wenn notwendig…
Wenn mir da die 64kb vom Platz ausreichen, dann ist das ein guter Tipp :cool:

Hast du vlt. auch noch eine Idee, wie ich prüfen kann wie groß/voll ein Buffer ist und wenn ein Buffer am Limit ist, dann auf einen 2. Buffer swappen usw? :smiley: Da würde ich mir einfach ans Ende vom Buffer dann einen Marker setzen, dass danach noch ein weiterer Buffer folgt…

Ich nutze für die Buffer __get und __set.
Aktuell auch ‚etwas‘ böse, da theoretisch diese ‚Eigenschaften‘ der Instanz public sind.
In diesen magischen Methoden wird beim setzen geprüft ob die Länge größer 8000 Byte sind und dann ein weiterer benutzt.
Die eventuelle negative Differenz an Buffern werden geleert.

Die Unterscheidung ob es ein einzelner oder eine Gruppe von Buffern sind, mache ich am Namen fest.
Alles was mit Multi_ beginnt sind ein Array von Buffer.

/**
 * Trait welcher Objekt-Eigenschaften in den Instance-Buffer schreiben und lesen kann.
 */
trait BufferHelper
{

    /**
     * Wert einer Eigenschaft aus den InstanceBuffer lesen.
     * 
     * @access public
     * @param string $name Propertyname
     * @return mixed Value of Name
     */
    public function __get($name)
    {
        if (strpos($name, 'Multi_') === 0)
        {
            $Lines = "";
            foreach ($this->{"BufferListe_" . $name} as $BufferIndex)
            {
                $Lines .= $this->{'Part_' . $name . $BufferIndex};
            }
            return unserialize($Lines);
        }
        return unserialize($this->GetBuffer($name));
    }

    /**
     * Wert einer Eigenschaft in den InstanceBuffer schreiben.
     * 
     * @access public
     * @param string $name Propertyname
     * @param mixed Value of Name
     */
    public function __set($name, $value)
    {
        $Data = serialize($value);
        if (strpos($name, 'Multi_') === 0)
        {
            $OldBuffers = $this->{"BufferListe_" . $name};
            if ($OldBuffers == false)
                $OldBuffers = array();
            $Lines = str_split($Data, 8000);
            foreach ($Lines as $BufferIndex => $BufferLine)
            {
                $this->{'Part_' . $name . $BufferIndex} = $BufferLine;
            }
            $NewBuffers = array_keys($Lines);
            $this->{"BufferListe_" . $name} = $NewBuffers;
            $DelBuffers = array_diff_key($OldBuffers, $NewBuffers);
            foreach ($DelBuffers as $DelBuffer)
            {
                $this->{'Part_' . $name . $DelBuffer} = "";
            }
            return;
        }
        $this->SetBuffer($name, $Data);
    }

}

/**
 * @property Nodes $Multi_AllNodes 
 * @property string $Multi_String
 */
class PlugwiseNetwork extends IPSModule
{

    use BufferHelper;

    /**
     * Interne Funktion des SDK.
     *
     * @access public
     */
    public function Create()
    {
        parent::Create();
        $this->Multi_AllNodes = new Nodes(); // Objekt
        $this->Multi_String = "" ; // String
    }

    protected function YourFunction()
    {
        $Nodes = $this->Multi_AllNodes; // Objekt aus Buffer holen.
        $this->Multi_String = '1234567865asdfghjgfd' // String in Buffer schreiben.
    }
/* your code here */
}

Michael

Das mit den public functions finde ich jetzt nicht so dramatisch. Das dürfte bei den wenigstens Leuten ein Problem sein…und für meine aktuelle Projekte ist das zum Glück auch gar kein Problem.

Der „Trick“ mit „str_split($Data, 8000);“ ist gut :smiley: Du hast aber auch immer Ideen :smiley: :cool: Danke!

-Chris-