Exemple #1
0
int run(void)
{
#ifdef USE_ST
  st_usleep(1); //force context switch so timers will work
#endif
  g_hash_table_foreach(hash, create_q_threads, NULL);
#ifdef USE_ST
  if (debug > 3) { LOG(LOG_DEBUG, "waiting for all threads to finish"); }
  while (thread_count) {
    st_usleep(10000); /* 10 ms */
  }
#endif
  if (HAVE_OPT(HANGUPSCRIPT) && online) {
    int status;

    status = system(OPT_ARG(HANGUPSCRIPT));
    if (WIFEXITED(status)) {
      if (WEXITSTATUS(status) != 0) {
        LOG(LOG_WARNING, "%s: error %d", OPT_ARG(HANGUPSCRIPT), WEXITSTATUS(status));
      }
    } else {
      LOG(LOG_ERR, "%s exited abnormally", OPT_ARG(HANGUPSCRIPT));
    }
  }
  online = FALSE;
  uw_setproctitle("sleeping");
  return 0;
}
int SrsThread::start()
{
    int ret = ERROR_SUCCESS;
    
    if(tid) {
        srs_info("thread already running.");
        return ret;
    }
    
    if((tid = st_thread_create(thread_fun, this, (_joinable? 1:0), 0)) == NULL){
        ret = ERROR_ST_CREATE_CYCLE_THREAD;
        srs_error("st_thread_create failed. ret=%d", ret);
        return ret;
    }
    
    // we set to loop to true for thread to run.
    loop = true;
    
    // wait for cid to ready, for parent thread to get the cid.
    while (_cid < 0 && loop) {
        st_usleep(10 * 1000);
    }
    
    // now, cycle thread can run.
    can_run = true;
    
    return ret;
}
void
producer(void * d)
{
  printf("producer =%d\n",(int)d);
  while(1)
  {    
    while(count>=MAX_COUNT)
    {
      printf("=>wait produce=%d count=%d\n",(int)d,count);
      st_usleep(1000 * 100);
    }
    count++;
    printf("=>produce=%d count=%d\n",(int)d,count);
    st_usleep(1000 * 100);    
  }
}
int SrsServer::do_cycle()
{
    int ret = ERROR_SUCCESS;
    
    // find the max loop
    int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);
    max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES);
    
    // the deamon thread, update the time cache
    while (true) {
        for (int i = 1; i < max + 1; i++) {
            st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
        
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
// if user interrupt the program, exit to check mem leak.
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_AUTO_GPERF_MC
            if (signal_gmc_stop) {
                srs_warn("gmc got singal to stop server.");
                return ret;
            }
#endif
        
            if (signal_reload) {
                signal_reload = false;
                srs_info("get signal reload, to reload the config.");
                
                if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
                    srs_error("reload config failed. ret=%d", ret);
                    return ret;
                }
                srs_trace("reload config success.");
            }
            
            // update the cache time or rusage.
            if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) {
                srs_update_system_time_ms();
            }
            if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) {
                srs_update_system_rusage();
            }
            if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) {
                srs_update_proc_stat();
            }
            if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) {
                srs_update_meminfo();
            }
            if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) {
                srs_update_platform_info();
            }
        }
    }

    return ret;
}
void SrsEncoder::encoder_cycle()
{
	int ret = ERROR_SUCCESS;
	
	log_context->generate_id();
	srs_trace("encoder cycle start");
	
	while (loop) {
		if ((ret = cycle()) != ERROR_SUCCESS) {
			srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret);
		} else {
			srs_info("encoder cycle success, retry");
		}
		
		if (!loop) {
			break;
		}
		
		st_usleep(SRS_ENCODER_SLEEP_MS * 1000);
	}
	
	// kill ffmpeg when finished and it alive
	std::vector<SrsFFMPEG*>::iterator it;
	for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) {
		SrsFFMPEG* ffmpeg = *it;
		ffmpeg->stop();
	}
	
	srs_trace("encoder cycle finished");
}
Exemple #6
0
 void SrsThread::dispose()
 {
     if (disposed) {
         return;
     }
     
     // the interrupt will cause the socket to read/write error,
     // which will terminate the cycle thread.
     st_thread_interrupt(tid);
     
     // when joinable, wait util quit.
     if (_joinable) {
         // wait the thread to exit.
         int ret = st_thread_join(tid, NULL);
         if (ret) {
             srs_warn("core: ignore join thread failed.");
         }
     }
     
     // wait the thread actually terminated.
     // sometimes the thread join return -1, for example,
     // when thread use st_recvfrom, the thread join return -1.
     // so here, we use a variable to ensure the thread stopped.
     // @remark even the thread not joinable, we must ensure the thread stopped when stop.
     while (!really_terminated) {
         st_usleep(10 * 1000);
         
         if (really_terminated) {
             break;
         }
         srs_warn("core: wait thread to actually terminated");
     }
     
     disposed = true;
 }
void
consumer(void * d)
{
  printf("consumer =%d\n",(int)d);
  while(1)
  {
    while(0 >= count)
    {
      printf("<=========wait consumer=%d count=%d\n",(int)d,count);
      st_usleep(1000 * 100);
    }
    count--;
    printf("<=========consumer=%d count=%d\n",(int)d,count);
    st_usleep(1000 * 100);    
  }
}
void SrsThread::thread_cycle()
{
    int ret = ERROR_SUCCESS;
    
    _srs_context->generate_id();
    srs_info("thread cycle start");
    
    _cid = _srs_context->get_id();
    
    srs_assert(handler);
    handler->on_thread_start();
    
    // wait for cid to ready, for parent thread to get the cid.
    while (!can_run && loop) {
        st_usleep(10 * 1000);
    }
    
    while (loop) {
        if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
            srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
            goto failed;
        }
        srs_info("thread on before cycle success");
        
        if ((ret = handler->cycle()) != ERROR_SUCCESS) {
            srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
            goto failed;
        }
        srs_info("thread cycle success");
        
        if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
            srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
            goto failed;
        }
        srs_info("thread on end cycle success");

failed:
        if (!loop) {
            break;
        }
        
        st_usleep(cycle_interval_us);
    }
    
    handler->on_thread_stop();
    srs_info("thread cycle finished");
}
Exemple #9
0
void run_actual_probes(void)
{
  thread_count = 0;
  st_usleep(1); //force context switch so timers will work
  g_hash_table_foreach(cache, add_probe, NULL);
  while (thread_count) {
    st_sleep(1);
  }
}
Exemple #10
0
void *_queue_worker(void *arg) {
  struct rpc_queue *queue;
  queue = (struct rpc_queue*)arg;
  arg = NULL;
  struct rpc_package_head *head;

  for (; ; st_usleep(10)) {
    if (worker_thread_count < 1000 && queue->count > 0) {
      head = queue_get(queue);
      assert(head != NULL);

      st_thread_create(_peer_task_worker, head, 0, 0);

      worker_thread_count ++;
    }
  }
}
Exemple #11
0
static void *read_queue(void *data)
{
  struct q_info *q = (struct q_info *)data;
extern int forever;
static char path[PATH_MAX];
  G_CONST_RETURN gchar *filename;
  GDir *dir;
 
  q->fatal = 0;
  //sprintf(path, "%s/%s/new", OPT_ARG(SPOOLDIR), q->name);
  strcpy(path, OPT_ARG(SPOOLDIR));
  strcat(path, "/");
  strcat(path, q->name);
  strcat(path, "/new");
  if (debug > 3) { LOG(LOG_DEBUG, "reading queue %s", path); }
  dir = g_dir_open (path, 0, NULL);
  while ((filename = g_dir_read_name(dir)) != NULL && !q->fatal && forever) {
    char buffer[PATH_MAX];
    struct thr_data *td;
 
    sprintf(buffer, "%s/%s", path, filename);
    td = g_malloc0(sizeof(struct thr_data));
    td->q = q;
    td->filename = strdup(buffer);
#ifdef USE_ST
    if (st_thread_create(push, td, 0, 0) == NULL) { 
      LOG(LOG_WARNING, "couldn't create thread");
      st_sleep(1);
    } else {
      q->thread_count++;
      thread_count++;
    }
    while (q->thread_count >= q->maxthreads) {
      st_usleep(10000); /* 10 ms */
    }
#else
    push(td);
#endif
  }
  g_dir_close(dir);
#ifdef USE_ST
  thread_count--;
#endif
  return NULL;
}
int SrsEdgeIngester::ingest()
{
    int ret = ERROR_SUCCESS;
    
    client->set_recv_timeout(SRS_EDGE_INGESTER_TIMEOUT_US);
    
    SrsPithyPrint pithy_print(SRS_CONSTS_STAGE_EDGE);

    while (pthread->can_loop()) {
        // switch to other st-threads.
        st_usleep(0);
        
        pithy_print.elapse();
        
        // pithy print
        if (pithy_print.can_print()) {
            kbps->sample();
            srs_trace("<- "SRS_CONSTS_LOG_EDGE_PLAY
                " time=%"PRId64", okbps=%d,%d,%d, ikbps=%d,%d,%d", 
                pithy_print.age(),
                kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(),
                kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m());
        }

        // read from client.
        SrsMessage* msg = NULL;
        if ((ret = client->recv_message(&msg)) != ERROR_SUCCESS) {
            if (!srs_is_client_gracefully_close(ret)) {
                srs_error("pull origin server message failed. ret=%d", ret);
            }
            return ret;
        }
        srs_verbose("edge loop recv message. ret=%d", ret);
        
        srs_assert(msg);
        SrsAutoFree(SrsMessage, msg);
        
        if ((ret = process_publish_message(msg)) != ERROR_SUCCESS) {
            return ret;
        }
    }
    
    return ret;
}
int SrsServer::cycle()
{
    int ret = ERROR_SUCCESS;

    ret = do_cycle();

#ifdef SRS_AUTO_GPERF_MC
    destroy();
    
    srs_warn("sleep a long time for system st-threads to cleanup.");
    st_usleep(3 * 1000 * 1000);
    srs_warn("system quit");
#else
    srs_warn("main cycle terminated, system quit normally.");
    exit(0);
#endif
    
    return ret;
}
void SrsThread::thread_cycle()
{
	int ret = ERROR_SUCCESS;
	
	srs_assert(handler);
	
	log_context->generate_id();
	srs_trace("thread cycle start");

	handler->on_end_cycle();
	
	loop = true;
	while (loop) {
		if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
			srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
			goto failed;
		}
		srs_info("thread on before cycle success");
		
		if ((ret = handler->cycle()) != ERROR_SUCCESS) {
			srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
			goto failed;
		}
		srs_info("thread cycle success");
		
		if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
			srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
			goto failed;
		}
		srs_info("thread on end cycle success");

failed:
		if (!loop) {
			break;
		}
		
		st_usleep(cycle_interval_us);
	}
	
	handler->on_leave_loop();
	srs_trace("thread cycle finished");
}
// function called by the increment thread
// increments the counter, prints the current value, and then
// sleeps for some time.
void *increment_thread_func(void *s) {
	ThreadInit *init = s; // cast the void pointer to keep compiler happy
	
	int num_inc;

	for (num_inc = 0; num_inc < DEFAULT_NUM_ITERS; num_inc++) {
		// decrement the semaphore
		down(init->bin_sem);
	 	// dereference the value pointer, then increment it
		(*(init->value_ptr))++;
		// print the current value
		fprintf(init->output_stream, "%d\n", (*(init->value_ptr)));
		fflush(init->output_stream);
		// increment the semaphore
		up(init->bin_sem);
		// wait some time
		st_usleep(INC_SLEEP_TIME);
	}
	// all done - thread exits
	st_thread_exit(NULL);
}
int SrsServer::cycle()
{
    int ret = ERROR_SUCCESS;
    
    // the deamon thread, update the time cache
    while (true) {
        st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
        srs_update_system_time_ms();
        
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
// if user interrupt the program, exit to check mem leak.
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_GPERF_MC
        if (signal_gmc_stop) {
            break;
        }
#endif
        
        if (signal_reload) {
            signal_reload = false;
            srs_info("get signal reload, to reload the config.");
            
            if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
                srs_error("reload config failed. ret=%d", ret);
                return ret;
            }
            srs_trace("reload config success.");
        }
    }

#ifdef SRS_INGEST
    ingester->stop();
#endif
    
    return ret;
}
Exemple #17
0
/**
 * More precise sleep()
 *
 * Portable usleep() function.
 * \param delay the amount of time to sleep
 */
void msleep( mtime_t delay )
{
#if defined( HAVE_KERNEL_OS_H )
    snooze( delay );

#elif defined( PTH_INIT_IN_PTH_H )
    pth_usleep( delay );

#elif defined( ST_INIT_IN_ST_H )
    st_usleep( delay );

#elif defined( WIN32 ) || defined( UNDER_CE )
    Sleep( (int) (delay / 1000) );

#elif defined( HAVE_NANOSLEEP )
    struct timespec ts_delay;

    ts_delay.tv_sec = delay / 1000000;
    ts_delay.tv_nsec = (delay % 1000000) * 1000;

    nanosleep( &ts_delay, NULL );

#else
    struct timeval tv_delay;

    tv_delay.tv_sec = delay / 1000000;
    tv_delay.tv_usec = delay % 1000000;

    /* select() return value should be tested, since several possible errors
     * can occur. However, they should only happen in very particular occasions
     * (i.e. when a signal is sent to the thread, or when memory is full), and
     * can be ignored. */
    select( 0, NULL, NULL, NULL, &tv_delay );

#endif
}
int SrsServer::do_cycle()
{
    int ret = ERROR_SUCCESS;
    
    // find the max loop
    int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);
    max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_DISK_STAT_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES);
    max = srs_max(max, SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES);
    
    // the deamon thread, update the time cache
    while (true) {
        // the interval in config.
        int heartbeat_max_resolution = (int)(_srs_config->get_heartbeat_interval() / 100);
        
        // dynamic fetch the max.
        int __max = max;
        __max = srs_max(__max, heartbeat_max_resolution);
        
        for (int i = 0; i < __max; i++) {
            st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
        
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
// if user interrupt the program, exit to check mem leak.
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_AUTO_GPERF_MC
            if (signal_gmc_stop) {
                srs_warn("gmc got singal to stop server.");
                return ret;
            }
#endif
        
            if (signal_reload) {
                signal_reload = false;
                srs_info("get signal reload, to reload the config.");
                
                if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
                    srs_error("reload config failed. ret=%d", ret);
                    return ret;
                }
                srs_trace("reload config success.");
            }
            
            // update the cache time or rusage.
            if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) {
                srs_info("update current time cache.");
                srs_update_system_time_ms();
            }
            if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) {
                srs_info("update resource info, rss.");
                srs_update_system_rusage();
            }
            if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) {
                srs_info("update cpu info, cpu usage.");
                srs_update_proc_stat();
            }
            if ((i % SRS_SYS_DISK_STAT_RESOLUTION_TIMES) == 0) {
                srs_info("update disk info, disk iops.");
                srs_update_disk_stat();
            }
            if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) {
                srs_info("update memory info, usage/free.");
                srs_update_meminfo();
            }
            if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) {
                srs_info("update platform info, uptime/load.");
                srs_update_platform_info();
            }
            if ((i % SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES) == 0) {
                srs_info("update network devices info.");
                srs_update_network_devices();
            }
            if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) {
                srs_info("update network rtmp server info.");
                resample_kbps(NULL);
                srs_update_rtmp_server((int)conns.size(), kbps);
            }
#ifdef SRS_AUTO_HTTP_PARSER
            if (_srs_config->get_heartbeat_enabled()) {
                if ((i % heartbeat_max_resolution) == 0) {
                    srs_info("do http heartbeat, for internal server to report.");
                    http_heartbeat->heartbeat();
                }
            }
#endif
            srs_info("server main thread loop");
        }
    }

    return ret;
}
int SrsForwarder::forward()
{
    int ret = ERROR_SUCCESS;
    
    client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
    
    SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);

    SrsSharedPtrMessageArray msgs(SYS_MAX_FORWARD_SEND_MSGS);
    
    while (pthread->can_loop()) {
        // switch to other st-threads.
        st_usleep(0);

        pithy_print.elapse();

        // read from client.
        if (true) {
            SrsMessage* msg = NULL;
            ret = client->recv_message(&msg);
            
            srs_verbose("play loop recv message. ret=%d", ret);
            if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
                srs_error("recv server control message failed. ret=%d", ret);
                return ret;
            }
            
            srs_freep(msg);
        }
        
        // forward all messages.
        int count = 0;
        if ((ret = queue->dump_packets(msgs.size, msgs.msgs, count)) != ERROR_SUCCESS) {
            srs_error("get message to forward failed. ret=%d", ret);
            return ret;
        }
        
        // pithy print
        if (pithy_print.can_print()) {
            kbps->sample();
            srs_trace("-> "SRS_LOG_ID_FOWARDER
                " time=%"PRId64", msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d", 
                pithy_print.age(), count,
                kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(),
                kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m());
        }
        
        // ignore when no messages.
        if (count <= 0) {
            srs_verbose("no packets to forward.");
            continue;
        }
    
        // all msgs to forward.
        // @remark, becareful, all msgs must be free explicitly,
        //      free by send_and_free_message or srs_freep.
        for (int i = 0; i < count; i++) {
            SrsSharedPtrMessage* msg = msgs.msgs[i];
            
            srs_assert(msg);
            msgs.msgs[i] = NULL;
            
            if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) {
                srs_error("forwarder send message to server failed. ret=%d", ret);
                return ret;
            }
        }
    }
    
    return ret;
}
Exemple #20
0
 void SrsThread::thread_cycle()
 {
     int ret = ERROR_SUCCESS;
     
     _srs_context->generate_id();
     srs_info("thread %s cycle start", _name);
     
     _cid = _srs_context->get_id();
     
     srs_assert(handler);
     handler->on_thread_start();
     
     // thread is running now.
     really_terminated = false;
     
     // wait for cid to ready, for parent thread to get the cid.
     while (!can_run && loop) {
         st_usleep(10 * 1000);
     }
     
     while (loop) {
         if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
             srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret);
             goto failed;
         }
         srs_info("thread %s on before cycle success");
         
         if ((ret = handler->cycle()) != ERROR_SUCCESS) {
             if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) {
                 srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret);
             }
             goto failed;
         }
         srs_info("thread %s cycle success", _name);
         
         if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
             srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret);
             goto failed;
         }
         srs_info("thread %s on end cycle success", _name);
         
     failed:
         if (!loop) {
             break;
         }
         
         // to improve performance, donot sleep when interval is zero.
         // @see: https://github.com/ossrs/srs/issues/237
         if (cycle_interval_us != 0) {
             st_usleep(cycle_interval_us);
         }
     }
     
     // readly terminated now.
     really_terminated = true;
     
     // when thread terminated normally, also disposed.
     // we must set to disposed before the on_thread_stop, which may free the thread.
     // @see https://github.com/ossrs/srs/issues/546
     disposed = true;
     
     handler->on_thread_stop();
     srs_info("thread %s cycle finished", _name);
 }
Exemple #21
0
int st_sleep(int secs)
{
  return st_usleep((secs >= 0) ? secs * (st_utime_t) 1000000LL :
				 ST_UTIME_NO_TIMEOUT);
}
int SrsForwarder::forward()
{
    int ret = ERROR_SUCCESS;
    
    client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
    
    SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);

    while (pthread->can_loop()) {
        // switch to other st-threads.
        st_usleep(0);

        // read from client.
        if (true) {
            SrsCommonMessage* msg = NULL;
            ret = client->recv_message(&msg);
            
            srs_verbose("play loop recv message. ret=%d", ret);
            if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
                srs_error("recv server control message failed. ret=%d", ret);
                return ret;
            }
        }
        
        // forward all messages.
        int count = 0;
        SrsSharedPtrMessage** msgs = NULL;
        if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
            srs_error("get message to forward failed. ret=%d", ret);
            return ret;
        }
        
        // ignore when no messages.
        if (count <= 0) {
            srs_verbose("no packets to forward.");
            continue;
        }
        SrsAutoFree(SrsSharedPtrMessage*, msgs, true);

        // pithy print
        pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
        if (pithy_print.can_print()) {
            srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", 
                pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
        }
    
        // all msgs to forward.
        for (int i = 0; i < count; i++) {
            SrsSharedPtrMessage* msg = msgs[i];
            
            srs_assert(msg);
            msgs[i] = NULL;
            
            if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
                srs_error("forwarder send message to server failed. ret=%d", ret);
                return ret;
            }
        }
    }
    
    return ret;
}
int SrsEdgeForwarder::cycle()
{
    int ret = ERROR_SUCCESS;
    
    client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
    
    SrsPithyPrint pithy_print(SRS_STAGE_EDGE);

    while (pthread->can_loop()) {
        // switch to other st-threads.
        st_usleep(0);
        
        if (send_error_code != ERROR_SUCCESS) {
            st_usleep(SRS_EDGE_FORWARDER_ERROR_US);
            continue;
        }

        // read from client.
        if (true) {
            SrsMessage* msg = NULL;
            ret = client->recv_message(&msg);
            
            srs_verbose("edge loop recv message. ret=%d", ret);
            if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
                srs_error("edge forwarder recv server control message failed. ret=%d", ret);
                send_error_code = ret;
                continue;
            }
            
            srs_freep(msg);
        }
        
        // forward all messages.
        int count = 0;
        SrsSharedPtrMessage** msgs = NULL;
        if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
            srs_error("get message to forward to origin failed. ret=%d", ret);
            return ret;
        }
        
        pithy_print.elapse();
        
        // pithy print
        if (pithy_print.can_print()) {
            kbps->sample();
            srs_trace("-> "SRS_LOG_ID_EDGE_PUBLISH
                " time=%"PRId64", msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d", 
                pithy_print.age(), count,
                kbps->get_send_kbps(), kbps->get_send_kbps_sample_high(), kbps->get_send_kbps_sample_medium(),
                kbps->get_recv_kbps(), kbps->get_recv_kbps_sample_high(), kbps->get_recv_kbps_sample_medium());
        }
        
        // ignore when no messages.
        if (count <= 0) {
            srs_verbose("no packets to forward.");
            continue;
        }
        SrsAutoFreeArray(SrsSharedPtrMessage, msgs, count);
    
        // all msgs to forward to origin.
        // @remark, becareful, all msgs must be free explicitly,
        //      free by send_and_free_message or srs_freep.
        for (int i = 0; i < count; i++) {
            SrsSharedPtrMessage* msg = msgs[i];
            
            srs_assert(msg);
            msgs[i] = NULL;
            
            if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) {
                srs_error("edge publish forwarder send message to server failed. ret=%d", ret);
                return ret;
            }
        }
    }
    
    return ret;
}
Exemple #24
0
/**
 * Wait for a date
 *
 * This function uses select() and an system date function to wake up at a
 * precise date. It should be used for process synchronization. If current date
 * is posterior to wished date, the function returns immediately.
 * \param date The date to wake up at
 */
void mwait( mtime_t date )
{
#if defined( HAVE_KERNEL_OS_H )
    mtime_t delay;

    delay = date - real_time_clock_usecs();
    if( delay <= 0 )
    {
        return;
    }
    snooze( delay );

#elif defined( WIN32 ) || defined( UNDER_CE )
    mtime_t usec_time, delay;

    usec_time = mdate();
    delay = date - usec_time;
    if( delay <= 0 )
    {
        return;
    }
    msleep( delay );

#else

    struct timeval tv_date;
    mtime_t        delay;          /* delay in msec, signed to detect errors */

    /* see mdate() about gettimeofday() possible errors */
    gettimeofday( &tv_date, NULL );

    /* calculate delay and check if current date is before wished date */
    delay = date - (mtime_t) tv_date.tv_sec * 1000000
                 - (mtime_t) tv_date.tv_usec
                 - 10000;

    /* Linux/i386 has a granularity of 10 ms. It's better to be in advance
     * than to be late. */
    if( delay <= 0 )                 /* wished date is now or already passed */
    {
        return;
    }

#   if defined( PTH_INIT_IN_PTH_H )
    pth_usleep( delay );

#   elif defined( ST_INIT_IN_ST_H )
    st_usleep( delay );

#   else

#       if defined( HAVE_NANOSLEEP )
    {
        struct timespec ts_delay;
        ts_delay.tv_sec = delay / 1000000;
        ts_delay.tv_nsec = (delay % 1000000) * 1000;

        nanosleep( &ts_delay, NULL );
    }

#       else
    tv_date.tv_sec = delay / 1000000;
    tv_date.tv_usec = delay % 1000000;
    /* see msleep() about select() errors */
    select( 0, NULL, NULL, NULL, &tv_date );
#       endif

#   endif

#endif
}