Example #1
0
void * request(DfaSet * dfaSet, state_name start_state, char * recipient_addr, state_machine_id recipient_machine_id, Message * message) {
  StateMachine * initial_sm;
  state_machine_id machine_id;
  void * ret;
  writelock(dfaSet->lock, 600);

  initial_sm = allocSmash(dfaSet->smash);
  if(initial_sm == NULL) {
    return NULL;
  }

  assert(start_state != NULL_STATE);
  
  if(message != NULL) {
    
    memcpy(&(initial_sm->message), message, sizeof(Message));
  }
  
  initial_sm->current_state = start_state;
  initial_sm->message.from_machine_id = initial_sm->machine_id;
  initial_sm->message.to_machine_id = recipient_machine_id;
  initial_sm->message.type = start_state;

  char * initiator;
  {
    int err = asprintf(&initiator, "%s:%d", dfaSet->networkSetup.localhost, dfaSet->networkSetup.localport);
    assert(err != -1);
  }
  strcpy(initial_sm->message.initiator, initiator);
  free(initiator);
  //  printf("Set message initiator to %s\n", initial_sm->message.initiator); fflush(stdout);
  initial_sm->message.initiator_machine_id = initial_sm->machine_id;

  strcpy(initial_sm->message_recipient, recipient_addr);
  machine_id = initial_sm->machine_id;
  writeunlock(dfaSet->lock);

  ret = run_request(dfaSet, machine_id);

  writelock(dfaSet->lock, machine_id); 
  assert(initial_sm == getSmash(dfaSet->smash, machine_id));
  if(message != NULL) {

    memcpy(message, &(initial_sm->message), sizeof(Message));
  }

  freeSmash(dfaSet->smash, initial_sm->machine_id);
  writeunlock(dfaSet->lock);

  return ret;
}
Example #2
0
void * worker_loop(void * arg_void) {

  WorkerLoopArgs * arg = arg_void;
  
  StateMachine * stateMachine;
  DfaSet * dfaSet = arg->dfaSet;
  state_machine_id machine_id = arg->machine_id;
  readlock(dfaSet->lock, machine_id);

  DEBUG("Worker loop: %ld\n", machine_id);
  
  stateMachine = getSmash(dfaSet->smash, machine_id);

  assert(stateMachine->machine_id == machine_id);

  if(pthread_detach(stateMachine->worker_thread) != 0) {
    perror("pthread_detach");
  }

  readunlock(dfaSet->lock);
  inner_worker_loop(arg_void);

  writelock(dfaSet->lock, machine_id); 
  DEBUG("Freeing machine %ld\n", machine_id);

  freeSmash(dfaSet->smash, machine_id);
  writeunlock(dfaSet->lock);

  return 0;
}
Example #3
0
void *writer (void *args)
{
    rwargs *a = static_cast<rwargs *>(args);

    for (int i = 2; i < MAXCOUNT; ++i)
    {
        writelock (a->lock, a->id);
        data = i;
        usleep (a->delay);
        writeunlock (a->lock);
        RPMS_DEBUG( LOGNAME, "Writer " + rpms::convert<std::string>(a->id) + ": Wrote " + rpms::convert<std::string>(i));
        usleep (a->delay);
    }
    RPMS_DEBUG( LOGNAME, "Writer " + rpms::convert<std::string>(a->id) + ": finishing... " );
    writelock (a->lock, a->id);
    data = 0;
    writeunlock (a->lock);
    RPMS_DEBUG( LOGNAME, "Writer " + rpms::convert<std::string>(a->id) + ": finished" );

    return 0;
}
Example #4
0
static int stasis_log_impl_in_memory_truncate(stasis_log_t * log, lsn_t lsn) {
  stasis_log_impl_in_memory * impl = log->impl;
  writelock(impl->flushedLSN_lock,1);
  writelock(impl->globalOffset_lock,1);

  assert(lsn <= impl->nextAvailableLSN);


  if(lsn > impl->globalOffset) {
    for(int i = impl->globalOffset; i < lsn; i++) {
      free(impl->buffer[i - impl->globalOffset]);
    }
    assert((lsn-impl->globalOffset) + (impl->nextAvailableLSN -lsn) <= impl->bufferLen);
    memmove(&(impl->buffer[0]), &(impl->buffer[lsn - impl->globalOffset]),
			sizeof(LogEntry*) * (impl->nextAvailableLSN - lsn));
    impl->globalOffset = lsn;
  }

  writeunlock(impl->globalOffset_lock);
  writeunlock(impl->flushedLSN_lock);

  return 0;
}
Example #5
0
int dfa_reinitialize(DfaSet *dfaSet, char * localhost,
	      Transition transitions[], int transition_count, 
	      State states[], state_name state_count) {

  dfaSet->lock = initlock();
  dfaSet->states = states;
  dfaSet->state_count = state_count;
  dfaSet->transitions = transitions;
  dfaSet->transition_count = transition_count;

  if(init_network_broadcast(&(dfaSet->networkSetup), dfaSet->networkSetup.localport, localhost,
			    dfaSet->networkSetup.broadcast_lists,
			    dfaSet->networkSetup.broadcast_lists_count,
			    dfaSet->networkSetup.broadcast_list_host_count) < 0) {
    return -1;
  }
  writelock(dfaSet->lock, 100);
  recover(dfaSet);
  writeunlock(dfaSet->lock);

  return 0;

}
Example #6
0
void* main_loop(DfaSet *dfaSet) {

  Message * message = malloc(sizeof(Message));
  char * from = malloc(sizeof(char) * MAX_ADDRESS_LENGTH);
  NetworkSetup * networkSetup = malloc(sizeof(NetworkSetup));
  int recieved_message = 0;

  StateMachine * stateMachine;
  
  writelock(dfaSet->lock, 300);
  memcpy(networkSetup, &(dfaSet->networkSetup), sizeof(NetworkSetup));
  writeunlock(dfaSet->lock);

  /** @todo the locking scheme for this loop could be improved.  The loop assumes that 
	    pointers to existing state machines could be invalidated by unrelated threads, 
            and this forces it to hold a global write lock during processing. */
  
  while(1) {
    int i;
    state_name new_state, current_state;
    int new_machine = 0;

    /*Listen on socket... */
    if(recieved_message) {
      writeunlock(dfaSet->lock); 
      recieved_message = 0;
    }

    if(receive_message(networkSetup, message, from) <= 0) {
      continue;
    }

    recieved_message = 1;
    
    writelock(dfaSet->lock, 200);

    stateMachine = getSmash(dfaSet->smash, message->to_machine_id);
    DEBUG("Lookup %ld, ret = %d\n", message->to_machine_id, ret);

    /** @todo Check states to make sure they actually exist? */
    
    if(stateMachine == NULL) {
    
      DEBUG("Allocate machine %ld->", message->to_machine_id); fflush(NULL); 
      
      if(message->to_machine_id == NULL_MACHINE) {
	
	stateMachine = allocSmash(dfaSet->smash);
	
      } else {
	
	/* @todo: Check id. */	  
	stateMachine = insertSmash(dfaSet->smash, message->to_machine_id);
      }
      
      if(stateMachine == NULL) {
	fprintf(stderr, "Too many state machines.  Dropping request for new one.\n");
	continue;
      }
      
      new_machine = 1;

      stateMachine->worker_thread  = (pid_t)0;
      
      stateMachine->page      = NULL; 
      /* @todo libdfa doesn't use the 'conventional' null recordid, {0,0,-1} */
      stateMachine->page_id.page = 0; 
      stateMachine->page_id.slot = 0;
      stateMachine->page_id.size = 0;  
      
      current_state = NULL_STATE;
    } else {
      current_state = stateMachine->current_state;
    }
    
    new_state = current_state; 
    
    /* Find the appropriate transition */

    assert(message->to_machine_id == stateMachine->machine_id  || message->to_machine_id == NULL_MACHINE);
    
    for(i = 0; i< dfaSet->transition_count; i++) {
      if(dfaSet->transitions[i].remote_state == message->type && 
	 dfaSet->transitions[i].pre_state    == current_state) { 
	
	break;
      }
    }
    
    if(i == dfaSet->transition_count) {
      
      fprintf(stderr, "%ld received: %ld-%d:%d->? (bad message from %s)\n",  stateMachine->machine_id, message->from_machine_id, 
	     message->type, current_state, from);
      continue;
      
    } 
    
    
    if(dfaSet->transitions[i].fcn_ptr == NULL) {
      
      new_state = dfaSet->transitions[i].post_state;
      
    } else {
      
      /* Evaluate callback -- This produces a new state, and
	 overwrites m with a new message for the state machine. */

      int ret = (dfaSet->transitions[i].fcn_ptr)(dfaSet, stateMachine, message, from);
      
      if (dfaSet->transitions[i].post_state == OVERRIDDEN_STATE) {
	if( ret != OVERRIDDEN_STATE) {
	  
	  new_state = ret;
	
	} /* else leave new_state alone; the transition failed. */
      } else if (ret) {
	
 	new_state = dfaSet->transitions[i].post_state;
	
      }
      
    }
    
    
    /* Update machine state. */
    
    if(new_state == NULL_STATE) {
      
      /* Time to de-allocate machine */ 
      
      if(stateMachine->worker_thread == (pid_t)0) {
	
	/* No worker thread, so just deallocate, and move on */

	freeSmash(dfaSet->smash, stateMachine->machine_id);
	continue;

      } else {
	
	/* NULL_STATE_TOMBSTONE tells the worker thread that it's
	   time to shut down.  (NULL_STATE is reserved by monoTree
	   for machines that have already been deleted..) */
	
	new_state = NULL_STATE_TOMBSTONE;
      }
      assert(!new_machine);
    }

    if(new_state != current_state) {
      
      DEBUG("%ld transitioned on: %ld-%d:%d->%d from %s\n", stateMachine->machine_id, message->from_machine_id, 
	     dfaSet->transitions[i].remote_state, dfaSet->transitions[i].pre_state, dfaSet->transitions[i].post_state, from); 
      DEBUG(" -> %d %ld\n", new_state, message->from_machine_id);

      assert(new_state != NULL_STATE);
      stateMachine->current_state = new_state;	
      stateMachine->last_transition = time(NULL);
      
      /* @todo Is this general enough?  The transition function is
	 able to overwrite both variables, so it should be
	 good enough. */
      
      memcpy(&(stateMachine->message_recipient), from, MAX_ADDRESS_LENGTH);
      memcpy(&(stateMachine->message), message, sizeof(Message));
      
      /* We don't want to just swap the sender and recipient,
	 since we might have just allocated this machine.  If not,
	 then the original message's recipient should be the
	 same as stateMachine->machine_id anyway. 
	 
	 At any rate, the transition function should overwrite
	 message->from_machine_id to change the machine that the
	 state machine will deal with.
	 
      */
      
      stateMachine->message.from_machine_id = stateMachine->machine_id;
      stateMachine->message.to_machine_id   = message->from_machine_id;
      
      if(dfaSet->transitions[i].force) {
	setSmash(dfaSet->smash, stateMachine->machine_id);
	forceSmash(dfaSet->smash); 
      }

      /* Fork or signal the process if there already is one. */
      
      if(stateMachine->worker_thread == (pthread_t)NULL) {
 	assert ((stateMachine->current_state != NULL_STATE) && 
 		(stateMachine->current_state != NULL_STATE_TOMBSTONE));

	stateMachine->worker_thread = spawn_worker_thread(dfaSet, stateMachine->machine_id);

      } else {
	// This was a broadcast, but was recently changed to signal for 
	// performance reasons.
	pthread_cond_signal(stateMachine->sleepCond);
      }
    }
  }
}