Zone Transfer

Zone Transfer

Zona ko'chirish

Zona ko'chirish (zone transfer) — asosiy DNS serveri o'zining barcha yozuvlarini (zonasini) zaxira serverga to'liq nusxalash jarayoni, shunda ikkalasi ham bir xil javob beradi. Zaxira server buni vaqti-vaqti bilan qaytaradi: yangi to'plamni oladi va uni o'zining eski nusxasi bilan birlashtiradi (merge).

Birlashtirish uchta holatni to'g'ri boshqarishi kerak: yangi to'plamda yangilangan yozuv (masalan, IP manzili o'zgargan) eskisining o'rnini bosishi kerak; yangi to'plamda bo'lmagan eski yozuv o'z joyida qolishi kerak; va yangi to'plamdagi butunlay yangi yozuv qo'shilishi kerak.

"Bu yozuv allaqachon bormi, agar bo'lsa qayerda?" degan savolga tez javob berish uchun, DNS Cache darsidagi kalitlash g'oyasidan (name + ":" + type) foydalanamiz — lekin bu safar qiymat sifatida emas, natija slice ichidagi indeksni saqlash uchun:

example.go
index := make(map[string]int) // "name:type" -> result ichidagi pozitsiya
result := make([]DNSRecord, len(existing))
copy(result, existing)
for i, r := range result {
	index[r.Name+":"+r.Type] = i
}

Endi yangi to'plam bo'ylab yurganda, har bir yozuv uchun uning kaliti allaqachon indexda bor-yo'qligini tekshirasiz: bor bo'lsa, o'sha pozitsiyadagi yozuvni yangisi bilan almashtirasiz (yangilanish); yo'q bo'lsa, yangi yozuvni oxiriga qo'shasiz (qo'shilish) va uning yangi pozitsiyasini ham indexga yozib qo'yasiz.

example.go
for _, r := range incoming {
	key := r.Name + ":" + r.Type
	if i, ok := index[key]; ok {
		result[i] = r // joyida yangilash
	} else {
		result = append(result, r) // yangi yozuv qo'shish
		index[key] = len(result) - 1
	}
}

copy(result, existing) — Slice Surgery darsida ko'rmagan, lekin oddiy o'rnatilgan funksiya: u ikkinchi slicening elementlarini birinchisiga nusxalaydi. Bu yerda u existingni butunlay o'zgartirmasdan, uning nusxasidan boshlash uchun ishlatiladi.

>_ Exercise

existingni incoming bilan birlashtirib, yangilangan zonani qaytaradigan MergeZone(existing, incoming []DNSRecord) []DNSRecord funksiyasini yozing.

Talablar

  • Agar incomingdagi yozuv existingdagi biror yozuv bilan bir xil Name va Typega ega bo'lsa, u eskisining o'rnini bosishi kerak (o'sha pozitsiyada)
  • incomingda mos kelmagan existing yozuvlar o'z joyida, o'zgarishsiz qolishi kerak
  • existingda mos kelmagan incoming yozuvlar natijaning oxiriga qo'shilishi kerak

Misol:

  • existing ikkita yozuvga ega: example.com A (eski IP) va example.com MX. incoming ikkita yozuvga ega: example.com A (yangi IP) va example.com TXT (yangi). Natija uchta yozuvdan iborat: yangilangan A, o'zgarishsiz MX, va qo'shilgan TXT.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Bir to'plamni ikkinchisi bilan kalit orqali birlashtirganda, map[string]int bilan har bir kalitning natija slicedagi pozitsiyasini kuzatib boring — shunda "yangilashmi yoki qo'shishmi" degan qarorni bitta comma-ok tekshiruvi bilan hal qilasiz.

NEXT UP

Dig Output

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Zone Transfer

Zona ko'chirish

Zona ko'chirish (zone transfer) — asosiy DNS serveri o'zining barcha yozuvlarini (zonasini) zaxira serverga to'liq nusxalash jarayoni, shunda ikkalasi ham bir xil javob beradi. Zaxira server buni vaqti-vaqti bilan qaytaradi: yangi to'plamni oladi va uni o'zining eski nusxasi bilan birlashtiradi (merge).

Birlashtirish uchta holatni to'g'ri boshqarishi kerak: yangi to'plamda yangilangan yozuv (masalan, IP manzili o'zgargan) eskisining o'rnini bosishi kerak; yangi to'plamda bo'lmagan eski yozuv o'z joyida qolishi kerak; va yangi to'plamdagi butunlay yangi yozuv qo'shilishi kerak.

"Bu yozuv allaqachon bormi, agar bo'lsa qayerda?" degan savolga tez javob berish uchun, DNS Cache darsidagi kalitlash g'oyasidan (name + ":" + type) foydalanamiz — lekin bu safar qiymat sifatida emas, natija slice ichidagi indeksni saqlash uchun:

example.go
index := make(map[string]int) // "name:type" -> result ichidagi pozitsiya
result := make([]DNSRecord, len(existing))
copy(result, existing)
for i, r := range result {
	index[r.Name+":"+r.Type] = i
}

Endi yangi to'plam bo'ylab yurganda, har bir yozuv uchun uning kaliti allaqachon indexda bor-yo'qligini tekshirasiz: bor bo'lsa, o'sha pozitsiyadagi yozuvni yangisi bilan almashtirasiz (yangilanish); yo'q bo'lsa, yangi yozuvni oxiriga qo'shasiz (qo'shilish) va uning yangi pozitsiyasini ham indexga yozib qo'yasiz.

example.go
for _, r := range incoming {
	key := r.Name + ":" + r.Type
	if i, ok := index[key]; ok {
		result[i] = r // joyida yangilash
	} else {
		result = append(result, r) // yangi yozuv qo'shish
		index[key] = len(result) - 1
	}
}

copy(result, existing) — Slice Surgery darsida ko'rmagan, lekin oddiy o'rnatilgan funksiya: u ikkinchi slicening elementlarini birinchisiga nusxalaydi. Bu yerda u existingni butunlay o'zgartirmasdan, uning nusxasidan boshlash uchun ishlatiladi.

>_ Exercise

existingni incoming bilan birlashtirib, yangilangan zonani qaytaradigan MergeZone(existing, incoming []DNSRecord) []DNSRecord funksiyasini yozing.

Talablar

  • Agar incomingdagi yozuv existingdagi biror yozuv bilan bir xil Name va Typega ega bo'lsa, u eskisining o'rnini bosishi kerak (o'sha pozitsiyada)
  • incomingda mos kelmagan existing yozuvlar o'z joyida, o'zgarishsiz qolishi kerak
  • existingda mos kelmagan incoming yozuvlar natijaning oxiriga qo'shilishi kerak

Misol:

  • existing ikkita yozuvga ega: example.com A (eski IP) va example.com MX. incoming ikkita yozuvga ega: example.com A (yangi IP) va example.com TXT (yangi). Natija uchta yozuvdan iborat: yangilangan A, o'zgarishsiz MX, va qo'shilgan TXT.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Bir to'plamni ikkinchisi bilan kalit orqali birlashtirganda, map[string]int bilan har bir kalitning natija slicedagi pozitsiyasini kuzatib boring — shunda "yangilashmi yoki qo'shishmi" degan qarorni bitta comma-ok tekshiruvi bilan hal qilasiz.

NEXT UP

Dig Output