Move out of alloc_algo code modifying the data model

This way the alloc_algo() becomes idempotent, simplifying implementation
of new alloc_algos as well as rolling back if allocation fails (for
instance because some resource is exhausted at the time).

For now the code applying the results is moved to tbf::alloc_algo(), but
it will eventually get out of tbf code, so that the MS object is
responsible for running it. As a result, there's no even need to create
TBF object before trying to allocate resources, which will help furher in
rollback operations described above.

Change-Id: I5ffd00f5f80bde4b73b78db44896f65e70e12b20
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index cb01222..4af9ae6 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -418,6 +418,28 @@
 	return create_dl_acked_block(fn, pdch, bsn, bsn2);
 }
 
+void gprs_rlcmac_dl_tbf::apply_allocated_resources(const struct alloc_resources_res *res)
+{
+	uint8_t ts;
+
+	this->trx = res->trx;
+	this->upgrade_to_multislot = res->upgrade_to_multislot;
+
+	for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) {
+		struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts];
+		OSMO_ASSERT(!this->pdch[pdch->ts_no]);
+		if (!(res->ass_slots_mask & (1 << ts)))
+			continue;
+		LOGPTBFDL(this, LOGL_DEBUG, "Assigning TS=%u TFI=%d\n",
+			  ts, res->tfi);
+
+		this->m_tfi = res->tfi;
+
+		this->pdch[pdch->ts_no] = pdch;
+		pdch->attach_tbf(this);
+	}
+}
+
 /* old_tbf (UL TBF or DL TBF) will send a Pkt Dl Ass on PACCH to assign tbf.
  * Note: It is possible that "tbf == old_tbf" if the TBF is being updated. This can
  * happen when we first assign over PCH (only single slot is possible) and we want
@@ -472,9 +494,8 @@
 		.direction = tbf_direction(tbf),
 		.single = false,
 		.use_trx = -1,
-		.tbf = tbf,
 	};
-	rc = the_pcu->alloc_algorithm(&req);
+	rc = dl_tbf->alloc_algorithm(&req);
 	/* if no resource */
 	if (rc < 0) {
 		LOGPTBFDL(dl_tbf, LOGL_ERROR, "No resources allocated during upgrade to multislot!\n");