function recordStat($data, $update = false)
 {
     global $db, $repository, $sotfVars;
     $type = $data['type'];
     if ($type != 'listens' && $type != 'downloads' && $type != 'visits') {
         raiseError("addStat: type should be 'listens' or 'downloads' or 'visits'");
     }
     // update periodic stat
     $date = $data['date'];
     //debug("date", $db->getTimestampTz($date));
     $now = getdate($date);
     //debug("now", $now);
     $year = $now['year'];
     $month = $now['mon'];
     $day = $now['mday'];
     $week = date('W', $date);
     $prgId = $data['prog_id'];
     $fileId = $data['file'];
     $where = " WHERE prog_id='{$prgId}' AND year='{$year}' AND month='{$month}' AND day='{$day}' AND week='{$week}'";
     $prg = $repository->getObject($prgId);
     if (!$prg) {
         // don't raiseError("addStat: no such programme: $prgId");
         return null;
     }
     $db->begin();
     // to avoid deadlocks I try this:
     $db->query("LOCK TABLE sotf_stats, sotf_unique_access, sotf_to_update IN ROW EXCLUSIVE MODE");
     $id = $db->getOne("SELECT id FROM sotf_stats {$where}");
     if ($id) {
         $obj = new sotf_Statistics($id);
         $obj->set($type, $obj->get($type) + 1);
         // station may change!!
         $obj->set('station_id', $prg->get('station_id'));
     } else {
         $obj = new sotf_Statistics();
         $obj->setAll(array('prog_id' => $prgId, 'station_id' => $prg->get('station_id'), 'year' => $year, 'month' => $month, 'week' => $week, 'day' => $day, $type => 1));
     }
     if ($obj->exists()) {
         $obj->update();
     } else {
         $obj->create();
         //debug("obj1", $obj);
         $obj->find();
         // to get the id
         //debug("obj2", $obj);
     }
     // update uniqueness memory
     sotf_Statistics::addUniqueAccess($data['ip'], $prgId, $fileId, $type);
     // would be too often:
     if ($update) {
         $obj->updateStats(false);
     } else {
         sotf_Object::addToUpdate('sotf_stats', $obj->id);
     }
     $db->commit();
     return $obj;
 }
 /** static */
 function doUpdates()
 {
     global $db, $repository;
     debug("object updates started");
     $list = $db->getAll("SELECT * FROM sotf_to_update");
     while (list(, $item) = each($list)) {
         $db->begin(true);
         $tablename = $item['tablename'];
         $rowId = $item['row_id'];
         debug("to_update", "{$tablename}, {$rowId}");
         switch ($tablename) {
             case 'ratingUpdate':
                 $rating = new sotf_Rating();
                 $rating->updateInstant($rowId);
                 break;
             case 'sotf_stats':
                 $obj = new sotf_Statistics($rowId);
                 if ($obj->exists()) {
                     $obj->updateStats();
                 }
                 break;
             case 'updateMeta':
                 $obj = $repository->getObject($rowId);
                 if (is_object($obj)) {
                     $obj->saveMetadataFile();
                 }
                 break;
             default:
                 logError("Unknown to_update type: " . $tablename);
         }
         $db->query("DELETE FROM sotf_to_update WHERE tablename='{$tablename}' AND row_id='{$rowId}'");
         $db->commit();
     }
     debug("object updates finished");
 }