Пример #1
0
 /**
  * Initialize a semaphore that can be handled by the
  * functions provided by this class.
  * @throws ParamNotValidException
  * @return true if loading the semaphore was successful
  */
 public function load($sem = null)
 {
     if (strncmp(gettype($sem), "object", 6) == 0 && strncmp(get_class($sem), "core\\control\\Semaphore", strlen(get_class($sem))) == 0) {
         $this->semaphore = $sem;
         $this->semaphore->create();
         return true;
     } else {
         $this->log(__METHOD__ . ": %", array(new ParamNotValidException("sem(core\\control\\Semaphore)=" . StringUtil::get_object_value($sem))));
         throw new ParamNotValidException("sem(core\\control\\Semaphore)=" . StringUtil::get_object_value($sem));
     }
 }
Пример #2
0
 /**
  * Search for an element.
  * @param $index to search $skey at $kpos'th position regarding the 
  *        the element layout
  * @param $skey string key value to lookup at position $kpos
  * @param $kpos position to search for $skey
  * @param $kval value to compare the last serialized object with
  * @param $type search type, "native" or "avltree"
  * @return the first complete element found, otherwise an empty string
  */
 public function search($index = -1, $skey = "", $kpos = 0, $kval = null, $type = "native")
 {
     if (strncmp(gettype($type), "string", 6) == 0 && strncmp($type, "native", 6) == 0) {
         if (strncmp(gettype($index), "integer", 7) == 0 && strncmp(gettype($skey), "string", 6) == 0 && strncmp(gettype($kpos), "integer", 7) == 0) {
             // get the element stored at $index or all on failure
             $elems = "";
             if ($index > -1) {
                 $elems = $this->get($index);
             }
             // find first match for $skey at $kpos in $elems
             // and compare the last entry with $kval
             $dl = $this->element->get_shm_seg_var_eleft();
             $dr = $this->element->get_shm_seg_var_eright();
             foreach ($elems as $k => $v) {
                 // first check if there is an $skey
                 $mix = StringUtil::get_offset_first($dl . $skey . $dr, $v);
                 // if $skey was found
                 if ($mix !== -1) {
                     // substring length for the match
                     $sub = $substr($v, 0, $mix);
                     $sl = strlen($sub);
                     $c = 0;
                     // $sl could only be 0 if it is located at the
                     // first 0th position due to substr($v,0,0) is empty
                     // check if it is the correct $kpos and if left side delimiter(s)
                     // were found
                     $dlb = unpack("C*", $dl)[1];
                     // 91 for "["
                     $cc = count_chars($sub, 1);
                     if ($sl > 0 && array_key_exists($dlb, $cc)) {
                         if ($kpos === $cc[$dlb] - 1 && $kval === null) {
                             return $v;
                         } else {
                             if ($kpos === $cc[$dlb] - 1 && $kval === null) {
                                 // check the serialized version of $kval passed against the last
                                 // term of the current element, this check is optional but when
                                 // it is passed it need to be checked
                                 //$sv = $this->get_payload($k);
                                 $sv = $this->get_payload($v);
                                 if (strncmp($sv, serialize($kval), strlen($sv)) == 0) {
                                     return $v;
                                 }
                             }
                         }
                     } else {
                         $this->log(__METHOD__ . ": %", array(new DelimiterNotFoundException("'" . $dl . "', " . $sub)));
                         throw new DelimiterNotFoundException("'" . $dl . "', " . $sub);
                     }
                 }
             }
             return "";
         } else {
             $this->log(__METHOD__ . ": %", array(new ParamNotValidException("index(int)=" . gettype($index) . ", skey(string)=" . gettype($skey) . ", kpos(int)=" . gettype($kpos))));
             throw new ParamNotValidExcepton("index(int)=" . gettype($index) . ", skey(string)=" . gettype($skey) . ", kpos(int)=" . gettype($kpos));
         }
     } else {
         if (strncmp(gettype($type), "string", 6) == 0 && strncmp($type, "avltree", 6) == 0) {
             // TODO: probably use AVLTreeImplementation, see above $avltree
             // NOTE: probably just useful if there is a way to keep an already
             //       created avl object in a way restoring is not exhausting
         } else {
             $this->log(__METHOD__ . ": %", array(new ParamNotValidException("type(string)=" . gettype($type))));
             throw new ParamNotValidExcepton("type(string)=" . gettype($kpos));
         }
     }
 }
Пример #3
0
 /**
  * Function to flat several objects for logging. Arrays will be flattened.
  * For other objects there will be looked after a class method named 
  * __toString(). If no such method exists the object signature will be used.
  * @param object $obj object to flatte for logging.
  * @param boolean $debug indicates to get detailed information for $obj
  * @return string flattened object, its string representation or a unique id
  */
 public function flatten($obj = null, $debug = false)
 {
     $a = array();
     // NOTE: get_class_methods invokes autoloader for a string value
     if (is_object($obj) && strncmp(gettype(get_class_methods($obj)), "array", 5) == 0) {
         $a = get_class_methods($obj);
     }
     $ret = "";
     if (in_array("__toString", $a)) {
         $ret = $obj->__toString();
     } else {
         if (strncmp(gettype($obj), "array", 5) == 0) {
             $ret = StringUtil::get_object_string($obj);
         } else {
             if (strncmp(gettype($obj), "string", 6) == 0) {
                 $ret = $obj;
             } else {
                 if (strncmp(gettype($obj), "integer", 7) == 0) {
                     $ret = strval($obj);
                 } else {
                     if (is_null($obj)) {
                         $ret = "NULL";
                     } else {
                         if (is_object($obj)) {
                             $ret = get_class($obj) . spl_object_hash($obj);
                         }
                     }
                 }
             }
         }
     }
     if ($debug === true) {
         $ret = "OBJECT(" . StringUtil::get_object_string($obj) . ")=" . $ret;
     }
     // replace multiple whitespaces by a single one
     return $ret;
 }
Пример #4
0
 /**
  * Write $values to the shared memory segment in the form
  * '[val1][...][valn-1][serialize(valn)];'. Each value need
  * to match the memory layout related which is currently set 
  * for the segment.
  * @param $values array containing values
  * @param $key postion to write to. -1 means simply append.
  * @throws SegmentException
  * @return number of bytes written.
  */
 public function write($values = array(), $key = -1)
 {
     $written_data = 0;
     if (!is_null($this->element) && strncmp(gettype($values), "array", 5) == 0) {
         // build string to put first
         $pstr = "";
         $l = $this->element->get_shm_seg_var_eleft();
         $r = $this->element->get_shm_seg_var_eright();
         $d = $this->element->get_shm_seg_var_delimiter();
         foreach (array_values($values) as $k => $v) {
             if ($k == count($values) - 1) {
                 $pstr = $pstr . $l . serialize($v) . $r . $d;
             } else {
                 $pstr = $pstr . $l . $v . $r;
             }
         }
         $this->log(__METHOD__ . ": pstr=%, key=%", array($pstr, $key));
         // check it against the memory layout first
         $has_layout = false;
         if (!StringUtil::has_layout($this->element->get_shm_seg_layout(), $pstr)) {
             $this->log(__METHOD__ . ": %", array(new SegmentException("layout=" . $this->element->get_shm_seg_layout() . ", data=" . $pstr, 2)));
             throw new SegmentException("layout=" . $this->element->get_shm_seg_layout() . ", data=" . $pstr, 2);
         } else {
             $has_layout = true;
         }
         $woffset = -1;
         $has_space = false;
         // NOTE: concatenation of delimiter string needs to be done
         //       for performance reasons when it is necessary
         $smr = new SharedMemoryReader($this->element);
         // get the lenght of the current data stored
         $seglen = $smr->getlen();
         // segment type
         $segtype = $this->element->get_shm_seg_type();
         // get an indexable segment version
         $xseg = $smr->get();
         // unsetting the temporary element string
         $this->telement = "";
         $this->log(__METHOD__ . ": slen=%, len=%, type=%, cws=%", array($seglen, strlen($smr->read()), gettype($smr->read()), preg_replace("/[\t ]+/", " ", preg_replace("/[\r\n]/", " ", var_export(count_chars($smr->read()), true)))));
         // get the offset for simply appending
         if ($key == -1) {
             // space required
             $required = StringUtil::get_offset_last($r . $d, $pstr) + strlen($r . $d);
             // offset for next entry to put
             //$woffset = $this->element->get_shm_seg_size() - $seglen;
             $woffset = $seglen;
             // check the space left/needed before writing
             // fifo segment
             if (strncmp($segtype, "fifo", 4) == 0) {
                 // if the new fully entry does not fit into the segment we free some
                 // space according to the segment strategy but only if the new entry
                 // fits into the segment itself to avoid uneccessary flushing if the entry
                 // is to big for the empty segment
                 if (!($woffsef >= 0 && $woffset + $required <= $this->element->get_shm_seg_size()) && strlen($pstr) <= $this->element->get_shm_seg_size()) {
                     // fifo, free oldest entries first
                     $this->telement = $smr->read();
                     while (strlen($this->telement) > 0 && $woffset + $required > $this->element->get_shm_seg_size()) {
                         // get the next entry to discard
                         $discardoffset = StringUtil::get_offset_first($r . $d, $this->telement) + strlen($r . $d) - 1;
                         // free
                         $this->telement = substr($this->telement, $discardoffset);
                         // recalc free space
                         $woffset = $this->element->get_shm_seg_size() - strlen($this->telement);
                     }
                     $has_space = true;
                     // otherwise there is something wrong with the space
                 } else {
                     $has_space = false;
                     $this->log(__METHOD__ . ": %", array(new SegmentException("freeing failed", 0)));
                     throw new SegmentException("freeing failed", 0);
                 }
                 // lifo segment
             } else {
                 if (strncmp($segtype, "lifo", 4) == 0) {
                     // stor segment
                 } else {
                     if (strncmp($segtype, "stor", 4) == 0) {
                         // simply check if there is still place left to push elements
                         if ($seglen + strlen($pstr) <= $this->element->get_shm_seg_size()) {
                             $has_space = true;
                         } else {
                             $this->log(__METHOD__ . ": %", array(new SegmentException("no more space", 1)));
                             throw new SegmentException("no more space", 1);
                         }
                     }
                 }
             }
             // writing to a specific index is a bit more complex
             // get the offset for writing to an index
         } else {
             if (strncmp(gettype($key), "integer", 7) == 0 && $key > -1) {
                 // if its a valid key
                 if ($key <= count($xseg) - 1) {
                     // calculate new minimum length for data stored
                     $segnlen = $seglen - strlen($xseg[$key] . $this->element->get_shm_seg_var_eright() . $this->element->get_shm_seg_var_delimiter()) + strlen($pstr);
                     // auto free space for fifo/lifo segment types if there is no more
                     // space left
                     // fifo segment
                     if (strncmp($segtype, "fifo", 4) == 0) {
                         // if the new segment data length is to big
                         if ($segnlen > $this->element->get_shm_seg_size()) {
                             $difflen = $segnlen - $this->element->get_shm_seg_size();
                             $tmp_key = 0;
                             while ($difflen > 0) {
                                 $difflen -= strlen(trim($xseg[$tmp_key]) . $this->element->get_shm_seg_var_eright() . $this->element->get_shm_seg_var_delimiter());
                                 unset($xseg[$tmp_key]);
                                 $tmp_key += 1;
                                 // increase it as unset doesn't modify indexes
                             }
                         }
                         // after cleaning the fifo queue there should be enough space
                         $has_space = true;
                         // lifo segment
                     } else {
                         if (strncmp($segtype, "lifo", 4) == 0) {
                             // if the new segment data length is to big
                             if ($segnlen > $this->element->get_shm_seg_size()) {
                                 $difflen = $segnlen - $this->element->get_shm_seg_size();
                                 $tmp_key = count($xseg) - 1;
                                 while ($difflen > 0) {
                                     $difflen -= strlen(trim($xseg[$tmp_key]) . $this->element->get_shm_seg_var_eright() . $this->element->get_shm_seg_var_delimiter());
                                     unset($xseg[$tmp_key]);
                                     $tmp_key -= 1;
                                     // increase it as unset doesn't modify indexes
                                 }
                             }
                             // after cleaning the lifo queue there should be enough space
                             $has_space = true;
                             // if the segment type is 'stor' simply try to store it or throw an
                             // exception if the length do not fit
                         } else {
                             if (strncmp($segtype, "stor", 4) == 0) {
                                 // if the modified length is less or equal the segment size
                                 // simply write it
                                 if ($segnlen <= $this->element->get_shm_seg_size()) {
                                     $has_space = true;
                                 } else {
                                     $has_space = false;
                                     $this->log(__METHOD__ . ": %", array(new SegmentException("no more space", 1)));
                                     throw new SegmentException("no more space", 1);
                                 }
                             }
                         }
                     }
                 }
             } else {
                 $this->log(__METHOD__ . ": %", array(new ParamNotValidException(__METHOD__ . ": key(int)=" . var_export($key, true))));
                 throw new ParamNotValidException(__METHOD__ . ": key(int)=" . var_export($key, true)) . "\n";
             }
         }
         // write it using shmop_write
         if ($has_layout && $has_space && $woffset > -1 && $this->element->get_shm_seg_id() > -1) {
             // TODO: WriterThread to allow multiple writes on different
             //       but "correctly calced" locations/offsets
             $this->log(__METHOD__ . ": tel=%, tels=%, pstr=%, pstrs=%, els=%, " . "woff=%, woff+lpstr=%, segs-(woff+lpstr)=%", array($this->telement, strlen($this->telement), $pstr, strlen($pstr), $this->element->get_shm_seg_size(), $woffset, $woffset + strlen($pstr), $this->element->get_shm_seg_size() - ($woffset + strlen($pstr))));
             // write modified prefix
             $written_prefix = shmop_write($this->element->get_shm_seg_id(), $this->telement, 0);
             // write additional entry from offset
             $written_data = shmop_write($this->element->get_shm_seg_id(), $pstr, $woffset);
             // write additional entry from offset
             // TODO: only write flush/whitespace pad for overlapping bytes at reduction
             $written_flush = shmop_write($this->element->get_shm_seg_id(), str_pad("", $this->element->get_shm_seg_size() - ($woffset + strlen($pstr)), " "), $woffset + strlen($pstr));
             $this->log(__METHOD__ . ": wp=%, wd=%, wf=%", array($written_prefix, $written_data, $written_flush));
             if ($written_prefix === false || $written_data === false || $written_flush === false) {
                 $this->log(__METHOD__ . "%", array(new SegmentException($this->element, 4)));
                 throw new SegmentException($this->element, 4);
             }
         }
     }
     // close if
     return $written_data;
 }
Пример #5
0
 /**
  * Set the segment type. Currently supported types be SharedMemoryWriter
  * are 'stor', 'fifo', 'lifo'.
  * @param $seg_type segment type
  */
 public function set_shm_seg_type($seg_type = "stor")
 {
     if (in_array($seg_type, $this->shm_seg_supported_types, true)) {
         switch ($seg_type) {
             case "stor":
                 $this->shm_seg_type = "stor";
                 break;
             case "fifo":
                 $this->shm_seg_type = "fifo";
                 break;
             case "lifo":
                 $this->shm_seg_type = "lifo";
                 break;
             default:
                 $this->shm_seg_type = "stor";
                 break;
         }
     } else {
         $this->log(__METHOD__ . ": %", array(new SegmentException(StringUtil::get_object_string($seg_type), 3)));
         throw new SegmentException(StringUtil::get_object_string($seg_type), 3);
     }
 }